diff --git a/build.sh b/build.sh index 2334e52..27e7439 100755 --- a/build.sh +++ b/build.sh @@ -9,7 +9,7 @@ DEPOT_TOOLS_DIR="$THIRD_PARTY_DIR/depot_tools" OS=$(go env GOOS) ARCH=$(go env GOARCH) CONFIG="Release" -COMMIT="f33698296719f956497d2dbff81b5080864a8804" # branch-heads/52 +COMMIT="c279861207c5b15fc51069e96595782350e0ac12" # branch-heads/58 INCLUDE_DIR="$PROJECT_DIR/include" LIB_DIR="$PROJECT_DIR/lib" @@ -57,6 +57,13 @@ else popd fi +if [ "$ARCH" = "arm" ]; then + echo "Manually fetching arm sysroot" + pushd $WEBRTC_SRC || exit 1 + ./build/linux/sysroot_scripts/install-sysroot.py --arch=arm || exit 1 + popd +fi + echo "Checking out latest tested / compatible version of webrtc ..." pushd $WEBRTC_SRC git checkout $COMMIT @@ -67,19 +74,15 @@ pushd $WEBRTC_SRC || exit 1 rm -rf out/$CONFIG popd -echo "Applying webrtc patches ..." -pushd $WEBRTC_SRC || exit 1 -for PATCH in build_at_webrtc_branch_heads_52.patch; do - git apply --check ${PROJECT_DIR}/webrtc_patches/${PATCH} || exit 1 - git am < ${PROJECT_DIR}/webrtc_patches/${PATCH} || exit 1 -done -popd - echo "Building webrtc ..." pushd $WEBRTC_SRC export GYP_DEFINES="include_tests=0 include_examples=0" -python webrtc/build/gyp_webrtc webrtc/api/api.gyp || exit 1 -ninja -C out/$CONFIG || exit 1 +if [ "$ARCH" = "arm" ]; then + gn gen out/$CONFIG --args='target_os="linux" target_cpu="arm" is_debug=false' || exit 1 +else + gn gen out/$CONFIG --args='is_debug=false' || exit 1 +fi +ninja -C out/$CONFIG webrtc webrtc/test webrtc/pc:pc_test_utils || exit 1 popd echo "Copying headers ..." @@ -92,15 +95,17 @@ do done popd pushd $PROJECT_DIR || exit 1 -git clean -fdx "$INCLUDE_DIR" +git clean -fd "$INCLUDE_DIR" popd echo "Concatenating libraries ..." pushd $WEBRTC_SRC/out/$CONFIG if [ "$OS" = "darwin" ]; then - ls *.a > filelist + find . -name '*.o' > filelist libtool -static -o libwebrtc-magic.a -filelist filelist strip -S -x -o libwebrtc-magic.a libwebrtc-magic.a +elif [ "$ARCH" = "arm" ]; then + arm-linux-gnueabihf-ar crs libwebrtc-magic.a $(find . -name '*.o' -not -name '*.main.o') else ar crs libwebrtc-magic.a $(find . -name '*.o' -not -name '*.main.o') fi diff --git a/datachannel.cc b/datachannel.cc index a9fa7fb..e411956 100644 --- a/datachannel.cc +++ b/datachannel.cc @@ -111,8 +111,24 @@ class FakeDataChannel : public DataChannelInterface { return state_; }; + virtual uint32_t messages_sent() const { + return 1234; + }; + + virtual uint64_t bytes_sent() const { + return 1234; + }; + + virtual uint32_t messages_received() const { + return 1234; + }; + + virtual uint64_t bytes_received() const { + return 1234; + }; + virtual uint64_t buffered_amount() const { - return 0; + return 1234; }; // Sends data to self. diff --git a/datachannel.hpp b/datachannel.hpp index 2a34533..440b695 100644 --- a/datachannel.hpp +++ b/datachannel.hpp @@ -2,6 +2,7 @@ #define _DATACHANNEL_H_ #include <_cgo_export.h> // Allow calling certain Go functions. +#include #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/api/datachannelinterface.h" diff --git a/datachannel_test.go b/datachannel_test.go index 16ed952..2d617cd 100644 --- a/datachannel_test.go +++ b/datachannel_test.go @@ -29,7 +29,7 @@ func TestDataStateEnums(t *testing.T) { So(c.MaxRetransmits(), ShouldEqual, 0) So(c.Negotiated(), ShouldBeFalse) So(c.ID(), ShouldEqual, 12345) - So(c.BufferedAmount(), ShouldEqual, 0) + So(c.BufferedAmount(), ShouldEqual, 1234) // There's not a good way to create a DataChannel without first having an // available PeerConnection object with a valid session, but that's part of diff --git a/include/webrtc/api/androidvideocapturer.h b/include/webrtc/api/androidvideocapturer.h deleted file mode 100644 index 4c73f31..0000000 --- a/include/webrtc/api/androidvideocapturer.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_ANDROIDVIDEOCAPTURER_H_ -#define WEBRTC_API_ANDROIDVIDEOCAPTURER_H_ - -#include -#include - -#include "webrtc/base/thread_checker.h" -#include "webrtc/common_video/include/video_frame_buffer.h" -#include "webrtc/media/base/videocapturer.h" - -namespace webrtc { - -class AndroidVideoCapturer; - -class AndroidVideoCapturerDelegate : public rtc::RefCountInterface { - public: - virtual ~AndroidVideoCapturerDelegate() {} - // Start capturing. The implementation of the delegate must call - // AndroidVideoCapturer::OnCapturerStarted with the result of this request. - virtual void Start(int width, int height, int framerate, - AndroidVideoCapturer* capturer) = 0; - - // Stops capturing. - // The delegate may not call into AndroidVideoCapturer after this call. - virtual void Stop() = 0; - - virtual std::vector GetSupportedFormats() = 0; -}; - -// Android implementation of cricket::VideoCapturer for use with WebRtc -// PeerConnection. -class AndroidVideoCapturer : public cricket::VideoCapturer { - public: - explicit AndroidVideoCapturer( - const rtc::scoped_refptr& delegate); - virtual ~AndroidVideoCapturer(); - - // Called from JNI when the capturer has been started. - void OnCapturerStarted(bool success); - - // Called from JNI when a new frame has been captured. - // Argument |buffer| is intentionally by value, for use with rtc::Bind. - void OnIncomingFrame( - const rtc::scoped_refptr& buffer, - int rotation, - int64_t time_stamp); - - // Called from JNI to request a new video format. - void OnOutputFormatRequest(int width, int height, int fps); - - AndroidVideoCapturerDelegate* delegate() { return delegate_.get(); } - - // cricket::VideoCapturer implementation. - bool GetBestCaptureFormat(const cricket::VideoFormat& desired, - cricket::VideoFormat* best_format) override; - - private: - // cricket::VideoCapturer implementation. - // Video frames will be delivered using - // cricket::VideoCapturer::SignalFrameCaptured on the thread that calls Start. - cricket::CaptureState Start( - const cricket::VideoFormat& capture_format) override; - void Stop() override; - bool IsRunning() override; - bool IsScreencast() const override { return false; } - bool GetPreferredFourccs(std::vector* fourccs) override; - - bool running_; - rtc::scoped_refptr delegate_; - - rtc::ThreadChecker thread_checker_; - - class FrameFactory; - FrameFactory* frame_factory_; // Owned by cricket::VideoCapturer. - - cricket::CaptureState current_state_; -}; - -} // namespace webrtc - -#endif // WEBRTC_API_ANDROIDVIDEOCAPTURER_H_ diff --git a/include/webrtc/api/audio/audio_mixer.h b/include/webrtc/api/audio/audio_mixer.h new file mode 100644 index 0000000..931f20e --- /dev/null +++ b/include/webrtc/api/audio/audio_mixer.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_AUDIO_AUDIO_MIXER_H_ +#define WEBRTC_API_AUDIO_AUDIO_MIXER_H_ + +#include + +#include "webrtc/base/refcount.h" +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { + +// WORK IN PROGRESS +// This class is under development and is not yet intended for for use outside +// of WebRtc/Libjingle. +class AudioMixer : public rtc::RefCountInterface { + public: + // A callback class that all mixer participants must inherit from/implement. + class Source { + public: + enum class AudioFrameInfo { + kNormal, // The samples in audio_frame are valid and should be used. + kMuted, // The samples in audio_frame should not be used, but + // should be implicitly interpreted as zero. Other + // fields in audio_frame may be read and should + // contain meaningful values. + kError, // The audio_frame will not be used. + }; + + // Overwrites |audio_frame|. The data_ field is overwritten with + // 10 ms of new audio (either 1 or 2 interleaved channels) at + // |sample_rate_hz|. All fields in |audio_frame| must be updated. + virtual AudioFrameInfo GetAudioFrameWithInfo(int sample_rate_hz, + AudioFrame* audio_frame) = 0; + + // A way for a mixer implementation to distinguish participants. + virtual int Ssrc() const = 0; + + // A way for this source to say that GetAudioFrameWithInfo called + // with this sample rate or higher will not cause quality loss. + virtual int PreferredSampleRate() const = 0; + + virtual ~Source() {} + }; + + // Returns true if adding was successful. A source is never added + // twice. Addition and removal can happen on different threads. + virtual bool AddSource(Source* audio_source) = 0; + + // Removal is never attempted if a source has not been successfully + // added to the mixer. + virtual void RemoveSource(Source* audio_source) = 0; + + // Performs mixing by asking registered audio sources for audio. The + // mixed result is placed in the provided AudioFrame. This method + // will only be called from a single thread. The channels argument + // specifies the number of channels of the mix result. The mixer + // should mix at a rate that doesn't cause quality loss of the + // sources' audio. The mixing rate is one of the rates listed in + // AudioProcessing::NativeRate. All fields in + // |audio_frame_for_mixing| must be updated. + virtual void Mix(size_t number_of_channels, + AudioFrame* audio_frame_for_mixing) = 0; + + protected: + // Since the mixer is reference counted, the destructor may be + // called from any thread. + ~AudioMixer() override {} +}; +} // namespace webrtc + +#endif // WEBRTC_API_AUDIO_AUDIO_MIXER_H_ diff --git a/include/webrtc/api/audio_codecs/audio_decoder.h b/include/webrtc/api/audio_codecs/audio_decoder.h new file mode 100644 index 0000000..dab7d3b --- /dev/null +++ b/include/webrtc/api/audio_codecs/audio_decoder.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_H_ +#define WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_H_ + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/buffer.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +class AudioDecoder { + public: + enum SpeechType { + kSpeech = 1, + kComfortNoise = 2, + }; + + // Used by PacketDuration below. Save the value -1 for errors. + enum { kNotImplemented = -2 }; + + AudioDecoder() = default; + virtual ~AudioDecoder() = default; + + class EncodedAudioFrame { + public: + struct DecodeResult { + size_t num_decoded_samples; + SpeechType speech_type; + }; + + virtual ~EncodedAudioFrame() = default; + + // Returns the duration in samples-per-channel of this audio frame. + // If no duration can be ascertained, returns zero. + virtual size_t Duration() const = 0; + + // Decodes this frame of audio and writes the result in |decoded|. + // |decoded| must be large enough to store as many samples as indicated by a + // call to Duration() . On success, returns an rtc::Optional containing the + // total number of samples across all channels, as well as whether the + // decoder produced comfort noise or speech. On failure, returns an empty + // rtc::Optional. Decode may be called at most once per frame object. + virtual rtc::Optional Decode( + rtc::ArrayView decoded) const = 0; + }; + + struct ParseResult { + ParseResult(); + ParseResult(uint32_t timestamp, + int priority, + std::unique_ptr frame); + ParseResult(ParseResult&& b); + ~ParseResult(); + + ParseResult& operator=(ParseResult&& b); + + // The timestamp of the frame is in samples per channel. + uint32_t timestamp; + // The relative priority of the frame compared to other frames of the same + // payload and the same timeframe. A higher value means a lower priority. + // The highest priority is zero - negative values are not allowed. + int priority; + std::unique_ptr frame; + }; + + // Let the decoder parse this payload and prepare zero or more decodable + // frames. Each frame must be between 10 ms and 120 ms long. The caller must + // ensure that the AudioDecoder object outlives any frame objects returned by + // this call. The decoder is free to swap or move the data from the |payload| + // buffer. |timestamp| is the input timestamp, in samples, corresponding to + // the start of the payload. + virtual std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp); + + // Decodes |encode_len| bytes from |encoded| and writes the result in + // |decoded|. The maximum bytes allowed to be written into |decoded| is + // |max_decoded_bytes|. Returns the total number of samples across all + // channels. If the decoder produced comfort noise, |speech_type| + // is set to kComfortNoise, otherwise it is kSpeech. The desired output + // sample rate is provided in |sample_rate_hz|, which must be valid for the + // codec at hand. + int Decode(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type); + + // Same as Decode(), but interfaces to the decoders redundant decode function. + // The default implementation simply calls the regular Decode() method. + int DecodeRedundant(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + size_t max_decoded_bytes, + int16_t* decoded, + SpeechType* speech_type); + + // Indicates if the decoder implements the DecodePlc method. + virtual bool HasDecodePlc() const; + + // Calls the packet-loss concealment of the decoder to update the state after + // one or several lost packets. The caller has to make sure that the + // memory allocated in |decoded| should accommodate |num_frames| frames. + virtual size_t DecodePlc(size_t num_frames, int16_t* decoded); + + // Resets the decoder state (empty buffers etc.). + virtual void Reset() = 0; + + // Notifies the decoder of an incoming packet to NetEQ. + virtual int IncomingPacket(const uint8_t* payload, + size_t payload_len, + uint16_t rtp_sequence_number, + uint32_t rtp_timestamp, + uint32_t arrival_timestamp); + + // Returns the last error code from the decoder. + virtual int ErrorCode(); + + // Returns the duration in samples-per-channel of the payload in |encoded| + // which is |encoded_len| bytes long. Returns kNotImplemented if no duration + // estimate is available, or -1 in case of an error. + virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const; + + // Returns the duration in samples-per-channel of the redandant payload in + // |encoded| which is |encoded_len| bytes long. Returns kNotImplemented if no + // duration estimate is available, or -1 in case of an error. + virtual int PacketDurationRedundant(const uint8_t* encoded, + size_t encoded_len) const; + + // Detects whether a packet has forward error correction. The packet is + // comprised of the samples in |encoded| which is |encoded_len| bytes long. + // Returns true if the packet has FEC and false otherwise. + virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const; + + // Returns the actual sample rate of the decoder's output. This value may not + // change during the lifetime of the decoder. + virtual int SampleRateHz() const = 0; + + // The number of channels in the decoder's output. This value may not change + // during the lifetime of the decoder. + virtual size_t Channels() const = 0; + + protected: + static SpeechType ConvertSpeechType(int16_t type); + + virtual int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) = 0; + + virtual int DecodeRedundantInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type); + + private: + RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoder); +}; + +} // namespace webrtc +#endif // WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/audio_decoder_factory.h b/include/webrtc/api/audio_codecs/audio_decoder_factory.h similarity index 59% rename from include/webrtc/modules/audio_coding/codecs/audio_decoder_factory.h rename to include/webrtc/api/audio_codecs/audio_decoder_factory.h index 12b9778..3479a4e 100644 --- a/include/webrtc/modules/audio_coding/codecs/audio_decoder_factory.h +++ b/include/webrtc/api/audio_codecs/audio_decoder_factory.h @@ -8,24 +8,25 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_FACTORY_H_ -#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_FACTORY_H_ +#ifndef WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ +#define WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ #include #include -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" -#include "webrtc/modules/audio_coding/codecs/audio_format.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/api/audio_codecs/audio_format.h" +#include "webrtc/base/refcount.h" namespace webrtc { // A factory that creates AudioDecoders. // NOTE: This class is still under development and may change without notice. -class AudioDecoderFactory { +class AudioDecoderFactory : public rtc::RefCountInterface { public: - virtual ~AudioDecoderFactory() = default; + virtual std::vector GetSupportedDecoders() = 0; - virtual std::vector GetSupportedFormats() = 0; + virtual bool IsSupportedDecoder(const SdpAudioFormat& format) = 0; virtual std::unique_ptr MakeAudioDecoder( const SdpAudioFormat& format) = 0; @@ -33,4 +34,4 @@ class AudioDecoderFactory { } // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_FACTORY_H_ +#endif // WEBRTC_API_AUDIO_CODECS_AUDIO_DECODER_FACTORY_H_ diff --git a/include/webrtc/api/audio_codecs/audio_format.h b/include/webrtc/api/audio_codecs/audio_format.h new file mode 100644 index 0000000..db3990f --- /dev/null +++ b/include/webrtc/api/audio_codecs/audio_format.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_AUDIO_CODECS_AUDIO_FORMAT_H_ +#define WEBRTC_API_AUDIO_CODECS_AUDIO_FORMAT_H_ + +#include +#include +#include +#include + +namespace webrtc { + +// SDP specification for a single audio codec. +// NOTE: This class is still under development and may change without notice. +struct SdpAudioFormat { + using Parameters = std::map; + + SdpAudioFormat(const SdpAudioFormat&); + SdpAudioFormat(SdpAudioFormat&&); + SdpAudioFormat(const char* name, int clockrate_hz, int num_channels); + SdpAudioFormat(const std::string& name, int clockrate_hz, int num_channels); + SdpAudioFormat(const char* name, + int clockrate_hz, + int num_channels, + const Parameters& param); + SdpAudioFormat(const std::string& name, + int clockrate_hz, + int num_channels, + const Parameters& param); + ~SdpAudioFormat(); + + SdpAudioFormat& operator=(const SdpAudioFormat&); + SdpAudioFormat& operator=(SdpAudioFormat&&); + + friend bool operator==(const SdpAudioFormat& a, const SdpAudioFormat& b); + friend bool operator!=(const SdpAudioFormat& a, const SdpAudioFormat& b) { + return !(a == b); + } + + std::string name; + int clockrate_hz; + int num_channels; + Parameters parameters; +}; + +void swap(SdpAudioFormat& a, SdpAudioFormat& b); +std::ostream& operator<<(std::ostream& os, const SdpAudioFormat& saf); + +// To avoid API breakage, and make the code clearer, AudioCodecSpec should not +// be directly initializable with any flags indicating optional support. If it +// were, these initializers would break any time a new flag was added. It's also +// more difficult to understand: +// AudioCodecSpec spec{{"format", 8000, 1}, true, false, false, true, true}; +// than +// AudioCodecSpec spec({"format", 8000, 1}); +// spec.allow_comfort_noise = true; +// spec.future_flag_b = true; +// spec.future_flag_c = true; +struct AudioCodecSpec { + explicit AudioCodecSpec(const SdpAudioFormat& format); + explicit AudioCodecSpec(SdpAudioFormat&& format); + ~AudioCodecSpec() = default; + + SdpAudioFormat format; + bool allow_comfort_noise = true; // This codec can be used with an external + // comfort noise generator. + bool supports_network_adaption = false; // This codec can adapt to varying + // network conditions. +}; + +} // namespace webrtc + +#endif // WEBRTC_API_AUDIO_CODECS_AUDIO_FORMAT_H_ diff --git a/include/webrtc/api/audio_codecs/builtin_audio_decoder_factory.h b/include/webrtc/api/audio_codecs/builtin_audio_decoder_factory.h new file mode 100644 index 0000000..f7452f4 --- /dev/null +++ b/include/webrtc/api/audio_codecs/builtin_audio_decoder_factory.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ +#define WEBRTC_API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ + +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" +#include "webrtc/base/scoped_ref_ptr.h" + +namespace webrtc { + +// Creates a new factory that can create the built-in types of audio decoders. +// NOTE: This function is still under development and may change without notice. +rtc::scoped_refptr CreateBuiltinAudioDecoderFactory(); + +} // namespace webrtc + +#endif // WEBRTC_API_AUDIO_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ diff --git a/include/webrtc/audio_sink.h b/include/webrtc/api/call/audio_sink.h similarity index 92% rename from include/webrtc/audio_sink.h rename to include/webrtc/api/call/audio_sink.h index 2c932c5..e865ead 100644 --- a/include/webrtc/audio_sink.h +++ b/include/webrtc/api/call/audio_sink.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_AUDIO_SINK_H_ -#define WEBRTC_AUDIO_SINK_H_ +#ifndef WEBRTC_API_CALL_AUDIO_SINK_H_ +#define WEBRTC_API_CALL_AUDIO_SINK_H_ #if defined(WEBRTC_POSIX) && !defined(__STDC_FORMAT_MACROS) // Avoid conflict with format_macros.h. @@ -50,4 +50,4 @@ class AudioSinkInterface { } // namespace webrtc -#endif // WEBRTC_AUDIO_SINK_H_ +#endif // WEBRTC_API_CALL_AUDIO_SINK_H_ diff --git a/include/webrtc/transport.h b/include/webrtc/api/call/transport.h similarity index 88% rename from include/webrtc/transport.h rename to include/webrtc/api/call/transport.h index 4e329de..1126f62 100644 --- a/include/webrtc/transport.h +++ b/include/webrtc/api/call/transport.h @@ -8,12 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_TRANSPORT_H_ -#define WEBRTC_TRANSPORT_H_ +#ifndef WEBRTC_API_CALL_TRANSPORT_H_ +#define WEBRTC_API_CALL_TRANSPORT_H_ #include - -#include "webrtc/typedefs.h" +#include namespace webrtc { @@ -38,4 +37,4 @@ class Transport { } // namespace webrtc -#endif // WEBRTC_TRANSPORT_H_ +#endif // WEBRTC_API_CALL_TRANSPORT_H_ diff --git a/include/webrtc/api/datachannel.h b/include/webrtc/api/datachannel.h index 3fb400b..28112ad 100644 --- a/include/webrtc/api/datachannel.h +++ b/include/webrtc/api/datachannel.h @@ -11,272 +11,8 @@ #ifndef WEBRTC_API_DATACHANNEL_H_ #define WEBRTC_API_DATACHANNEL_H_ -#include -#include -#include - -#include "webrtc/api/datachannelinterface.h" -#include "webrtc/api/proxy.h" -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/media/base/mediachannel.h" -#include "webrtc/pc/channel.h" - -namespace webrtc { - -class DataChannel; - -class DataChannelProviderInterface { - public: - // Sends the data to the transport. - virtual bool SendData(const cricket::SendDataParams& params, - const rtc::CopyOnWriteBuffer& payload, - cricket::SendDataResult* result) = 0; - // Connects to the transport signals. - virtual bool ConnectDataChannel(DataChannel* data_channel) = 0; - // Disconnects from the transport signals. - virtual void DisconnectDataChannel(DataChannel* data_channel) = 0; - // Adds the data channel SID to the transport for SCTP. - virtual void AddSctpDataStream(int sid) = 0; - // Removes the data channel SID from the transport for SCTP. - virtual void RemoveSctpDataStream(int sid) = 0; - // Returns true if the transport channel is ready to send data. - virtual bool ReadyToSendData() const = 0; - - protected: - virtual ~DataChannelProviderInterface() {} -}; - -struct InternalDataChannelInit : public DataChannelInit { - enum OpenHandshakeRole { - kOpener, - kAcker, - kNone - }; - // The default role is kOpener because the default |negotiated| is false. - InternalDataChannelInit() : open_handshake_role(kOpener) {} - explicit InternalDataChannelInit(const DataChannelInit& base) - : DataChannelInit(base), open_handshake_role(kOpener) { - // If the channel is externally negotiated, do not send the OPEN message. - if (base.negotiated) { - open_handshake_role = kNone; - } - } - - OpenHandshakeRole open_handshake_role; -}; - -// Helper class to allocate unique IDs for SCTP DataChannels -class SctpSidAllocator { - public: - // Gets the first unused odd/even id based on the DTLS role. If |role| is - // SSL_CLIENT, the allocated id starts from 0 and takes even numbers; - // otherwise, the id starts from 1 and takes odd numbers. - // Returns false if no id can be allocated. - bool AllocateSid(rtc::SSLRole role, int* sid); - - // Attempts to reserve a specific sid. Returns false if it's unavailable. - bool ReserveSid(int sid); - - // Indicates that |sid| isn't in use any more, and is thus available again. - void ReleaseSid(int sid); - - private: - // Checks if |sid| is available to be assigned to a new SCTP data channel. - bool IsSidAvailable(int sid) const; - - std::set used_sids_; -}; - -// DataChannel is a an implementation of the DataChannelInterface based on -// libjingle's data engine. It provides an implementation of unreliable or -// reliabledata channels. Currently this class is specifically designed to use -// both RtpDataEngine and SctpDataEngine. - -// DataChannel states: -// kConnecting: The channel has been created the transport might not yet be -// ready. -// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc -// and a remote SSRC set by call to UpdateReceiveSsrc and the transport -// has been writable once. -// kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc -// has been called with SSRC==0 -// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with -// SSRC==0. -class DataChannel : public DataChannelInterface, - public sigslot::has_slots<>, - public rtc::MessageHandler { - public: - static rtc::scoped_refptr Create( - DataChannelProviderInterface* provider, - cricket::DataChannelType dct, - const std::string& label, - const InternalDataChannelInit& config); - - virtual void RegisterObserver(DataChannelObserver* observer); - virtual void UnregisterObserver(); - - virtual std::string label() const { return label_; } - virtual bool reliable() const; - virtual bool ordered() const { return config_.ordered; } - virtual uint16_t maxRetransmitTime() const { - return config_.maxRetransmitTime; - } - virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; } - virtual std::string protocol() const { return config_.protocol; } - virtual bool negotiated() const { return config_.negotiated; } - virtual int id() const { return config_.id; } - virtual uint64_t buffered_amount() const; - virtual void Close(); - virtual DataState state() const { return state_; } - virtual bool Send(const DataBuffer& buffer); - - // rtc::MessageHandler override. - virtual void OnMessage(rtc::Message* msg); - - // Called when the channel's ready to use. That can happen when the - // underlying DataMediaChannel becomes ready, or when this channel is a new - // stream on an existing DataMediaChannel, and we've finished negotiation. - void OnChannelReady(bool writable); - - // Sigslots from cricket::DataChannel - void OnDataReceived(cricket::DataChannel* channel, - const cricket::ReceiveDataParams& params, - const rtc::CopyOnWriteBuffer& payload); - void OnStreamClosedRemotely(uint32_t sid); - - // The remote peer request that this channel should be closed. - void RemotePeerRequestClose(); - - // The following methods are for SCTP only. - - // Sets the SCTP sid and adds to transport layer if not set yet. Should only - // be called once. - void SetSctpSid(int sid); - // Called when the transport channel is created. - // Only needs to be called for SCTP data channels. - void OnTransportChannelCreated(); - // Called when the transport channel is destroyed. - void OnTransportChannelDestroyed(); - - // The following methods are for RTP only. - - // Set the SSRC this channel should use to send data on the - // underlying data engine. |send_ssrc| == 0 means that the channel is no - // longer part of the session negotiation. - void SetSendSsrc(uint32_t send_ssrc); - // Set the SSRC this channel should use to receive data from the - // underlying data engine. - void SetReceiveSsrc(uint32_t receive_ssrc); - - cricket::DataChannelType data_channel_type() const { - return data_channel_type_; - } - - // Emitted when state transitions to kClosed. - // In the case of SCTP channels, this signal can be used to tell when the - // channel's sid is free. - sigslot::signal1 SignalClosed; - - protected: - DataChannel(DataChannelProviderInterface* client, - cricket::DataChannelType dct, - const std::string& label); - virtual ~DataChannel(); - - private: - // A packet queue which tracks the total queued bytes. Queued packets are - // owned by this class. - class PacketQueue { - public: - PacketQueue(); - ~PacketQueue(); - - size_t byte_count() const { - return byte_count_; - } - - bool Empty() const; - - DataBuffer* Front(); - - void Pop(); - - void Push(DataBuffer* packet); - - void Clear(); - - void Swap(PacketQueue* other); - - private: - std::deque packets_; - size_t byte_count_; - }; - - // The OPEN(_ACK) signaling state. - enum HandshakeState { - kHandshakeInit, - kHandshakeShouldSendOpen, - kHandshakeShouldSendAck, - kHandshakeWaitingForAck, - kHandshakeReady - }; - - bool Init(const InternalDataChannelInit& config); - void DoClose(); - void UpdateState(); - void SetState(DataState state); - void DisconnectFromProvider(); - - void DeliverQueuedReceivedData(); - - void SendQueuedDataMessages(); - bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked); - bool QueueSendDataMessage(const DataBuffer& buffer); - - void SendQueuedControlMessages(); - void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer); - bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer); - - std::string label_; - InternalDataChannelInit config_; - DataChannelObserver* observer_; - DataState state_; - cricket::DataChannelType data_channel_type_; - DataChannelProviderInterface* provider_; - HandshakeState handshake_state_; - bool connected_to_provider_; - bool send_ssrc_set_; - bool receive_ssrc_set_; - bool writable_; - uint32_t send_ssrc_; - uint32_t receive_ssrc_; - // Control messages that always have to get sent out before any queued - // data. - PacketQueue queued_control_data_; - PacketQueue queued_received_data_; - PacketQueue queued_send_data_; -}; - -// Define proxy for DataChannelInterface. -BEGIN_SIGNALING_PROXY_MAP(DataChannel) - PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) - PROXY_METHOD0(void, UnregisterObserver) - PROXY_CONSTMETHOD0(std::string, label) - PROXY_CONSTMETHOD0(bool, reliable) - PROXY_CONSTMETHOD0(bool, ordered) - PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime) - PROXY_CONSTMETHOD0(uint16_t, maxRetransmits) - PROXY_CONSTMETHOD0(std::string, protocol) - PROXY_CONSTMETHOD0(bool, negotiated) - PROXY_CONSTMETHOD0(int, id) - PROXY_CONSTMETHOD0(DataState, state) - PROXY_CONSTMETHOD0(uint64_t, buffered_amount) - PROXY_METHOD0(void, Close) - PROXY_METHOD1(bool, Send, const DataBuffer&) -END_SIGNALING_PROXY() - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/datachannel.h" #endif // WEBRTC_API_DATACHANNEL_H_ diff --git a/include/webrtc/api/datachannelinterface.h b/include/webrtc/api/datachannelinterface.h index 53c11d4..92bdee2 100644 --- a/include/webrtc/api/datachannelinterface.h +++ b/include/webrtc/api/datachannelinterface.h @@ -24,31 +24,43 @@ namespace webrtc { +// C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelinit +// TODO(deadbeef): Use rtc::Optional for the "-1 if unset" things. struct DataChannelInit { - DataChannelInit() - : reliable(false), - ordered(true), - maxRetransmitTime(-1), - maxRetransmits(-1), - negotiated(false), - id(-1) { - } - - bool reliable; // Deprecated. - bool ordered; // True if ordered delivery is required. - int maxRetransmitTime; // The max period of time in milliseconds in which - // retransmissions will be sent. After this time, no - // more retransmissions will be sent. -1 if unset. - int maxRetransmits; // The max number of retransmissions. -1 if unset. - std::string protocol; // This is set by the application and opaque to the - // WebRTC implementation. - bool negotiated; // True if the channel has been externally negotiated - // and we do not send an in-band signalling in the - // form of an "open" message. - int id; // The stream id, or SID, for SCTP data channels. -1 - // if unset. + // Deprecated. Reliability is assumed, and channel will be unreliable if + // maxRetransmitTime or MaxRetransmits is set. + bool reliable = false; + + // True if ordered delivery is required. + bool ordered = true; + + // The max period of time in milliseconds in which retransmissions will be + // sent. After this time, no more retransmissions will be sent. -1 if unset. + // + // Cannot be set along with |maxRetransmits|. + int maxRetransmitTime = -1; + + // The max number of retransmissions. -1 if unset. + // + // Cannot be set along with |maxRetransmitTime|. + int maxRetransmits = -1; + + // This is set by the application and opaque to the WebRTC implementation. + std::string protocol; + + // True if the channel has been externally negotiated and we do not send an + // in-band signalling in the form of an "open" message. If this is true, |id| + // below must be set; otherwise it should be unset and will be negotiated + // in-band. + bool negotiated = false; + + // The stream id, or SID, for SCTP data channels. -1 if unset (see above). + int id = -1; }; +// At the JavaScript level, data can be passed in as a string or a blob, so +// this structure's |binary| flag tells whether the data should be interpreted +// as binary or text. struct DataBuffer { DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary) : data(data), @@ -68,6 +80,10 @@ struct DataBuffer { bool binary; }; +// Used to implement RTCDataChannel events. +// +// The code responding to these callbacks should unwind the stack before +// using any other webrtc APIs; re-entrancy is not supported. class DataChannelObserver { public: // The data channel state have changed. @@ -75,7 +91,7 @@ class DataChannelObserver { // A data buffer was successfully received. virtual void OnMessage(const DataBuffer& buffer) = 0; // The data channel's buffered_amount has changed. - virtual void OnBufferedAmountChange(uint64_t previous_amount){}; + virtual void OnBufferedAmountChange(uint64_t previous_amount) {} protected: virtual ~DataChannelObserver() {} @@ -83,7 +99,8 @@ class DataChannelObserver { class DataChannelInterface : public rtc::RefCountInterface { public: - // Keep in sync with DataChannel.java:State and + // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelstate + // Unlikely to change, but keep in sync with DataChannel.java:State and // RTCDataChannel.h:RTCDataChannelState. enum DataState { kConnecting, @@ -107,14 +124,20 @@ class DataChannelInterface : public rtc::RefCountInterface { return ""; } + // Used to receive events from the data channel. Only one observer can be + // registered at a time. UnregisterObserver should be called before the + // observer object is destroyed. virtual void RegisterObserver(DataChannelObserver* observer) = 0; virtual void UnregisterObserver() = 0; + // The label attribute represents a label that can be used to distinguish this // DataChannel object from other DataChannel objects. virtual std::string label() const = 0; - virtual bool reliable() const = 0; - // TODO(tommyw): Remove these dummy implementations when all classes have + // The accessors below simply return the properties from the DataChannelInit + // the data channel was constructed with. + virtual bool reliable() const = 0; + // TODO(deadbeef): Remove these dummy implementations when all classes have // implemented these APIs. They should all just return the values the // DataChannel was created with. virtual bool ordered() const { return false; } @@ -123,14 +146,33 @@ class DataChannelInterface : public rtc::RefCountInterface { virtual std::string protocol() const { return std::string(); } virtual bool negotiated() const { return false; } + // Returns the ID from the DataChannelInit, if it was negotiated out-of-band. + // If negotiated in-band, this ID will be populated once the DTLS role is + // determined, and until then this will return -1. virtual int id() const = 0; virtual DataState state() const = 0; - // The buffered_amount returns the number of bytes of application data - // (UTF-8 text and binary data) that have been queued using SendBuffer but - // have not yet been transmitted to the network. + virtual uint32_t messages_sent() const = 0; + virtual uint64_t bytes_sent() const = 0; + virtual uint32_t messages_received() const = 0; + virtual uint64_t bytes_received() const = 0; + + // Returns the number of bytes of application data (UTF-8 text and binary + // data) that have been queued using Send but have not yet been processed at + // the SCTP level. See comment above Send below. virtual uint64_t buffered_amount() const = 0; + + // Begins the graceful data channel closing procedure. See: + // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7 virtual void Close() = 0; - // Sends |data| to the remote peer. + + // Sends |data| to the remote peer. If the data can't be sent at the SCTP + // level (due to congestion control), it's buffered at the data channel level, + // up to a maximum of 16MB. If Send is called while this buffer is full, the + // data channel will be closed abruptly. + // + // So, it's important to use buffered_amount() and OnBufferedAmountChange to + // ensure the data channel is used efficiently but without filling this + // buffer. virtual bool Send(const DataBuffer& buffer) = 0; protected: diff --git a/include/webrtc/api/dtlsidentitystore.h b/include/webrtc/api/dtlsidentitystore.h deleted file mode 100644 index e25b795..0000000 --- a/include/webrtc/api/dtlsidentitystore.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_DTLSIDENTITYSTORE_H_ -#define WEBRTC_API_DTLSIDENTITYSTORE_H_ - -#include -#include -#include -#include - -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/messagequeue.h" -#include "webrtc/base/optional.h" -#include "webrtc/base/refcount.h" -#include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/base/sslidentity.h" -#include "webrtc/base/thread.h" - -namespace webrtc { - -// Passed to SSLIdentity::Generate. -extern const char kIdentityName[]; - -class SSLIdentity; -class Thread; - -// Used to receive callbacks of DTLS identity requests. -class DtlsIdentityRequestObserver : public rtc::RefCountInterface { - public: - virtual void OnFailure(int error) = 0; - // TODO(hbos): Unify the OnSuccess method once Chrome code is updated. - virtual void OnSuccess(const std::string& der_cert, - const std::string& der_private_key) = 0; - // |identity| is a unique_ptr because rtc::SSLIdentity is not copyable and the - // client has to get the ownership of the object to make use of it. - virtual void OnSuccess(std::unique_ptr identity) = 0; - - protected: - virtual ~DtlsIdentityRequestObserver() {} -}; - -// This interface defines an in-memory DTLS identity store, which generates DTLS -// identities. -// APIs calls must be made on the signaling thread and the callbacks are also -// called on the signaling thread. -class DtlsIdentityStoreInterface { - public: - virtual ~DtlsIdentityStoreInterface() { } - - // The |observer| will be called when the requested identity is ready, or when - // identity generation fails. - virtual void RequestIdentity( - const rtc::KeyParams& key_params, - const rtc::Optional& expires_ms, - const rtc::scoped_refptr& observer) = 0; -}; - -// The WebRTC default implementation of DtlsIdentityStoreInterface. -// Identity generation is performed on the worker thread. -class DtlsIdentityStoreImpl : public DtlsIdentityStoreInterface, - public rtc::MessageHandler { - public: - // This will start to preemptively generating an RSA identity in the - // background if the worker thread is not the same as the signaling thread. - DtlsIdentityStoreImpl(rtc::Thread* signaling_thread, - rtc::Thread* worker_thread); - ~DtlsIdentityStoreImpl() override; - - // DtlsIdentityStoreInterface override; - void RequestIdentity( - const rtc::KeyParams& key_params, - const rtc::Optional& expires_ms, - const rtc::scoped_refptr& observer) override; - - // rtc::MessageHandler override; - void OnMessage(rtc::Message* msg) override; - - // Returns true if there is a free RSA identity, used for unit tests. - bool HasFreeIdentityForTesting(rtc::KeyType key_type) const; - - private: - void GenerateIdentity( - rtc::KeyType key_type, - const rtc::scoped_refptr& observer); - void OnIdentityGenerated(rtc::KeyType key_type, - std::unique_ptr identity); - - class WorkerTask; - typedef rtc::ScopedMessageData - WorkerTaskMessageData; - - // A key type-identity pair. - struct IdentityResult { - IdentityResult(rtc::KeyType key_type, - std::unique_ptr identity) - : key_type_(key_type), identity_(std::move(identity)) {} - - rtc::KeyType key_type_; - std::unique_ptr identity_; - }; - - typedef rtc::ScopedMessageData IdentityResultMessageData; - - sigslot::signal0<> SignalDestroyed; - - rtc::Thread* const signaling_thread_; - // TODO(hbos): RSA generation is slow and would be VERY slow if we switch over - // to 2048, DtlsIdentityStore should use a new thread and not the "general - // purpose" worker thread. - rtc::Thread* const worker_thread_; - - struct RequestInfo { - RequestInfo() - : request_observers_(), gen_in_progress_counts_(0), free_identity_() {} - - std::queue> - request_observers_; - size_t gen_in_progress_counts_; - std::unique_ptr free_identity_; - }; - - // One RequestInfo per KeyType. Only touch on the |signaling_thread_|. - RequestInfo request_info_[rtc::KT_LAST]; -}; - -} // namespace webrtc - -#endif // WEBRTC_API_DTLSIDENTITYSTORE_H_ diff --git a/include/webrtc/api/dtmfsenderinterface.h b/include/webrtc/api/dtmfsenderinterface.h index a726ca3..a1ef3ec 100644 --- a/include/webrtc/api/dtmfsenderinterface.h +++ b/include/webrtc/api/dtmfsenderinterface.h @@ -14,15 +14,13 @@ #include #include "webrtc/api/mediastreaminterface.h" -#include "webrtc/base/common.h" #include "webrtc/base/refcount.h" -// This file contains interfaces for DtmfSender. - namespace webrtc { -// DtmfSender callback interface. Application should implement this interface -// to get notifications from the DtmfSender. +// DtmfSender callback interface, used to implement RTCDtmfSender events. +// Applications should implement this interface to get notifications from the +// DtmfSender. class DtmfSenderObserverInterface { public: // Triggered when DTMF |tone| is sent. @@ -36,13 +34,18 @@ class DtmfSenderObserverInterface { // The interface of native implementation of the RTCDTMFSender defined by the // WebRTC W3C Editor's Draft. +// See: https://www.w3.org/TR/webrtc/#peer-to-peer-dtmf class DtmfSenderInterface : public rtc::RefCountInterface { public: + // Used to receive events from the DTMF sender. Only one observer can be + // registered at a time. UnregisterObserver should be called before the + // observer object is destroyed. virtual void RegisterObserver(DtmfSenderObserverInterface* observer) = 0; virtual void UnregisterObserver() = 0; - // Returns true if this DtmfSender is capable of sending DTMF. - // Otherwise returns false. + // Returns true if this DtmfSender is capable of sending DTMF. Otherwise + // returns false. To be able to send DTMF, the associated RtpSender must be + // able to send packets, and a "telephone-event" codec must be negotiated. virtual bool CanInsertDtmf() = 0; // Queues a task that sends the DTMF |tones|. The |tones| parameter is treated @@ -50,20 +53,26 @@ class DtmfSenderInterface : public rtc::RefCountInterface { // * generate the associated DTMF tones. The characters a to d are equivalent // to A to D. The character ',' indicates a delay of 2 seconds before // processing the next character in the tones parameter. + // // Unrecognized characters are ignored. + // // The |duration| parameter indicates the duration in ms to use for each - // character passed in the |tones| parameter. - // The duration cannot be more than 6000 or less than 70. - // The |inter_tone_gap| parameter indicates the gap between tones in ms. - // The |inter_tone_gap| must be at least 50 ms but should be as short as + // character passed in the |tones| parameter. The duration cannot be more + // than 6000 or less than 70. + // + // The |inter_tone_gap| parameter indicates the gap between tones in ms. The + // |inter_tone_gap| must be at least 50 ms but should be as short as // possible. + // // If InsertDtmf is called on the same object while an existing task for this // object to generate DTMF is still running, the previous task is canceled. // Returns true on success and false on failure. virtual bool InsertDtmf(const std::string& tones, int duration, int inter_tone_gap) = 0; - // Returns the track given as argument to the constructor. + // Returns the track given as argument to the constructor. Only exists for + // backwards compatibilty; now that DtmfSenders are tied to RtpSenders, it's + // no longer relevant. virtual const AudioTrackInterface* track() const = 0; // Returns the tones remaining to be played out. diff --git a/include/webrtc/api/fakemetricsobserver.h b/include/webrtc/api/fakemetricsobserver.h index baac0ca..90046c9 100644 --- a/include/webrtc/api/fakemetricsobserver.h +++ b/include/webrtc/api/fakemetricsobserver.h @@ -13,6 +13,7 @@ #include #include +#include #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/base/thread_checker.h" diff --git a/include/webrtc/api/java/jni/androidmediacodeccommon.h b/include/webrtc/api/java/jni/androidmediacodeccommon.h deleted file mode 100644 index db7260a..0000000 --- a/include/webrtc/api/java/jni/androidmediacodeccommon.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_ANDROIDMEDIACODECCOMMON_H_ -#define WEBRTC_API_JAVA_JNI_ANDROIDMEDIACODECCOMMON_H_ - -#include -#include - -#include "webrtc/base/thread.h" -#include "webrtc/api/java/jni/classreferenceholder.h" -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/thread.h" - -namespace webrtc_jni { - -// Uncomment this define to enable verbose logging for every encoded/decoded -// video frame. -//#define TRACK_BUFFER_TIMING - -#define TAG_COMMON "MediaCodecVideo" - -// Color formats supported by encoder - should mirror supportedColorList -// from MediaCodecVideoEncoder.java -enum COLOR_FORMATTYPE { - COLOR_FormatYUV420Planar = 0x13, - COLOR_FormatYUV420SemiPlanar = 0x15, - COLOR_QCOM_FormatYUV420SemiPlanar = 0x7FA30C00, - // NV12 color format supported by QCOM codec, but not declared in MediaCodec - - // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h - // This format is presumably similar to COLOR_FormatYUV420SemiPlanar, - // but requires some (16, 32?) byte alignment. - COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04 -}; - -// Arbitrary interval to poll the codec for new outputs. -enum { kMediaCodecPollMs = 10 }; -// Media codec maximum output buffer ready timeout. -enum { kMediaCodecTimeoutMs = 1000 }; -// Interval to print codec statistics (bitrate, fps, encoding/decoding time). -enum { kMediaCodecStatisticsIntervalMs = 3000 }; -// Maximum amount of pending frames for VP8 decoder. -enum { kMaxPendingFramesVp8 = 1 }; -// Maximum amount of pending frames for VP9 decoder. -enum { kMaxPendingFramesVp9 = 1 }; -// Maximum amount of pending frames for H.264 decoder. -enum { kMaxPendingFramesH264 = 8 }; -// Maximum amount of decoded frames for which per-frame logging is enabled. -enum { kMaxDecodedLogFrames = 10 }; -// Maximum amount of encoded frames for which per-frame logging is enabled. -enum { kMaxEncodedLogFrames = 10 }; - -static inline void AllowBlockingCalls() { - rtc::Thread* current_thread = rtc::Thread::Current(); - if (current_thread != NULL) - current_thread->SetAllowBlockingCalls(true); -} - -// Return the (singleton) Java Enum object corresponding to |index|; -// |state_class_fragment| is something like "MediaSource$State". -static inline jobject JavaEnumFromIndexAndClassName( - JNIEnv* jni, const std::string& state_class_fragment, int index) { - const std::string state_class = "org/webrtc/" + state_class_fragment; - return JavaEnumFromIndex(jni, FindClass(jni, state_class.c_str()), - state_class, index); -} - -// Checks for any Java exception, prints stack backtrace and clears -// currently thrown exception. -static inline bool CheckException(JNIEnv* jni) { - if (jni->ExceptionCheck()) { - LOG_TAG(rtc::LS_ERROR, TAG_COMMON) << "Java JNI exception."; - jni->ExceptionDescribe(); - jni->ExceptionClear(); - return true; - } - return false; -} - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_ANDROIDMEDIACODECCOMMON_H_ diff --git a/include/webrtc/api/java/jni/androidmediadecoder_jni.h b/include/webrtc/api/java/jni/androidmediadecoder_jni.h deleted file mode 100644 index 0719926..0000000 --- a/include/webrtc/api/java/jni/androidmediadecoder_jni.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_ANDROIDMEDIADECODER_JNI_H_ -#define WEBRTC_API_JAVA_JNI_ANDROIDMEDIADECODER_JNI_H_ - -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/media/engine/webrtcvideodecoderfactory.h" - -namespace webrtc_jni { - -// Implementation of Android MediaCodec based decoder factory. -class MediaCodecVideoDecoderFactory - : public cricket::WebRtcVideoDecoderFactory { - public: - MediaCodecVideoDecoderFactory(); - virtual ~MediaCodecVideoDecoderFactory(); - - void SetEGLContext(JNIEnv* jni, jobject render_egl_context); - - // WebRtcVideoDecoderFactory implementation. - webrtc::VideoDecoder* CreateVideoDecoder(webrtc::VideoCodecType type) - override; - - void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override; - - private: - jobject egl_context_; - std::vector supported_codec_types_; -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_ANDROIDMEDIADECODER_JNI_H_ diff --git a/include/webrtc/api/java/jni/androidmediaencoder_jni.h b/include/webrtc/api/java/jni/androidmediaencoder_jni.h deleted file mode 100644 index 4e50700..0000000 --- a/include/webrtc/api/java/jni/androidmediaencoder_jni.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_ANDROIDMEDIAENCODER_JNI_H_ -#define WEBRTC_API_JAVA_JNI_ANDROIDMEDIAENCODER_JNI_H_ - -#include - -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/media/engine/webrtcvideoencoderfactory.h" - -namespace webrtc_jni { - -// Implementation of Android MediaCodec based encoder factory. -class MediaCodecVideoEncoderFactory - : public cricket::WebRtcVideoEncoderFactory { - public: - MediaCodecVideoEncoderFactory(); - virtual ~MediaCodecVideoEncoderFactory(); - - void SetEGLContext(JNIEnv* jni, jobject egl_context); - - // WebRtcVideoEncoderFactory implementation. - webrtc::VideoEncoder* CreateVideoEncoder(webrtc::VideoCodecType type) - override; - const std::vector& codecs() const override; - void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; - - private: - jobject egl_context_; - - // Empty if platform support is lacking, const after ctor returns. - std::vector supported_codecs_; -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_ANDROIDMEDIAENCODER_JNI_H_ diff --git a/include/webrtc/api/java/jni/androidnetworkmonitor_jni.h b/include/webrtc/api/java/jni/androidnetworkmonitor_jni.h deleted file mode 100644 index 2537ce8..0000000 --- a/include/webrtc/api/java/jni/androidnetworkmonitor_jni.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_ANDROIDNETWORKMONITOR_JNI_H_ -#define WEBRTC_API_JAVA_JNI_ANDROIDNETWORKMONITOR_JNI_H_ - -#include "webrtc/base/networkmonitor.h" - -#include - -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/base/thread_checker.h" - -namespace webrtc_jni { - -typedef uint32_t NetworkHandle; - -// c++ equivalent of java NetworkMonitorAutoDetect.ConnectionType. -enum NetworkType { - NETWORK_UNKNOWN, - NETWORK_ETHERNET, - NETWORK_WIFI, - NETWORK_4G, - NETWORK_3G, - NETWORK_2G, - NETWORK_BLUETOOTH, - NETWORK_NONE -}; - -// The information is collected from Android OS so that the native code can get -// the network type and handle (Android network ID) for each interface. -struct NetworkInformation { - std::string interface_name; - NetworkHandle handle; - NetworkType type; - std::vector ip_addresses; - - std::string ToString() const; -}; - -class AndroidNetworkMonitor : public rtc::NetworkMonitorBase, - public rtc::NetworkBinderInterface { - public: - AndroidNetworkMonitor(); - - static void SetAndroidContext(JNIEnv* jni, jobject context); - - void Start() override; - void Stop() override; - - int BindSocketToNetwork(int socket_fd, - const rtc::IPAddress& address) override; - rtc::AdapterType GetAdapterType(const std::string& if_name) override; - void OnNetworkConnected(const NetworkInformation& network_info); - void OnNetworkDisconnected(NetworkHandle network_handle); - void SetNetworkInfos(const std::vector& network_infos); - - private: - JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); } - - void OnNetworkConnected_w(const NetworkInformation& network_info); - void OnNetworkDisconnected_w(NetworkHandle network_handle); - - ScopedGlobalRef j_network_monitor_class_; - ScopedGlobalRef j_network_monitor_; - rtc::ThreadChecker thread_checker_; - static jobject application_context_; - bool started_ = false; - std::map adapter_type_by_name_; - std::map network_handle_by_address_; - std::map network_info_by_handle_; -}; - -class AndroidNetworkMonitorFactory : public rtc::NetworkMonitorFactory { - public: - AndroidNetworkMonitorFactory() {} - - rtc::NetworkMonitorInterface* CreateNetworkMonitor() override; -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_ANDROIDNETWORKMONITOR_JNI_H_ diff --git a/include/webrtc/api/java/jni/androidvideocapturer_jni.h b/include/webrtc/api/java/jni/androidvideocapturer_jni.h deleted file mode 100644 index eea56ad..0000000 --- a/include/webrtc/api/java/jni/androidvideocapturer_jni.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_ -#define WEBRTC_API_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_ - -#include -#include - -#include "webrtc/api/androidvideocapturer.h" -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/base/asyncinvoker.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/thread_checker.h" -#include "webrtc/common_video/include/i420_buffer_pool.h" - -namespace webrtc_jni { - -struct NativeHandleImpl; -class SurfaceTextureHelper; - -// AndroidVideoCapturerJni implements AndroidVideoCapturerDelegate. -// The purpose of the delegate is to hide the JNI specifics from the C++ only -// AndroidVideoCapturer. -class AndroidVideoCapturerJni : public webrtc::AndroidVideoCapturerDelegate { - public: - static int SetAndroidObjects(JNIEnv* jni, jobject appliction_context); - - AndroidVideoCapturerJni(JNIEnv* jni, - jobject j_video_capturer, - jobject j_egl_context); - - void Start(int width, int height, int framerate, - webrtc::AndroidVideoCapturer* capturer) override; - void Stop() override; - - std::vector GetSupportedFormats() override; - - // Called from VideoCapturer::NativeObserver on a Java thread. - void OnCapturerStarted(bool success); - void OnMemoryBufferFrame(void* video_frame, int length, int width, - int height, int rotation, int64_t timestamp_ns); - void OnTextureFrame(int width, int height, int rotation, int64_t timestamp_ns, - const NativeHandleImpl& handle); - void OnOutputFormatRequest(int width, int height, int fps); - - protected: - ~AndroidVideoCapturerJni(); - - private: - JNIEnv* jni(); - - // To avoid deducing Args from the 3rd parameter of AsyncCapturerInvoke. - template - struct Identity { - typedef T type; - }; - - // Helper function to make safe asynchronous calls to |capturer_|. The calls - // are not guaranteed to be delivered. - template - void AsyncCapturerInvoke( - const char* method_name, - void (webrtc::AndroidVideoCapturer::*method)(Args...), - typename Identity::type... args); - - const ScopedGlobalRef j_video_capturer_; - const ScopedGlobalRef j_video_capturer_class_; - const ScopedGlobalRef j_observer_class_; - - // Used on the Java thread running the camera. - webrtc::I420BufferPool buffer_pool_; - rtc::scoped_refptr surface_texture_helper_; - rtc::ThreadChecker thread_checker_; - - // |capturer| is a guaranteed to be a valid pointer between a call to - // AndroidVideoCapturerDelegate::Start - // until AndroidVideoCapturerDelegate::Stop. - rtc::CriticalSection capturer_lock_; - webrtc::AndroidVideoCapturer* capturer_ GUARDED_BY(capturer_lock_); - // |invoker_| is used to communicate with |capturer_| on the thread Start() is - // called on. - std::unique_ptr invoker_ GUARDED_BY(capturer_lock_); - - static jobject application_context_; - - RTC_DISALLOW_COPY_AND_ASSIGN(AndroidVideoCapturerJni); -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_ANDROIDVIDEOCAPTURER_JNI_H_ diff --git a/include/webrtc/api/java/jni/classreferenceholder.h b/include/webrtc/api/java/jni/classreferenceholder.h deleted file mode 100644 index 4120278..0000000 --- a/include/webrtc/api/java/jni/classreferenceholder.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Android's FindClass() is trickier than usual because the app-specific -// ClassLoader is not consulted when there is no app-specific frame on the -// stack. Consequently, we only look up all classes once in app/webrtc. -// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass - -#ifndef WEBRTC_API_JAVA_JNI_CLASSREFERENCEHOLDER_H_ -#define WEBRTC_API_JAVA_JNI_CLASSREFERENCEHOLDER_H_ - -#include -#include -#include - -namespace webrtc_jni { - -// LoadGlobalClassReferenceHolder must be called in JNI_OnLoad. -void LoadGlobalClassReferenceHolder(); -// FreeGlobalClassReferenceHolder must be called in JNI_UnLoad. -void FreeGlobalClassReferenceHolder(); - -// Returns a global reference guaranteed to be valid for the lifetime of the -// process. -jclass FindClass(JNIEnv* jni, const char* name); - -// Convenience macro defining JNI-accessible methods in the org.webrtc package. -// Eliminates unnecessary boilerplate and line-wraps, reducing visual clutter. -#define JOW(rettype, name) extern "C" rettype JNIEXPORT JNICALL \ - Java_org_webrtc_##name - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_CLASSREFERENCEHOLDER_H_ diff --git a/include/webrtc/api/java/jni/jni_helpers.h b/include/webrtc/api/java/jni/jni_helpers.h deleted file mode 100644 index 2832df1..0000000 --- a/include/webrtc/api/java/jni/jni_helpers.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This file contain convenience functions and classes for JNI. -// Before using any of the methods, InitGlobalJniVariables must be called. - -#ifndef WEBRTC_API_JAVA_JNI_JNI_HELPERS_H_ -#define WEBRTC_API_JAVA_JNI_JNI_HELPERS_H_ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/checks.h" -#include "webrtc/base/thread_checker.h" - -// Abort the process if |jni| has a Java exception pending. -// This macros uses the comma operator to execute ExceptionDescribe -// and ExceptionClear ignoring their return values and sending "" -// to the error stream. -#define CHECK_EXCEPTION(jni) \ - RTC_CHECK(!jni->ExceptionCheck()) \ - << (jni->ExceptionDescribe(), jni->ExceptionClear(), "") - -// Helper that calls ptr->Release() and aborts the process with a useful -// message if that didn't actually delete *ptr because of extra refcounts. -#define CHECK_RELEASE(ptr) \ - RTC_CHECK_EQ(0, (ptr)->Release()) << "Unexpected refcount." - -namespace webrtc_jni { - -jint InitGlobalJniVariables(JavaVM *jvm); - -// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached. -JNIEnv* GetEnv(); - -JavaVM *GetJVM(); - -// Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary. -JNIEnv* AttachCurrentThreadIfNeeded(); - -// Return a |jlong| that will correctly convert back to |ptr|. This is needed -// because the alternative (of silently passing a 32-bit pointer to a vararg -// function expecting a 64-bit param) picks up garbage in the high 32 bits. -jlong jlongFromPointer(void* ptr); - -// JNIEnv-helper methods that RTC_CHECK success: no Java exception thrown and -// found object/class/method/field is non-null. -jmethodID GetMethodID( - JNIEnv* jni, jclass c, const std::string& name, const char* signature); - -jmethodID GetStaticMethodID( - JNIEnv* jni, jclass c, const char* name, const char* signature); - -jfieldID GetFieldID(JNIEnv* jni, jclass c, const char* name, - const char* signature); - -jclass GetObjectClass(JNIEnv* jni, jobject object); - -// Throws an exception if the object field is null. -jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id); - -jobject GetNullableObjectField(JNIEnv* jni, jobject object, jfieldID id); - -jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id); - -jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id); - -jint GetIntField(JNIEnv* jni, jobject object, jfieldID id); - -bool GetBooleanField(JNIEnv* jni, jobject object, jfieldID id); - -// Returns true if |obj| == null in Java. -bool IsNull(JNIEnv* jni, jobject obj); - -// Given a UTF-8 encoded |native| string return a new (UTF-16) jstring. -jstring JavaStringFromStdString(JNIEnv* jni, const std::string& native); - -// Given a (UTF-16) jstring return a new UTF-8 native string. -std::string JavaToStdString(JNIEnv* jni, const jstring& j_string); - -// Return the (singleton) Java Enum object corresponding to |index|; -jobject JavaEnumFromIndex(JNIEnv* jni, jclass state_class, - const std::string& state_class_name, int index); - -// Returns the name of a Java enum. -std::string GetJavaEnumName(JNIEnv* jni, - const std::string& className, - jobject j_enum); - -jobject NewGlobalRef(JNIEnv* jni, jobject o); - -void DeleteGlobalRef(JNIEnv* jni, jobject o); - -// Scope Java local references to the lifetime of this object. Use in all C++ -// callbacks (i.e. entry points that don't originate in a Java callstack -// through a "native" method call). -class ScopedLocalRefFrame { - public: - explicit ScopedLocalRefFrame(JNIEnv* jni); - ~ScopedLocalRefFrame(); - - private: - JNIEnv* jni_; -}; - -// Scoped holder for global Java refs. -template // T is jclass, jobject, jintArray, etc. -class ScopedGlobalRef { - public: - ScopedGlobalRef(JNIEnv* jni, T obj) - : obj_(static_cast(jni->NewGlobalRef(obj))) {} - ~ScopedGlobalRef() { - DeleteGlobalRef(AttachCurrentThreadIfNeeded(), obj_); - } - T operator*() const { - return obj_; - } - private: - T obj_; -}; - -// Provides a convenient way to iterate over a Java Iterable using the -// C++ range-for loop. -// E.g. for (jobject value : Iterable(jni, j_iterable)) { ... } -// Note: Since Java iterators cannot be duplicated, the iterator class is not -// copyable to prevent creating multiple C++ iterators that refer to the same -// Java iterator. -class Iterable { - public: - Iterable(JNIEnv* jni, jobject iterable) : jni_(jni), iterable_(iterable) {} - - class Iterator { - public: - // Creates an iterator representing the end of any collection. - Iterator(); - // Creates an iterator pointing to the beginning of the specified - // collection. - Iterator(JNIEnv* jni, jobject iterable); - - // Move constructor - necessary to be able to return iterator types from - // functions. - Iterator(Iterator&& other); - - // Move assignment should not be used. - Iterator& operator=(Iterator&&) = delete; - - // Advances the iterator one step. - Iterator& operator++(); - - // Provides a way to compare the iterator with itself and with the end - // iterator. - // Note: all other comparison results are undefined, just like for C++ input - // iterators. - bool operator==(const Iterator& other); - bool operator!=(const Iterator& other) { return !(*this == other); } - jobject operator*(); - - private: - bool AtEnd() const; - - JNIEnv* jni_ = nullptr; - jobject iterator_ = nullptr; - jobject value_ = nullptr; - jmethodID has_next_id_ = nullptr; - jmethodID next_id_ = nullptr; - rtc::ThreadChecker thread_checker_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Iterator); - }; - - Iterable::Iterator begin() { return Iterable::Iterator(jni_, iterable_); } - Iterable::Iterator end() { return Iterable::Iterator(); } - - private: - JNIEnv* jni_; - jobject iterable_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Iterable); -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_JNI_HELPERS_H_ diff --git a/include/webrtc/api/java/jni/native_handle_impl.h b/include/webrtc/api/java/jni/native_handle_impl.h deleted file mode 100644 index b781815..0000000 --- a/include/webrtc/api/java/jni/native_handle_impl.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_NATIVE_HANDLE_IMPL_H_ -#define WEBRTC_API_JAVA_JNI_NATIVE_HANDLE_IMPL_H_ - -#include - -#include "webrtc/common_video/include/video_frame_buffer.h" -#include "webrtc/common_video/rotation.h" - -namespace webrtc_jni { - -// Wrapper for texture object. -struct NativeHandleImpl { - NativeHandleImpl(JNIEnv* jni, - jint j_oes_texture_id, - jfloatArray j_transform_matrix); - - const int oes_texture_id; - float sampling_matrix[16]; -}; - -class AndroidTextureBuffer : public webrtc::NativeHandleBuffer { - public: - AndroidTextureBuffer(int width, - int height, - const NativeHandleImpl& native_handle, - jobject surface_texture_helper, - const rtc::Callback0& no_longer_used); - ~AndroidTextureBuffer(); - rtc::scoped_refptr NativeToI420Buffer() override; - - // First crop, then scale to dst resolution, and then rotate. - rtc::scoped_refptr CropScaleAndRotate( - int cropped_width, - int cropped_height, - int dst_width, - int dst_height, - webrtc::VideoRotation rotation); - - private: - NativeHandleImpl native_handle_; - // Raw object pointer, relying on the caller, i.e., - // AndroidVideoCapturerJni or the C++ SurfaceTextureHelper, to keep - // a global reference. TODO(nisse): Make this a reference to the C++ - // SurfaceTextureHelper instead, but that requires some refactoring - // of AndroidVideoCapturerJni. - jobject surface_texture_helper_; - rtc::Callback0 no_longer_used_cb_; -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_NATIVE_HANDLE_IMPL_H_ diff --git a/include/webrtc/api/java/jni/surfacetexturehelper_jni.h b/include/webrtc/api/java/jni/surfacetexturehelper_jni.h deleted file mode 100644 index d7a9a77..0000000 --- a/include/webrtc/api/java/jni/surfacetexturehelper_jni.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_JAVA_JNI_SURFACETEXTUREHELPER_JNI_H_ -#define WEBRTC_API_JAVA_JNI_SURFACETEXTUREHELPER_JNI_H_ - -#include - -#include "webrtc/api/java/jni/jni_helpers.h" -#include "webrtc/api/java/jni/native_handle_impl.h" -#include "webrtc/base/refcount.h" -#include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/common_video/include/video_frame_buffer.h" - -namespace webrtc_jni { - -// Helper class to create and synchronize access to an Android SurfaceTexture. -// It is used for creating webrtc::VideoFrameBuffers from a SurfaceTexture when -// the SurfaceTexture has been updated. -// When the VideoFrameBuffer is released, this class returns the buffer to the -// java SurfaceTextureHelper so it can be updated safely. The VideoFrameBuffer -// can be released on an arbitrary thread. -// SurfaceTextureHelper is reference counted to make sure that it is not -// destroyed while a VideoFrameBuffer is in use. -// This class is the C++ counterpart of the java class SurfaceTextureHelper. -// Usage: -// 1. Create an instance of this class. -// 2. Get the Java SurfaceTextureHelper with GetJavaSurfaceTextureHelper(). -// 3. Register a listener to the Java SurfaceListener and start producing -// new buffers. -// 4. Call CreateTextureFrame to wrap the Java texture in a VideoFrameBuffer. -class SurfaceTextureHelper : public rtc::RefCountInterface { - public: - // Might return null if creating the Java SurfaceTextureHelper fails. - static rtc::scoped_refptr create( - JNIEnv* jni, const char* thread_name, jobject j_egl_context); - - jobject GetJavaSurfaceTextureHelper() const; - - rtc::scoped_refptr CreateTextureFrame( - int width, - int height, - const NativeHandleImpl& native_handle); - - protected: - ~SurfaceTextureHelper(); - SurfaceTextureHelper(JNIEnv* jni, jobject j_surface_texture_helper); - - private: - // May be called on arbitrary thread. - void ReturnTextureFrame() const; - - const ScopedGlobalRef j_surface_texture_helper_; - const jmethodID j_return_texture_method_; -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_SURFACETEXTUREHELPER_JNI_H_ diff --git a/include/webrtc/api/jsep.h b/include/webrtc/api/jsep.h index e11a2ad..aa6e9a1 100644 --- a/include/webrtc/api/jsep.h +++ b/include/webrtc/api/jsep.h @@ -8,15 +8,23 @@ * be found in the AUTHORS file in the root of the source tree. */ -// Interfaces matching the draft-ietf-rtcweb-jsep-01. +// This file contains declarations of interfaces that wrap SDP-related +// constructs; session descriptions and ICE candidates. The inner "cricket::" +// objects shouldn't be accessed directly; the intention is that an application +// using the PeerConnection API only creates these objects from strings, and +// them passes them into the PeerConnection. +// +// Though in the future, we're planning to provide an SDP parsing API, with a +// structure more friendly than cricket::SessionDescription. #ifndef WEBRTC_API_JSEP_H_ #define WEBRTC_API_JSEP_H_ +#include + #include #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/refcount.h" namespace cricket { @@ -35,34 +43,40 @@ struct SdpParseError { }; // Class representation of an ICE candidate. +// // An instance of this interface is supposed to be owned by one class at // a time and is therefore not expected to be thread safe. +// +// An instance can be created by CreateIceCandidate. class IceCandidateInterface { public: virtual ~IceCandidateInterface() {} - /// If present, this contains the identierfier of the "media stream - // identification" as defined in [RFC 3388] for m-line this candidate is - // assocated with. + // If present, this is the value of the "a=mid" attribute of the candidate's + // m= section in SDP, which identifies the m= section. virtual std::string sdp_mid() const = 0; - // This indeicates the index (starting at zero) of m-line in the SDP this - // candidate is assocated with. + // This indicates the index (starting at zero) of m= section this candidate + // is assocated with. Needed when an endpoint doesn't support MIDs. virtual int sdp_mline_index() const = 0; + // Only for use internally. virtual const cricket::Candidate& candidate() const = 0; + // The URL of the ICE server which this candidate was gathered from. + // TODO(zhihuang): Remove the default implementation once the subclasses + // implement this method. + virtual std::string server_url() const { return ""; } // Creates a SDP-ized form of this candidate. virtual bool ToString(std::string* out) const = 0; }; // Creates a IceCandidateInterface based on SDP string. -// Returns NULL if the sdp string can't be parsed. -// |error| can be NULL if doesn't care about the failure reason. +// Returns null if the sdp string can't be parsed. +// |error| may be null. IceCandidateInterface* CreateIceCandidate(const std::string& sdp_mid, int sdp_mline_index, const std::string& sdp, SdpParseError* error); -// This class represents a collection of candidates for a specific m-line. -// This class is used in SessionDescriptionInterface to represent all known -// candidates for a certain m-line. +// This class represents a collection of candidates for a specific m= section. +// Used in SessionDescriptionInterface. class IceCandidateCollection { public: virtual ~IceCandidateCollection() {} @@ -72,9 +86,12 @@ class IceCandidateCollection { virtual const IceCandidateInterface* at(size_t index) const = 0; }; -// Class representation of a Session description. -// An instance of this interface is supposed to be owned by one class at -// a time and is therefore not expected to be thread safe. +// Class representation of an SDP session description. +// +// An instance of this interface is supposed to be owned by one class at a time +// and is therefore not expected to be thread safe. +// +// An instance can be created by CreateSessionDescription. class SessionDescriptionInterface { public: // Supported types: @@ -83,44 +100,59 @@ class SessionDescriptionInterface { static const char kAnswer[]; virtual ~SessionDescriptionInterface() {} + + // Only for use internally. virtual cricket::SessionDescription* description() = 0; virtual const cricket::SessionDescription* description() const = 0; + // Get the session id and session version, which are defined based on // RFC 4566 for the SDP o= line. virtual std::string session_id() const = 0; virtual std::string session_version() const = 0; + + // kOffer/kPrAnswer/kAnswer virtual std::string type() const = 0; + // Adds the specified candidate to the description. + // // Ownership is not transferred. - // Returns false if the session description does not have a media section that - // corresponds to the |candidate| label. + // + // Returns false if the session description does not have a media section + // that corresponds to |candidate.sdp_mid()| or + // |candidate.sdp_mline_index()|. virtual bool AddCandidate(const IceCandidateInterface* candidate) = 0; - // Removes the candidates from the description. + + // Removes the candidates from the description, if found. + // // Returns the number of candidates removed. virtual size_t RemoveCandidates( const std::vector& candidates) { return 0; } - // Returns the number of m- lines in the session description. + // Returns the number of m= sections in the session description. virtual size_t number_of_mediasections() const = 0; - // Returns a collection of all candidates that belong to a certain m-line + + // Returns a collection of all candidates that belong to a certain m= + // section. virtual const IceCandidateCollection* candidates( size_t mediasection_index) const = 0; + // Serializes the description to SDP. virtual bool ToString(std::string* out) const = 0; }; -// Creates a SessionDescriptionInterface based on SDP string and the type. -// Returns NULL if the sdp string can't be parsed or the type is unsupported. -// |error| can be NULL if doesn't care about the failure reason. +// Creates a SessionDescriptionInterface based on the SDP string and the type. +// Returns null if the sdp string can't be parsed or the type is unsupported. +// |error| may be null. SessionDescriptionInterface* CreateSessionDescription(const std::string& type, const std::string& sdp, SdpParseError* error); -// Jsep CreateOffer and CreateAnswer callback interface. +// CreateOffer and CreateAnswer callback interface. class CreateSessionDescriptionObserver : public rtc::RefCountInterface { public: - // The implementation of the CreateSessionDescriptionObserver takes - // the ownership of the |desc|. + // This callback transfers the ownership of the |desc|. + // TODO(deadbeef): Make this take an std::unique_ptr<> to avoid confusion + // around ownership. virtual void OnSuccess(SessionDescriptionInterface* desc) = 0; virtual void OnFailure(const std::string& error) = 0; @@ -128,7 +160,7 @@ class CreateSessionDescriptionObserver : public rtc::RefCountInterface { ~CreateSessionDescriptionObserver() {} }; -// Jsep SetLocalDescription and SetRemoteDescription callback interface. +// SetLocalDescription and SetRemoteDescription callback interface. class SetSessionDescriptionObserver : public rtc::RefCountInterface { public: virtual void OnSuccess() = 0; diff --git a/include/webrtc/api/jsepicecandidate.h b/include/webrtc/api/jsepicecandidate.h index 7e9500b..3566013 100644 --- a/include/webrtc/api/jsepicecandidate.h +++ b/include/webrtc/api/jsepicecandidate.h @@ -8,12 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ -// Implements the IceCandidateInterface. +// TODO(deadbeef): Move this out of api/; it's an implementation detail and +// shouldn't be used externally. #ifndef WEBRTC_API_JSEPICECANDIDATE_H_ #define WEBRTC_API_JSEPICECANDIDATE_H_ #include +#include +#include #include "webrtc/api/jsep.h" #include "webrtc/base/constructormagic.h" @@ -21,13 +24,14 @@ namespace webrtc { +// Implementation of IceCandidateInterface. class JsepIceCandidate : public IceCandidateInterface { public: JsepIceCandidate(const std::string& sdp_mid, int sdp_mline_index); JsepIceCandidate(const std::string& sdp_mid, int sdp_mline_index, const cricket::Candidate& candidate); ~JsepIceCandidate(); - // |error| can be NULL if don't care about the failure reason. + // |err| may be null. bool Initialize(const std::string& sdp, SdpParseError* err); void SetCandidate(const cricket::Candidate& candidate) { candidate_ = candidate; @@ -39,6 +43,8 @@ class JsepIceCandidate : public IceCandidateInterface { return candidate_; } + virtual std::string server_url() const { return candidate_.url(); } + virtual bool ToString(std::string* out) const; private: @@ -49,8 +55,7 @@ class JsepIceCandidate : public IceCandidateInterface { RTC_DISALLOW_COPY_AND_ASSIGN(JsepIceCandidate); }; -// Implementation of IceCandidateCollection. -// This implementation stores JsepIceCandidates. +// Implementation of IceCandidateCollection which stores JsepIceCandidates. class JsepCandidateCollection : public IceCandidateCollection { public: JsepCandidateCollection() {} @@ -64,6 +69,8 @@ class JsepCandidateCollection : public IceCandidateCollection { } virtual bool HasCandidate(const IceCandidateInterface* candidate) const; // Adds and takes ownership of the JsepIceCandidate. + // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is + // more clear. virtual void add(JsepIceCandidate* candidate) { candidates_.push_back(candidate); } @@ -71,6 +78,7 @@ class JsepCandidateCollection : public IceCandidateCollection { return candidates_[index]; } // Removes the candidate that has a matching address and protocol. + // // Returns the number of candidates that were removed. size_t remove(const cricket::Candidate& candidate); diff --git a/include/webrtc/api/jsepsessiondescription.h b/include/webrtc/api/jsepsessiondescription.h index 0248a07..e4855b9 100644 --- a/include/webrtc/api/jsepsessiondescription.h +++ b/include/webrtc/api/jsepsessiondescription.h @@ -8,7 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -// Implements the SessionDescriptionInterface. +// TODO(deadbeef): Move this out of api/; it's an implementation detail and +// shouldn't be used externally. #ifndef WEBRTC_API_JSEPSESSIONDESCRIPTION_H_ #define WEBRTC_API_JSEPSESSIONDESCRIPTION_H_ @@ -28,15 +29,18 @@ class SessionDescription; namespace webrtc { +// Implementation of SessionDescriptionInterface. class JsepSessionDescription : public SessionDescriptionInterface { public: explicit JsepSessionDescription(const std::string& type); virtual ~JsepSessionDescription(); - // |error| can be NULL if don't care about the failure reason. + // |error| may be null. bool Initialize(const std::string& sdp, SdpParseError* error); // Takes ownership of |description|. + // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is + // more clear. bool Initialize(cricket::SessionDescription* description, const std::string& session_id, const std::string& session_version); @@ -56,7 +60,7 @@ class JsepSessionDescription : public SessionDescriptionInterface { virtual std::string type() const { return type_; } - // Allow changing the type. Used for testing. + // Allows changing the type. Used for testing. void set_type(const std::string& type) { type_ = type; } virtual bool AddCandidate(const IceCandidateInterface* candidate); virtual size_t RemoveCandidates( @@ -66,13 +70,8 @@ class JsepSessionDescription : public SessionDescriptionInterface { size_t mediasection_index) const; virtual bool ToString(std::string* out) const; - // Default video encoder settings. The resolution is the max resolution. - // TODO(perkj): Implement proper negotiation of video resolution. static const int kDefaultVideoCodecId; - static const int kDefaultVideoCodecFramerate; static const char kDefaultVideoCodecName[]; - static const int kMaxVideoCodecWidth; - static const int kMaxVideoCodecHeight; private: std::unique_ptr description_; diff --git a/include/webrtc/api/mediaconstraintsinterface.h b/include/webrtc/api/mediaconstraintsinterface.h index 13560dd..8dafea4 100644 --- a/include/webrtc/api/mediaconstraintsinterface.h +++ b/include/webrtc/api/mediaconstraintsinterface.h @@ -28,9 +28,12 @@ namespace webrtc { -// MediaConstraintsInterface // Interface used for passing arguments about media constraints // to the MediaStream and PeerConnection implementation. +// +// Constraints may be either "mandatory", which means that unless satisfied, +// the method taking the constraints should fail, or "optional", which means +// they may not be satisfied.. class MediaConstraintsInterface { public: struct Constraint { @@ -74,9 +77,14 @@ class MediaConstraintsInterface { static const char kNoiseSuppression[]; // googNoiseSuppression static const char kExperimentalNoiseSuppression[]; // googNoiseSuppression2 static const char kIntelligibilityEnhancer[]; // intelligibilityEnhancer + static const char kLevelControl[]; // levelControl + static const char + kLevelControlInitialPeakLevelDBFS[]; // levelControlInitialPeakLevelDBFS static const char kHighpassFilter[]; // googHighpassFilter static const char kTypingNoiseDetection[]; // googTypingNoiseDetection static const char kAudioMirroring[]; // googAudioMirroring + static const char + kAudioNetworkAdaptorConfig[]; // goodAudioNetworkAdaptorConfig // Google-specific constraint keys for a local video source static const char kNoiseReduction[]; // googNoiseReduction @@ -136,6 +144,11 @@ void CopyConstraintsIntoRtcConfiguration( const MediaConstraintsInterface* constraints, PeerConnectionInterface::RTCConfiguration* configuration); +// Copy all relevant constraints into an AudioOptions object. +void CopyConstraintsIntoAudioOptions( + const MediaConstraintsInterface* constraints, + cricket::AudioOptions* options); + } // namespace webrtc #endif // WEBRTC_API_MEDIACONSTRAINTSINTERFACE_H_ diff --git a/include/webrtc/api/mediacontroller.h b/include/webrtc/api/mediacontroller.h index d7c76ab..9c2b708 100644 --- a/include/webrtc/api/mediacontroller.h +++ b/include/webrtc/api/mediacontroller.h @@ -11,32 +11,8 @@ #ifndef WEBRTC_API_MEDIACONTROLLER_H_ #define WEBRTC_API_MEDIACONTROLLER_H_ -#include "webrtc/base/thread.h" - -namespace cricket { -class ChannelManager; -struct MediaConfig; -} // namespace cricket - -namespace webrtc { -class Call; -class VoiceEngine; - -// The MediaController currently owns shared state between media channels, but -// in the future will create and own RtpSenders and RtpReceivers. -class MediaControllerInterface { - public: - static MediaControllerInterface* Create( - const cricket::MediaConfig& config, - rtc::Thread* worker_thread, - cricket::ChannelManager* channel_manager); - - virtual ~MediaControllerInterface() {} - virtual void Close() = 0; - virtual webrtc::Call* call_w() = 0; - virtual cricket::ChannelManager* channel_manager() const = 0; - virtual const cricket::MediaConfig& config() const = 0; -}; -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/mediacontroller.h" #endif // WEBRTC_API_MEDIACONTROLLER_H_ diff --git a/include/webrtc/api/mediastream.h b/include/webrtc/api/mediastream.h index 1f80f25..e6556c5 100644 --- a/include/webrtc/api/mediastream.h +++ b/include/webrtc/api/mediastream.h @@ -1,5 +1,5 @@ /* - * Copyright 2011 The WebRTC project authors. All Rights Reserved. + * Copyright 2015 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -8,51 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -// This file contains the implementation of MediaStreamInterface interface. - #ifndef WEBRTC_API_MEDIASTREAM_H_ #define WEBRTC_API_MEDIASTREAM_H_ -#include -#include - -#include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/notifier.h" - -namespace webrtc { - -class MediaStream : public Notifier { - public: - static rtc::scoped_refptr Create(const std::string& label); - - std::string label() const override { return label_; } - - bool AddTrack(AudioTrackInterface* track) override; - bool AddTrack(VideoTrackInterface* track) override; - bool RemoveTrack(AudioTrackInterface* track) override; - bool RemoveTrack(VideoTrackInterface* track) override; - rtc::scoped_refptr - FindAudioTrack(const std::string& track_id) override; - rtc::scoped_refptr - FindVideoTrack(const std::string& track_id) override; - - AudioTrackVector GetAudioTracks() override { return audio_tracks_; } - VideoTrackVector GetVideoTracks() override { return video_tracks_; } - - protected: - explicit MediaStream(const std::string& label); - - private: - template - bool AddTrack(TrackVector* Tracks, Track* track); - template - bool RemoveTrack(TrackVector* Tracks, MediaStreamTrackInterface* track); - - std::string label_; - AudioTrackVector audio_tracks_; - VideoTrackVector video_tracks_; -}; - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/mediastream.h" #endif // WEBRTC_API_MEDIASTREAM_H_ diff --git a/include/webrtc/api/mediastreamhandler.h b/include/webrtc/api/mediastreamhandler.h deleted file mode 100644 index 4679037..0000000 --- a/include/webrtc/api/mediastreamhandler.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// TODO(deadbeef): Remove this file once Chrome build files no longer reference -// it. diff --git a/include/webrtc/api/mediastreaminterface.h b/include/webrtc/api/mediastreaminterface.h index 7f56325..2d16e52 100644 --- a/include/webrtc/api/mediastreaminterface.h +++ b/include/webrtc/api/mediastreaminterface.h @@ -17,10 +17,16 @@ #ifndef WEBRTC_API_MEDIASTREAMINTERFACE_H_ #define WEBRTC_API_MEDIASTREAMINTERFACE_H_ +#include + #include #include -#include "webrtc/base/basictypes.h" +#include "webrtc/api/video/video_frame.h" +// TODO(nisse): Transition hack, Chrome expects that including this +// file declares I420Buffer. Delete after users of I420Buffer are +// fixed to include the new header. +#include "webrtc/api/video/i420_buffer.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/optional.h" @@ -28,14 +34,6 @@ #include "webrtc/media/base/videosinkinterface.h" #include "webrtc/media/base/videosourceinterface.h" -namespace cricket { - -class AudioRenderer; -class VideoRenderer; -class VideoFrame; - -} // namespace cricket - namespace webrtc { // Generic observer interface. @@ -55,8 +53,8 @@ class NotifierInterface { virtual ~NotifierInterface() {} }; -// Base class for sources. A MediaStreamTrack have an underlying source that -// provide media. A source can be shared with multiple tracks. +// Base class for sources. A MediaStreamTrack has an underlying source that +// provides media. A source can be shared by multiple tracks. class MediaSourceInterface : public rtc::RefCountInterface, public NotifierInterface { public: @@ -75,7 +73,8 @@ class MediaSourceInterface : public rtc::RefCountInterface, virtual ~MediaSourceInterface() {} }; -// Information about a track. +// C++ version of MediaStreamTrack. +// See: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack class MediaStreamTrackInterface : public rtc::RefCountInterface, public NotifierInterface { public: @@ -92,20 +91,27 @@ class MediaStreamTrackInterface : public rtc::RefCountInterface, // object is a subclass of VideoTrackInterface. It is typically used // to protect a static_cast<> to the corresponding subclass. virtual std::string kind() const = 0; + + // Track identifier. virtual std::string id() const = 0; + + // A disabled track will produce silence (if audio) or black frames (if + // video). Can be disabled and re-enabled. virtual bool enabled() const = 0; - virtual TrackState state() const = 0; virtual bool set_enabled(bool enable) = 0; + // Live or ended. A track will never be live again after becoming ended. + virtual TrackState state() const = 0; + protected: virtual ~MediaStreamTrackInterface() {} }; -// VideoTrackSourceInterface is a reference counted source used for VideoTracks. -// The same source can be used in multiple VideoTracks. +// VideoTrackSourceInterface is a reference counted source used for +// VideoTracks. The same source can be used by multiple VideoTracks. class VideoTrackSourceInterface : public MediaSourceInterface, - public rtc::VideoSourceInterface { + public rtc::VideoSourceInterface { public: struct Stats { // Original size of captured frame, before video adaptation. @@ -113,13 +119,10 @@ class VideoTrackSourceInterface int input_height; }; - virtual void Stop() = 0; - virtual void Restart() = 0; - // Indicates that parameters suitable for screencasts should be automatically // applied to RtpSenders. // TODO(perkj): Remove these once all known applications have moved to - // explicitly setting suitable parameters for screencasts and dont' need this + // explicitly setting suitable parameters for screencasts and don't need this // implicit behavior. virtual bool is_screencast() const = 0; @@ -130,9 +133,10 @@ class VideoTrackSourceInterface // the encoder. virtual rtc::Optional needs_denoising() const = 0; - // Returns false if no stats are available, e.g, for a remote - // source, or a source which has not seen its first frame yet. - // Should avoid blocking. + // Returns false if no stats are available, e.g, for a remote source, or a + // source which has not seen its first frame yet. + // + // Implementation should avoid blocking. virtual bool GetStats(Stats* stats) = 0; protected: @@ -141,16 +145,24 @@ class VideoTrackSourceInterface class VideoTrackInterface : public MediaStreamTrackInterface, - public rtc::VideoSourceInterface { + public rtc::VideoSourceInterface { public: - // Register a video sink for this track. - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override{}; - void RemoveSink( - rtc::VideoSinkInterface* sink) override{}; + // Video track content hint, used to override the source is_screencast + // property. + // See https://crbug.com/653531 and https://github.com/WICG/mst-content-hint. + enum class ContentHint { kNone, kFluid, kDetailed }; + + // Register a video sink for this track. Used to connect the track to the + // underlying video engine. + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override {} + void RemoveSink(rtc::VideoSinkInterface* sink) override {} virtual VideoTrackSourceInterface* GetSource() const = 0; + virtual ContentHint content_hint() const { return ContentHint::kNone; } + virtual void set_content_hint(ContentHint hint) {} + protected: virtual ~VideoTrackInterface() {} }; @@ -169,7 +181,7 @@ class AudioTrackSinkInterface { }; // AudioSourceInterface is a reference counted source used for AudioTracks. -// The same source can be used in multiple AudioTracks. +// The same source can be used by multiple AudioTracks. class AudioSourceInterface : public MediaSourceInterface { public: class AudioObserver { @@ -180,14 +192,15 @@ class AudioSourceInterface : public MediaSourceInterface { virtual ~AudioObserver() {} }; - // TODO(xians): Makes all the interface pure virtual after Chrome has their - // implementations. - // Sets the volume to the source. |volume| is in the range of [0, 10]. + // TODO(deadbeef): Makes all the interfaces pure virtual after they're + // implemented in chromium. + + // Sets the volume of the source. |volume| is in the range of [0, 10]. // TODO(tommi): This method should be on the track and ideally volume should // be applied in the track in a way that does not affect clones of the track. virtual void SetVolume(double volume) {} - // Registers/unregisters observer to the audio source. + // Registers/unregisters observers to the audio source. virtual void RegisterAudioObserver(AudioObserver* observer) {} virtual void UnregisterAudioObserver(AudioObserver* observer) {} @@ -201,21 +214,26 @@ class AudioSourceInterface : public MediaSourceInterface { class AudioProcessorInterface : public rtc::RefCountInterface { public: struct AudioProcessorStats { - AudioProcessorStats() : typing_noise_detected(false), - echo_return_loss(0), - echo_return_loss_enhancement(0), - echo_delay_median_ms(0), - aec_quality_min(0.0), - echo_delay_std_ms(0), - aec_divergent_filter_fraction(0.0) {} + AudioProcessorStats() + : typing_noise_detected(false), + echo_return_loss(0), + echo_return_loss_enhancement(0), + echo_delay_median_ms(0), + echo_delay_std_ms(0), + aec_quality_min(0.0), + residual_echo_likelihood(0.0f), + residual_echo_likelihood_recent_max(0.0f), + aec_divergent_filter_fraction(0.0) {} ~AudioProcessorStats() {} bool typing_noise_detected; int echo_return_loss; int echo_return_loss_enhancement; int echo_delay_median_ms; - float aec_quality_min; int echo_delay_std_ms; + float aec_quality_min; + float residual_echo_likelihood; + float residual_echo_likelihood_recent_max; float aec_divergent_filter_fraction; }; @@ -228,7 +246,8 @@ class AudioProcessorInterface : public rtc::RefCountInterface { class AudioTrackInterface : public MediaStreamTrackInterface { public: - // TODO(xians): Figure out if the following interface should be const or not. + // TODO(deadbeef): Figure out if the following interface should be const or + // not. virtual AudioSourceInterface* GetSource() const = 0; // Add/Remove a sink that will receive the audio data from the track. @@ -237,15 +256,16 @@ class AudioTrackInterface : public MediaStreamTrackInterface { // Get the signal level from the audio track. // Return true on success, otherwise false. - // TODO(xians): Change the interface to int GetSignalLevel() and pure virtual - // after Chrome has the correct implementation of the interface. + // TODO(deadbeef): Change the interface to int GetSignalLevel() and pure + // virtual after it's implemented in chromium. virtual bool GetSignalLevel(int* level) { return false; } - // Get the audio processor used by the audio track. Return NULL if the track + // Get the audio processor used by the audio track. Return null if the track // does not have any processor. - // TODO(xians): Make the interface pure virtual. - virtual rtc::scoped_refptr - GetAudioProcessor() { return NULL; } + // TODO(deadbeef): Make the interface pure virtual. + virtual rtc::scoped_refptr GetAudioProcessor() { + return nullptr; + } protected: virtual ~AudioTrackInterface() {} @@ -256,6 +276,14 @@ typedef std::vector > typedef std::vector > VideoTrackVector; +// C++ version of https://www.w3.org/TR/mediacapture-streams/#mediastream. +// +// A major difference is that remote audio/video tracks (received by a +// PeerConnection/RtpReceiver) are not synchronized simply by adding them to +// the same stream; a session description with the correct "a=msid" attributes +// must be pushed down. +// +// Thus, this interface acts as simply a container for tracks. class MediaStreamInterface : public rtc::RefCountInterface, public NotifierInterface { public: diff --git a/include/webrtc/api/mediastreamprovider.h b/include/webrtc/api/mediastreamprovider.h deleted file mode 100644 index b23e17b..0000000 --- a/include/webrtc/api/mediastreamprovider.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_API_MEDIASTREAMPROVIDER_H_ -#define WEBRTC_API_MEDIASTREAMPROVIDER_H_ - -#include - -#include "webrtc/api/rtpsenderinterface.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/media/base/videosinkinterface.h" -#include "webrtc/media/base/videosourceinterface.h" - -namespace cricket { - -class AudioSource; -class VideoFrame; -struct AudioOptions; -struct VideoOptions; - -} // namespace cricket - -namespace webrtc { - -class AudioSinkInterface; - -// TODO(deadbeef): Change the key from an ssrc to a "sender_id" or -// "receiver_id" string, which will be the MSID in the short term and MID in -// the long term. - -// TODO(deadbeef): These interfaces are effectively just a way for the -// RtpSenders/Receivers to get to the BaseChannels. These interfaces should be -// refactored away eventually, as the classes converge. - -// This interface is called by AudioRtpSender/Receivers to change the settings -// of an audio track connected to certain PeerConnection. -class AudioProviderInterface { - public: - // Enable/disable the audio playout of a remote audio track with |ssrc|. - virtual void SetAudioPlayout(uint32_t ssrc, bool enable) = 0; - // Enable/disable sending audio on the local audio track with |ssrc|. - // When |enable| is true |options| should be applied to the audio track. - virtual void SetAudioSend(uint32_t ssrc, - bool enable, - const cricket::AudioOptions& options, - cricket::AudioSource* source) = 0; - - // Sets the audio playout volume of a remote audio track with |ssrc|. - // |volume| is in the range of [0, 10]. - virtual void SetAudioPlayoutVolume(uint32_t ssrc, double volume) = 0; - - // Allows for setting a direct audio sink for an incoming audio source. - // Only one audio sink is supported per ssrc and ownership of the sink is - // passed to the provider. - virtual void SetRawAudioSink( - uint32_t ssrc, - std::unique_ptr sink) = 0; - - virtual RtpParameters GetAudioRtpSendParameters(uint32_t ssrc) const = 0; - virtual bool SetAudioRtpSendParameters(uint32_t ssrc, - const RtpParameters& parameters) = 0; - - virtual RtpParameters GetAudioRtpReceiveParameters(uint32_t ssrc) const = 0; - virtual bool SetAudioRtpReceiveParameters( - uint32_t ssrc, - const RtpParameters& parameters) = 0; - - protected: - virtual ~AudioProviderInterface() {} -}; - -// This interface is called by VideoRtpSender/Receivers to change the settings -// of a video track connected to a certain PeerConnection. -class VideoProviderInterface { - public: - virtual bool SetSource( - uint32_t ssrc, - rtc::VideoSourceInterface* source) = 0; - // Enable/disable the video playout of a remote video track with |ssrc|. - virtual void SetVideoPlayout( - uint32_t ssrc, - bool enable, - rtc::VideoSinkInterface* sink) = 0; - // Enable sending video on the local video track with |ssrc|. - virtual void SetVideoSend(uint32_t ssrc, - bool enable, - const cricket::VideoOptions* options) = 0; - - virtual RtpParameters GetVideoRtpSendParameters(uint32_t ssrc) const = 0; - virtual bool SetVideoRtpSendParameters(uint32_t ssrc, - const RtpParameters& parameters) = 0; - - virtual RtpParameters GetVideoRtpReceiveParameters(uint32_t ssrc) const = 0; - virtual bool SetVideoRtpReceiveParameters( - uint32_t ssrc, - const RtpParameters& parameters) = 0; - - protected: - virtual ~VideoProviderInterface() {} -}; - -} // namespace webrtc - -#endif // WEBRTC_API_MEDIASTREAMPROVIDER_H_ diff --git a/include/webrtc/api/mediastreamproxy.h b/include/webrtc/api/mediastreamproxy.h index 06f8eb3..15b40ed 100644 --- a/include/webrtc/api/mediastreamproxy.h +++ b/include/webrtc/api/mediastreamproxy.h @@ -11,26 +11,33 @@ #ifndef WEBRTC_API_MEDIASTREAMPROXY_H_ #define WEBRTC_API_MEDIASTREAMPROXY_H_ +#include + #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/proxy.h" namespace webrtc { +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_SIGNALING_PROXY_MAP(MediaStream) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, label) PROXY_METHOD0(AudioTrackVector, GetAudioTracks) PROXY_METHOD0(VideoTrackVector, GetVideoTracks) PROXY_METHOD1(rtc::scoped_refptr, - FindAudioTrack, const std::string&) + FindAudioTrack, + const std::string&) PROXY_METHOD1(rtc::scoped_refptr, - FindVideoTrack, const std::string&) + FindVideoTrack, + const std::string&) PROXY_METHOD1(bool, AddTrack, AudioTrackInterface*) PROXY_METHOD1(bool, AddTrack, VideoTrackInterface*) PROXY_METHOD1(bool, RemoveTrack, AudioTrackInterface*) PROXY_METHOD1(bool, RemoveTrack, VideoTrackInterface*) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/mediastreamtrack.h b/include/webrtc/api/mediastreamtrack.h index 9ba0420..6075abe 100644 --- a/include/webrtc/api/mediastreamtrack.h +++ b/include/webrtc/api/mediastreamtrack.h @@ -11,52 +11,8 @@ #ifndef WEBRTC_API_MEDIASTREAMTRACK_H_ #define WEBRTC_API_MEDIASTREAMTRACK_H_ -#include - -#include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/notifier.h" - -namespace webrtc { - -// MediaTrack implements the interface common to AudioTrackInterface and -// VideoTrackInterface. -template -class MediaStreamTrack : public Notifier { - public: - typedef typename T::TrackState TypedTrackState; - - std::string id() const override { return id_; } - MediaStreamTrackInterface::TrackState state() const override { - return state_; - } - bool enabled() const override { return enabled_; } - bool set_enabled(bool enable) override { - bool fire_on_change = (enable != enabled_); - enabled_ = enable; - if (fire_on_change) { - Notifier::FireOnChanged(); - } - return fire_on_change; - } - - protected: - explicit MediaStreamTrack(const std::string& id) - : enabled_(true), id_(id), state_(MediaStreamTrackInterface::kLive) {} - - bool set_state(MediaStreamTrackInterface::TrackState new_state) { - bool fire_on_change = (state_ != new_state); - state_ = new_state; - if (fire_on_change) - Notifier::FireOnChanged(); - return true; - } - - private: - bool enabled_; - std::string id_; - MediaStreamTrackInterface::TrackState state_; -}; - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/mediastreamtrack.h" #endif // WEBRTC_API_MEDIASTREAMTRACK_H_ diff --git a/include/webrtc/api/mediastreamtrackproxy.h b/include/webrtc/api/mediastreamtrackproxy.h index 12fdc36..605f3f2 100644 --- a/include/webrtc/api/mediastreamtrackproxy.h +++ b/include/webrtc/api/mediastreamtrackproxy.h @@ -14,12 +14,18 @@ #ifndef WEBRTC_API_MEDIASTREAMTRACKPROXY_H_ #define WEBRTC_API_MEDIASTREAMTRACKPROXY_H_ +#include + #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/proxy.h" namespace webrtc { +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. + BEGIN_SIGNALING_PROXY_MAP(AudioTrack) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, kind) PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(TrackState, state) @@ -28,31 +34,31 @@ BEGIN_SIGNALING_PROXY_MAP(AudioTrack) PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*) PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*) PROXY_METHOD1(bool, GetSignalLevel, int*) - PROXY_METHOD0(rtc::scoped_refptr, - GetAudioProcessor) + PROXY_METHOD0(rtc::scoped_refptr, GetAudioProcessor) PROXY_METHOD1(bool, set_enabled, bool) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_SIGNALING_PROXY() +END_PROXY_MAP() BEGIN_PROXY_MAP(VideoTrack) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, kind) PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(TrackState, state) PROXY_CONSTMETHOD0(bool, enabled) PROXY_METHOD1(bool, set_enabled, bool) + PROXY_CONSTMETHOD0(ContentHint, content_hint) + PROXY_METHOD1(void, set_content_hint, ContentHint) PROXY_WORKER_METHOD2(void, - AddOrUpdateSink, - rtc::VideoSinkInterface*, - const rtc::VideoSinkWants&) - PROXY_WORKER_METHOD1(void, - RemoveSink, - rtc::VideoSinkInterface*) + AddOrUpdateSink, + rtc::VideoSinkInterface*, + const rtc::VideoSinkWants&) + PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface*) PROXY_CONSTMETHOD0(VideoTrackSourceInterface*, GetSource) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/mediatypes.h b/include/webrtc/api/mediatypes.h new file mode 100644 index 0000000..ec3a70a --- /dev/null +++ b/include/webrtc/api/mediatypes.h @@ -0,0 +1,31 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_MEDIATYPES_H_ +#define WEBRTC_API_MEDIATYPES_H_ + +#include + +namespace cricket { + +enum MediaType { + MEDIA_TYPE_AUDIO, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_DATA +}; + +std::string MediaTypeToString(MediaType type); +// Aborts on invalid string. Only expected to be used on strings that are +// guaranteed to be valid, such as MediaStreamTrackInterface::kind(). +MediaType MediaTypeFromString(const std::string& type_str); + +} // namespace cricket + +#endif // WEBRTC_API_MEDIATYPES_H_ diff --git a/include/webrtc/api/notifier.h b/include/webrtc/api/notifier.h index 8be9ffe..d883051 100644 --- a/include/webrtc/api/notifier.h +++ b/include/webrtc/api/notifier.h @@ -14,11 +14,12 @@ #include #include "webrtc/api/mediastreaminterface.h" -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" namespace webrtc { -// Implement a template version of a notifier. +// Implements a template version of a notifier. +// TODO(deadbeef): This is an implementation detail; move out of api/. template class Notifier : public T { public: @@ -26,7 +27,7 @@ class Notifier : public T { } virtual void RegisterObserver(ObserverInterface* observer) { - ASSERT(observer != NULL); + RTC_DCHECK(observer != nullptr); observers_.push_back(observer); } diff --git a/include/webrtc/api/ortc/ortcfactoryinterface.h b/include/webrtc/api/ortc/ortcfactoryinterface.h new file mode 100644 index 0000000..855e3b0 --- /dev/null +++ b/include/webrtc/api/ortc/ortcfactoryinterface.h @@ -0,0 +1,230 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_ +#define WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_ + +#include +#include +#include // For std::move. + +#include "webrtc/api/mediaconstraintsinterface.h" +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/mediatypes.h" +#include "webrtc/api/ortc/ortcrtpreceiverinterface.h" +#include "webrtc/api/ortc/ortcrtpsenderinterface.h" +#include "webrtc/api/ortc/packettransportinterface.h" +#include "webrtc/api/ortc/rtptransportcontrollerinterface.h" +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/api/ortc/udptransportinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" +#include "webrtc/base/network.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/base/thread.h" +#include "webrtc/p2p/base/packetsocketfactory.h" + +namespace webrtc { + +// TODO(deadbeef): This should be part of /api/, but currently it's not and +// including its header violates checkdeps rules. +class AudioDeviceModule; + +// WARNING: This is experimental/under development, so use at your own risk; no +// guarantee about API stability is guaranteed here yet. +// +// This class is the ORTC analog of PeerConnectionFactory. It acts as a factory +// for ORTC objects that can be connected to each other. +// +// Some of these objects may not be represented by the ORTC specification, but +// follow the same general principles. +// +// If one of the factory methods takes another object as an argument, it MUST +// have been created by the same OrtcFactory. +// +// On object lifetimes: objects should be destroyed in this order: +// 1. Objects created by the factory. +// 2. The factory itself. +// 3. Objects passed into OrtcFactoryInterface::Create. +class OrtcFactoryInterface { + public: + // |network_thread| is the thread on which packets are sent and received. + // If null, a new rtc::Thread with a default socket server is created. + // + // |signaling_thread| is used for callbacks to the consumer of the API. If + // null, the current thread will be used, which assumes that the API consumer + // is running a message loop on this thread (either using an existing + // rtc::Thread, or by calling rtc::Thread::Current()->ProcessMessages). + // + // |network_manager| is used to determine which network interfaces are + // available. This is used for ICE, for example. If null, a default + // implementation will be used. Only accessed on |network_thread|. + // + // |socket_factory| is used (on the network thread) for creating sockets. If + // it's null, a default implementation will be used, which assumes + // |network_thread| is a normal rtc::Thread. + // + // |adm| is optional, and allows a different audio device implementation to + // be injected; otherwise a platform-specific module will be used that will + // use the default audio input. + // + // Note that the OrtcFactoryInterface does not take ownership of any of the + // objects passed in, and as previously stated, these objects can't be + // destroyed before the factory is. + static RTCErrorOr> Create( + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + AudioDeviceModule* adm); + + // Constructor for convenience which uses default implementations of + // everything (though does still require that the current thread runs a + // message loop; see above). + static RTCErrorOr> Create() { + return Create(nullptr, nullptr, nullptr, nullptr, nullptr); + } + + virtual ~OrtcFactoryInterface() {} + + // Creates an RTP transport controller, which is used in calls to + // CreateRtpTransport methods. If your application has some notion of a + // "call", you should create one transport controller per call. + // + // However, if you only are using one RtpTransport object, this doesn't need + // to be called explicitly; CreateRtpTransport will create one automatically + // if |rtp_transport_controller| is null. See below. + // + // TODO(deadbeef): Add MediaConfig and RtcEventLog arguments? + virtual RTCErrorOr> + CreateRtpTransportController() = 0; + + // Creates an RTP transport using the provided packet transports and + // transport controller. + // + // |rtp| will be used for sending RTP packets, and |rtcp| for RTCP packets. + // + // |rtp| can't be null. |rtcp| must be non-null if and only if + // |rtcp_parameters.mux| is false, indicating that RTCP muxing isn't used. + // Note that if RTCP muxing isn't enabled initially, it can still enabled + // later through SetRtcpParameters. + // + // If |transport_controller| is null, one will automatically be created, and + // its lifetime managed by the returned RtpTransport. This should only be + // done if a single RtpTransport is being used to communicate with the remote + // endpoint. + virtual RTCErrorOr> CreateRtpTransport( + const RtcpParameters& rtcp_parameters, + PacketTransportInterface* rtp, + PacketTransportInterface* rtcp, + RtpTransportControllerInterface* transport_controller) = 0; + + // Returns the capabilities of an RTP sender of type |kind|. These + // capabilities can be used to determine what RtpParameters to use to create + // an RtpSender. + // + // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure. + virtual RtpCapabilities GetRtpSenderCapabilities( + cricket::MediaType kind) const = 0; + + // Creates an RTP sender with |track|. Will not start sending until Send is + // called. This is provided as a convenience; it's equivalent to calling + // CreateRtpSender with a kind (see below), followed by SetTrack. + // + // |track| and |transport| must not be null. + virtual RTCErrorOr> CreateRtpSender( + rtc::scoped_refptr track, + RtpTransportInterface* transport) = 0; + + // Overload of CreateRtpSender allows creating the sender without a track. + // + // |kind| must be MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO. + virtual RTCErrorOr> CreateRtpSender( + cricket::MediaType kind, + RtpTransportInterface* transport) = 0; + + // Returns the capabilities of an RTP receiver of type |kind|. These + // capabilities can be used to determine what RtpParameters to use to create + // an RtpReceiver. + // + // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure. + virtual RtpCapabilities GetRtpReceiverCapabilities( + cricket::MediaType kind) const = 0; + + // Creates an RTP receiver of type |kind|. Will not start receiving media + // until Receive is called. + // + // |kind| must be MEDIA_TYPE_AUDIO or MEDIA_TYPE_VIDEO. + // + // |transport| must not be null. + virtual RTCErrorOr> + CreateRtpReceiver(cricket::MediaType kind, + RtpTransportInterface* transport) = 0; + + // Create a UDP transport with IP address family |family|, using a port + // within the specified range. + // + // |family| must be AF_INET or AF_INET6. + // + // |min_port|/|max_port| values of 0 indicate no range restriction. + // + // Returns an error if the transport wasn't successfully created. + virtual RTCErrorOr> + CreateUdpTransport(int family, uint16_t min_port, uint16_t max_port) = 0; + + // Method for convenience that has no port range restrictions. + RTCErrorOr> CreateUdpTransport( + int family) { + return CreateUdpTransport(family, 0, 0); + } + + // NOTE: The methods below to create tracks/sources return scoped_refptrs + // rather than unique_ptrs, because these interfaces are also used with + // PeerConnection, where everything is ref-counted. + + // Creates a audio source representing the default microphone input. + // |options| decides audio processing settings. + virtual rtc::scoped_refptr CreateAudioSource( + const cricket::AudioOptions& options) = 0; + + // Version of the above method that uses default options. + rtc::scoped_refptr CreateAudioSource() { + return CreateAudioSource(cricket::AudioOptions()); + } + + // Creates a video source object wrapping and taking ownership of |capturer|. + // + // |constraints| can be used for selection of resolution and frame rate, and + // may be null if no constraints are desired. + virtual rtc::scoped_refptr CreateVideoSource( + std::unique_ptr capturer, + const MediaConstraintsInterface* constraints) = 0; + + // Version of the above method that omits |constraints|. + rtc::scoped_refptr CreateVideoSource( + std::unique_ptr capturer) { + return CreateVideoSource(std::move(capturer), nullptr); + } + + // Creates a new local video track wrapping |source|. The same |source| can + // be used in several tracks. + virtual rtc::scoped_refptr CreateVideoTrack( + const std::string& id, + VideoTrackSourceInterface* source) = 0; + + // Creates an new local audio track wrapping |source|. + virtual rtc::scoped_refptr CreateAudioTrack( + const std::string& id, + AudioSourceInterface* source) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_ORTCFACTORYINTERFACE_H_ diff --git a/include/webrtc/api/ortc/ortcrtpreceiverinterface.h b/include/webrtc/api/ortc/ortcrtpreceiverinterface.h new file mode 100644 index 0000000..1fad29c --- /dev/null +++ b/include/webrtc/api/ortc/ortcrtpreceiverinterface.h @@ -0,0 +1,84 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains interfaces for RtpReceivers: +// http://publications.ortc.org/2016/20161202/#rtcrtpreceiver* +// +// However, underneath the RtpReceiver is an RtpTransport, rather than a +// DtlsTransport. This is to allow different types of RTP transports (besides +// DTLS-SRTP) to be used. + +#ifndef WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_ +#define WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_ + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/mediatypes.h" +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" + +namespace webrtc { + +// Note: Since receiver capabilities may depend on how the OrtcFactory was +// created, instead of a static "GetCapabilities" method on this interface, +// there is a "GetRtpReceiverCapabilities" method on the OrtcFactory. +class OrtcRtpReceiverInterface { + public: + virtual ~OrtcRtpReceiverInterface() {} + + // Returns a track representing the media received by this receiver. + // + // Currently, this will return null until Receive has been successfully + // called. Also, a new track will be created every time the primary SSRC + // changes. + // + // If encodings are removed, GetTrack will return null. Though deactivating + // an encoding (setting |active| to false) will not do this. + // + // In the future, these limitations will be fixed, and GetTrack will return + // the same track for the lifetime of the RtpReceiver. So it's not + // recommended to write code that depends on this non-standard behavior. + virtual rtc::scoped_refptr GetTrack() const = 0; + + // Once supported, will switch to receiving media on a new transport. + // However, this is not currently supported and will always return an error. + virtual RTCError SetTransport(RtpTransportInterface* transport) = 0; + // Returns previously set (or constructed-with) transport. + virtual RtpTransportInterface* GetTransport() const = 0; + + // Start receiving media with |parameters| (if |parameters| contains an + // active encoding). + // + // There are no limitations to how the parameters can be changed after the + // initial call to Receive, as long as they're valid (for example, they can't + // use the same payload type for two codecs). + virtual RTCError Receive(const RtpParameters& parameters) = 0; + // Returns parameters that were last successfully passed into Receive, or + // empty parameters if that hasn't yet occurred. + // + // Note that for parameters that are described as having an "implementation + // default" value chosen, GetParameters() will return those chosen defaults, + // with the exception of SSRCs which have special behavior. See + // rtpparameters.h for more details. + virtual RtpParameters GetParameters() const = 0; + + // Audio or video receiver? + // + // Once GetTrack() starts always returning a track, this method will be + // redundant, as one can call "GetTrack()->kind()". However, it's still a + // nice convenience, and is symmetric with OrtcRtpSenderInterface::GetKind. + virtual cricket::MediaType GetKind() const = 0; + + // TODO(deadbeef): GetContributingSources +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_ORTCRTPRECEIVERINTERFACE_H_ diff --git a/include/webrtc/api/ortc/ortcrtpsenderinterface.h b/include/webrtc/api/ortc/ortcrtpsenderinterface.h new file mode 100644 index 0000000..e369b53 --- /dev/null +++ b/include/webrtc/api/ortc/ortcrtpsenderinterface.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains interfaces for RtpSenders: +// http://publications.ortc.org/2016/20161202/#rtcrtpsender* +// +// However, underneath the RtpSender is an RtpTransport, rather than a +// DtlsTransport. This is to allow different types of RTP transports (besides +// DTLS-SRTP) to be used. + +#ifndef WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_ +#define WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_ + +#include "webrtc/api/mediatypes.h" +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" + +namespace webrtc { + +// Note: Since sender capabilities may depend on how the OrtcFactory was +// created, instead of a static "GetCapabilities" method on this interface, +// there is a "GetRtpSenderCapabilities" method on the OrtcFactory. +class OrtcRtpSenderInterface { + public: + virtual ~OrtcRtpSenderInterface() {} + + // Sets the source of media that will be sent by this sender. + // + // If Send has already been called, will immediately switch to sending this + // track. If |track| is null, will stop sending media. + // + // Returns INVALID_PARAMETER error if an audio track is set on a video + // RtpSender, or vice-versa. + virtual RTCError SetTrack(MediaStreamTrackInterface* track) = 0; + // Returns previously set (or constructed-with) track. + virtual rtc::scoped_refptr GetTrack() const = 0; + + // Once supported, will switch to sending media on a new transport. However, + // this is not currently supported and will always return an error. + virtual RTCError SetTransport(RtpTransportInterface* transport) = 0; + // Returns previously set (or constructed-with) transport. + virtual RtpTransportInterface* GetTransport() const = 0; + + // Start sending media with |parameters| (if |parameters| contains an active + // encoding). + // + // There are no limitations to how the parameters can be changed after the + // initial call to Send, as long as they're valid (for example, they can't + // use the same payload type for two codecs). + virtual RTCError Send(const RtpParameters& parameters) = 0; + // Returns parameters that were last successfully passed into Send, or empty + // parameters if that hasn't yet occurred. + // + // Note that for parameters that are described as having an "implementation + // default" value chosen, GetParameters() will return those chosen defaults, + // with the exception of SSRCs which have special behavior. See + // rtpparameters.h for more details. + virtual RtpParameters GetParameters() const = 0; + + // Audio or video sender? + virtual cricket::MediaType GetKind() const = 0; + + // TODO(deadbeef): SSRC conflict signal. +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_ORTCRTPSENDERINTERFACE_H_ diff --git a/include/webrtc/api/ortc/packettransportinterface.h b/include/webrtc/api/ortc/packettransportinterface.h new file mode 100644 index 0000000..2677ce6 --- /dev/null +++ b/include/webrtc/api/ortc/packettransportinterface.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_ +#define WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_ + +namespace rtc { + +class PacketTransportInternal; + +} // namespace rtc + +namespace webrtc { + +// Base class for different packet-based transports. +class PacketTransportInterface { + public: + virtual ~PacketTransportInterface() {} + + protected: + // Only for internal use. Returns a pointer to an internal interface, for use + // by the implementation. + virtual rtc::PacketTransportInternal* GetInternal() = 0; + + // Classes that can use this internal interface. + friend class RtpTransportControllerAdapter; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_PACKETTRANSPORTINTERFACE_H_ diff --git a/include/webrtc/api/ortc/rtptransportcontrollerinterface.h b/include/webrtc/api/ortc/rtptransportcontrollerinterface.h new file mode 100644 index 0000000..d1d0e44 --- /dev/null +++ b/include/webrtc/api/ortc/rtptransportcontrollerinterface.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_ +#define WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_ + +#include + +#include "webrtc/api/ortc/rtptransportinterface.h" + +namespace webrtc { + +class RtpTransportControllerAdapter; + +// Used to group RTP transports between a local endpoint and the same remote +// endpoint, for the purpose of sharing bandwidth estimation and other things. +// +// Comparing this to the PeerConnection model, non-budled audio/video would use +// two RtpTransports with a single RtpTransportController, whereas bundled +// media would use a single RtpTransport, and two PeerConnections would use +// independent RtpTransportControllers. +// +// RtpTransports are associated with this controller when they're created, by +// passing the controller into OrtcFactory's relevant "CreateRtpTransport" +// method. When a transport is destroyed, it's automatically disassociated. +// GetTransports returns all currently associated transports. +// +// This is the RTP equivalent of "IceTransportController" in ORTC; RtpTransport +// is to RtpTransportController as IceTransport is to IceTransportController. +class RtpTransportControllerInterface { + public: + virtual ~RtpTransportControllerInterface() {} + + // Returns all transports associated with this controller (see explanation + // above). No ordering is guaranteed. + virtual std::vector GetTransports() const = 0; + + protected: + // Only for internal use. Returns a pointer to an internal interface, for use + // by the implementation. + virtual RtpTransportControllerAdapter* GetInternal() = 0; + + // Classes that can use this internal interface. + friend class OrtcFactory; + friend class RtpTransportAdapter; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_RTPTRANSPORTCONTROLLERINTERFACE_H_ diff --git a/include/webrtc/api/ortc/rtptransportinterface.h b/include/webrtc/api/ortc/rtptransportinterface.h new file mode 100644 index 0000000..942dc50 --- /dev/null +++ b/include/webrtc/api/ortc/rtptransportinterface.h @@ -0,0 +1,103 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_ +#define WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_ + +#include + +#include "webrtc/api/ortc/packettransportinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/base/optional.h" + +namespace webrtc { + +class RtpTransportAdapter; + +struct RtcpParameters { + // The SSRC to be used in the "SSRC of packet sender" field. If not set, one + // will be chosen by the implementation. + // TODO(deadbeef): Not implemented. + rtc::Optional ssrc; + + // The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages). + // + // If empty in the construction of the RtpTransport, one will be generated by + // the implementation, and returned in GetRtcpParameters. Multiple + // RtpTransports created by the same OrtcFactory will use the same generated + // CNAME. + // + // If empty when passed into SetRtcpParameters, the CNAME simply won't be + // modified. + std::string cname; + + // Send reduced-size RTCP? + bool reduced_size = false; + + // Send RTCP multiplexed on the RTP transport? + bool mux = true; + + bool operator==(const RtcpParameters& o) const { + return ssrc == o.ssrc && cname == o.cname && + reduced_size == o.reduced_size && mux == o.mux; + } + bool operator!=(const RtcpParameters& o) const { return !(*this == o); } +}; + +// Base class for different types of RTP transports that can be created by an +// OrtcFactory. Used by RtpSenders/RtpReceivers. +// +// This is not present in the standard ORTC API, but exists here for a few +// reasons. Firstly, it allows different types of RTP transports to be used: +// DTLS-SRTP (which is required for the web), but also SDES-SRTP and +// unencrypted RTP. It also simplifies the handling of RTCP muxing, and +// provides a better API point for it. +// +// Note that Edge's implementation of ORTC provides a similar API point, called +// RTCSrtpSdesTransport: +// https://msdn.microsoft.com/en-us/library/mt502527(v=vs.85).aspx +class RtpTransportInterface { + public: + virtual ~RtpTransportInterface() {} + + // Returns packet transport that's used to send RTP packets. + virtual PacketTransportInterface* GetRtpPacketTransport() const = 0; + + // Returns separate packet transport that's used to send RTCP packets. If + // RTCP multiplexing is being used, returns null. + virtual PacketTransportInterface* GetRtcpPacketTransport() const = 0; + + // Set/get RTCP params. Can be used to enable RTCP muxing or reduced-size + // RTCP if initially not enabled. + // + // Changing |mux| from "true" to "false" is not allowed, and changing the + // CNAME is currently unsupported. + virtual RTCError SetRtcpParameters(const RtcpParameters& parameters) = 0; + // Returns last set or constructed-with parameters. If |cname| was empty in + // construction, the generated CNAME will be present in the returned + // parameters (see above). + virtual RtcpParameters GetRtcpParameters() const = 0; + + protected: + // Only for internal use. Returns a pointer to an internal interface, for use + // by the implementation. + virtual RtpTransportAdapter* GetInternal() = 0; + + // Classes that can use this internal interface. + friend class OrtcFactory; + friend class OrtcRtpSenderAdapter; + friend class OrtcRtpReceiverAdapter; + friend class RtpTransportControllerAdapter; + friend class RtpTransportAdapter; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_RTPTRANSPORTINTERFACE_H_ diff --git a/include/webrtc/api/ortc/udptransportinterface.h b/include/webrtc/api/ortc/udptransportinterface.h new file mode 100644 index 0000000..2781076 --- /dev/null +++ b/include/webrtc/api/ortc/udptransportinterface.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_ +#define WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_ + +#include "webrtc/api/ortc/packettransportinterface.h" +#include "webrtc/api/proxy.h" +#include "webrtc/base/socketaddress.h" + +namespace webrtc { + +// Interface for a raw UDP transport (not using ICE), meaning a combination of +// a local/remote IP address/port. +// +// An instance can be instantiated using OrtcFactory. +// +// Each instance reserves a UDP port, which will be freed when the +// UdpTransportInterface destructor is called. +// +// Calling SetRemoteAddress sets the destination of outgoing packets; without a +// destination, packets can't be sent, but they can be received. +class UdpTransportInterface : virtual public PacketTransportInterface { + public: + // Get the address of the socket allocated for this transport. + virtual rtc::SocketAddress GetLocalAddress() const = 0; + + // Sets the address to which packets will be delivered. + // + // Calling with a "nil" (default-constructed) address is legal, and unsets + // any previously set destination. + // + // However, calling with an incomplete address (port or IP not set) will + // fail. + virtual bool SetRemoteAddress(const rtc::SocketAddress& dest) = 0; + // Simple getter. If never set, returns nil address. + virtual rtc::SocketAddress GetRemoteAddress() const = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_ORTC_UDPTRANSPORTINTERFACE_H_ diff --git a/include/webrtc/api/peerconnectionfactoryproxy.h b/include/webrtc/api/peerconnectionfactoryproxy.h index c357de9..dd784f5 100644 --- a/include/webrtc/api/peerconnectionfactoryproxy.h +++ b/include/webrtc/api/peerconnectionfactoryproxy.h @@ -21,31 +21,29 @@ namespace webrtc { +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory) + PROXY_SIGNALING_THREAD_DESTRUCTOR() + // Use the overloads of CreateVideoSource that take raw VideoCapturer + // pointers from PeerConnectionFactoryInterface. + // TODO(deadbeef): Remove this using statement once those overloads are + // removed. + using PeerConnectionFactoryInterface::CreateVideoSource; PROXY_METHOD1(void, SetOptions, const Options&) - // Can't use PROXY_METHOD5 because unique_ptr must be moved. - // TODO(tommi,hbos): Use of templates to support unique_ptr? - rtc::scoped_refptr CreatePeerConnection( - const PeerConnectionInterface::RTCConfiguration& a1, - const MediaConstraintsInterface* a2, - std::unique_ptr a3, - std::unique_ptr a4, - PeerConnectionObserver* a5) override { - return signaling_thread_ - ->Invoke>( - rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, - this, a1, a2, a3.release(), a4.release(), a5)); - } - rtc::scoped_refptr CreatePeerConnection( - const PeerConnectionInterface::RTCConfiguration& a1, - std::unique_ptr a3, - std::unique_ptr a4, - PeerConnectionObserver* a5) override { - return signaling_thread_ - ->Invoke>( - rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, - this, a1, a3.release(), a4.release(), a5)); - } + PROXY_METHOD5(rtc::scoped_refptr, + CreatePeerConnection, + const PeerConnectionInterface::RTCConfiguration&, + const MediaConstraintsInterface*, + std::unique_ptr, + std::unique_ptr, + PeerConnectionObserver*); + PROXY_METHOD4(rtc::scoped_refptr, + CreatePeerConnection, + const PeerConnectionInterface::RTCConfiguration&, + std::unique_ptr, + std::unique_ptr, + PeerConnectionObserver*); PROXY_METHOD1(rtc::scoped_refptr, CreateLocalMediaStream, const std::string&) PROXY_METHOD1(rtc::scoped_refptr, @@ -55,11 +53,11 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory) const cricket::AudioOptions&) PROXY_METHOD2(rtc::scoped_refptr, CreateVideoSource, - cricket::VideoCapturer*, + std::unique_ptr, const MediaConstraintsInterface*) PROXY_METHOD1(rtc::scoped_refptr, CreateVideoSource, - cricket::VideoCapturer*) + std::unique_ptr) PROXY_METHOD2(rtc::scoped_refptr, CreateVideoTrack, const std::string&, @@ -68,34 +66,12 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory) CreateAudioTrack, const std::string&, AudioSourceInterface*) PROXY_METHOD2(bool, StartAecDump, rtc::PlatformFile, int64_t) PROXY_METHOD0(void, StopAecDump) + // TODO(ivoc): Remove the StartRtcEventLog and StopRtcEventLog functions as + // soon as they are removed from PeerConnectionFactoryInterface. PROXY_METHOD1(bool, StartRtcEventLog, rtc::PlatformFile) PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t) PROXY_METHOD0(void, StopRtcEventLog) - - private: - rtc::scoped_refptr CreatePeerConnection_ot( - const PeerConnectionInterface::RTCConfiguration& a1, - const MediaConstraintsInterface* a2, - cricket::PortAllocator* a3, - DtlsIdentityStoreInterface* a4, - PeerConnectionObserver* a5) { - std::unique_ptr ptr_a3(a3); - std::unique_ptr ptr_a4(a4); - return c_->CreatePeerConnection(a1, a2, std::move(ptr_a3), - std::move(ptr_a4), a5); - } - - rtc::scoped_refptr CreatePeerConnection_ot( - const PeerConnectionInterface::RTCConfiguration& a1, - cricket::PortAllocator* a3, - DtlsIdentityStoreInterface* a4, - PeerConnectionObserver* a5) { - std::unique_ptr ptr_a3(a3); - std::unique_ptr ptr_a4(a4); - return c_->CreatePeerConnection(a1, std::move(ptr_a3), std::move(ptr_a4), - a5); - } - END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/peerconnectioninterface.h b/include/webrtc/api/peerconnectioninterface.h index 4fa9bf2..165f2d5 100644 --- a/include/webrtc/api/peerconnectioninterface.h +++ b/include/webrtc/api/peerconnectioninterface.h @@ -10,43 +10,59 @@ // This file contains the PeerConnection interface as defined in // http://dev.w3.org/2011/webrtc/editor/webrtc.html#peer-to-peer-connections. -// Applications must use this interface to implement peerconnection. -// PeerConnectionFactory class provides factory methods to create -// peerconnection, mediastream and media tracks objects. // -// The Following steps are needed to setup a typical call using Jsep. +// The PeerConnectionFactory class provides factory methods to create +// PeerConnection, MediaStream and MediaStreamTrack objects. +// +// The following steps are needed to setup a typical call using WebRTC: +// // 1. Create a PeerConnectionFactoryInterface. Check constructors for more // information about input parameters. -// 2. Create a PeerConnection object. Provide a configuration string which -// points either to stun or turn server to generate ICE candidates and provide -// an object that implements the PeerConnectionObserver interface. -// 3. Create local MediaStream and MediaTracks using the PeerConnectionFactory -// and add it to PeerConnection by calling AddStream. -// 4. Create an offer and serialize it and send it to the remote peer. -// 5. Once an ice candidate have been found PeerConnection will call the +// +// 2. Create a PeerConnection object. Provide a configuration struct which +// points to STUN and/or TURN servers used to generate ICE candidates, and +// provide an object that implements the PeerConnectionObserver interface, +// which is used to receive callbacks from the PeerConnection. +// +// 3. Create local MediaStreamTracks using the PeerConnectionFactory and add +// them to PeerConnection by calling AddTrack (or legacy method, AddStream). +// +// 4. Create an offer, call SetLocalDescription with it, serialize it, and send +// it to the remote peer +// +// 5. Once an ICE candidate has been gathered, the PeerConnection will call the // observer function OnIceCandidate. The candidates must also be serialized and // sent to the remote peer. +// // 6. Once an answer is received from the remote peer, call -// SetLocalSessionDescription with the offer and SetRemoteSessionDescription -// with the remote answer. +// SetRemoteDescription with the remote answer. +// // 7. Once a remote candidate is received from the remote peer, provide it to -// the peerconnection by calling AddIceCandidate. - - -// The Receiver of a call can decide to accept or reject the call. -// This decision will be taken by the application not peerconnection. -// If application decides to accept the call +// the PeerConnection by calling AddIceCandidate. +// +// The receiver of a call (assuming the application is "call"-based) can decide +// to accept or reject the call; this decision will be taken by the application, +// not the PeerConnection. +// +// If the application decides to accept the call, it should: +// // 1. Create PeerConnectionFactoryInterface if it doesn't exist. +// // 2. Create a new PeerConnection. +// // 3. Provide the remote offer to the new PeerConnection object by calling -// SetRemoteSessionDescription. +// SetRemoteDescription. +// // 4. Generate an answer to the remote offer by calling CreateAnswer and send it // back to the remote peer. +// // 5. Provide the local answer to the new PeerConnection by calling -// SetLocalSessionDescription with the answer. -// 6. Provide the remote ice candidates by calling AddIceCandidate. -// 7. Once a candidate have been found PeerConnection will call the observer -// function OnIceCandidate. Send these candidates to the remote peer. +// SetLocalDescription with the answer. +// +// 6. Provide the remote ICE candidates by calling AddIceCandidate. +// +// 7. Once a candidate has been gathered, the PeerConnection will call the +// observer function OnIceCandidate. Send these candidates to the remote peer. #ifndef WEBRTC_API_PEERCONNECTIONINTERFACE_H_ #define WEBRTC_API_PEERCONNECTIONINTERFACE_H_ @@ -56,21 +72,25 @@ #include #include +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" #include "webrtc/api/datachannelinterface.h" -#include "webrtc/api/dtlsidentitystore.h" #include "webrtc/api/dtmfsenderinterface.h" #include "webrtc/api/jsep.h" #include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/rtcerror.h" #include "webrtc/api/rtpreceiverinterface.h" #include "webrtc/api/rtpsenderinterface.h" +#include "webrtc/api/stats/rtcstatscollectorcallback.h" #include "webrtc/api/statstypes.h" #include "webrtc/api/umametrics.h" #include "webrtc/base/fileutils.h" #include "webrtc/base/network.h" #include "webrtc/base/rtccertificate.h" +#include "webrtc/base/rtccertificategenerator.h" #include "webrtc/base/socketaddress.h" #include "webrtc/base/sslstreamadapter.h" #include "webrtc/media/base/mediachannel.h" +#include "webrtc/media/base/videocapturer.h" #include "webrtc/p2p/base/portallocator.h" namespace rtc { @@ -85,6 +105,7 @@ class WebRtcVideoEncoderFactory; namespace webrtc { class AudioDeviceModule; +class AudioMixer; class MediaConstraintsInterface; // MediaStream container interface. @@ -112,33 +133,6 @@ class StatsObserver : public rtc::RefCountInterface { virtual ~StatsObserver() {} }; -class MetricsObserverInterface : public rtc::RefCountInterface { - public: - - // |type| is the type of the enum counter to be incremented. |counter| - // is the particular counter in that type. |counter_max| is the next sequence - // number after the highest counter. - virtual void IncrementEnumCounter(PeerConnectionEnumCounterType type, - int counter, - int counter_max) {} - - // This is used to handle sparse counters like SSL cipher suites. - // TODO(guoweis): Remove the implementation once the dependency's interface - // definition is updated. - virtual void IncrementSparseEnumCounter(PeerConnectionEnumCounterType type, - int counter) { - IncrementEnumCounter(type, counter, 0 /* Ignored */); - } - - virtual void AddHistogramSample(PeerConnectionMetricsName type, - int value) = 0; - - protected: - virtual ~MetricsObserverInterface() {} -}; - -typedef MetricsObserverInterface UMAObserver; - class PeerConnectionInterface : public rtc::RefCountInterface { public: // See http://dev.w3.org/2011/webrtc/editor/webrtc.html#state-definitions . @@ -151,19 +145,6 @@ class PeerConnectionInterface : public rtc::RefCountInterface { kClosed, }; - // TODO(bemasc): Remove IceState when callers are changed to - // IceConnection/GatheringState. - enum IceState { - kIceNew, - kIceGathering, - kIceWaiting, - kIceChecking, - kIceConnected, - kIceCompleted, - kIceFailed, - kIceClosed, - }; - enum IceGatheringState { kIceGatheringNew, kIceGatheringGathering, @@ -181,12 +162,30 @@ class PeerConnectionInterface : public rtc::RefCountInterface { kIceConnectionMax, }; + // TLS certificate policy. + enum TlsCertPolicy { + // For TLS based protocols, ensure the connection is secure by not + // circumventing certificate validation. + kTlsCertPolicySecure, + // For TLS based protocols, disregard security completely by skipping + // certificate validation. This is insecure and should never be used unless + // security is irrelevant in that particular context. + kTlsCertPolicyInsecureNoCheck, + }; + struct IceServer { // TODO(jbauch): Remove uri when all code using it has switched to urls. std::string uri; std::vector urls; std::string username; std::string password; + TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure; + + bool operator==(const IceServer& o) const { + return uri == o.uri && urls == o.urls && username == o.username && + password == o.password && tls_cert_policy == o.tls_cert_policy; + } + bool operator!=(const IceServer& o) const { return !(*this == o); } }; typedef std::vector IceServers; @@ -217,11 +216,25 @@ class PeerConnectionInterface : public rtc::RefCountInterface { kTcpCandidatePolicyDisabled }; + enum CandidateNetworkPolicy { + kCandidateNetworkPolicyAll, + kCandidateNetworkPolicyLowCost + }; + enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY }; + enum class RTCConfigurationType { + // A configuration that is safer to use, despite not having the best + // performance. Currently this is the default configuration. + kSafe, + // An aggressive configuration that has better performance, although it + // may be riskier and may need extra support in the application. + kAggressive + }; + // TODO(hbos): Change into class with private data and public getters. // TODO(nisse): In particular, accessing fields directly from an // application is brittle, since the organization mirrors the @@ -235,6 +248,26 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // methods for all settings which are of interest to applications, // Chrome in particular. + RTCConfiguration() = default; + explicit RTCConfiguration(RTCConfigurationType type) { + if (type == RTCConfigurationType::kAggressive) { + // These parameters are also defined in Java and IOS configurations, + // so their values may be overwritten by the Java or IOS configuration. + bundle_policy = kBundlePolicyMaxBundle; + rtcp_mux_policy = kRtcpMuxPolicyRequire; + ice_connection_receiving_timeout = + kAggressiveIceConnectionReceivingTimeout; + + // These parameters are not defined in Java or IOS configuration, + // so their values will not be overwritten. + enable_ice_renomination = true; + redetermine_role_on_ice_restart = false; + } + } + + bool operator==(const RTCConfiguration& o) const; + bool operator!=(const RTCConfiguration& o) const; + bool dscp() { return media_config.enable_dscp; } void set_dscp(bool enable) { media_config.enable_dscp = enable; } @@ -267,34 +300,145 @@ class PeerConnectionInterface : public rtc::RefCountInterface { static const int kUndefined = -1; // Default maximum number of packets in the audio jitter buffer. static const int kAudioJitterBufferMaxPackets = 50; - // TODO(pthatcher): Rename this ice_transport_type, but update - // Chromium at the same time. - IceTransportsType type = kAll; + // ICE connection receiving timeout for aggressive configuration. + static const int kAggressiveIceConnectionReceivingTimeout = 1000; + + //////////////////////////////////////////////////////////////////////// + // The below few fields mirror the standard RTCConfiguration dictionary: + // https://www.w3.org/TR/webrtc/#rtcconfiguration-dictionary + //////////////////////////////////////////////////////////////////////// + // TODO(pthatcher): Rename this ice_servers, but update Chromium // at the same time. IceServers servers; + // TODO(pthatcher): Rename this ice_transport_type, but update + // Chromium at the same time. + IceTransportsType type = kAll; BundlePolicy bundle_policy = kBundlePolicyBalanced; - RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyNegotiate; - TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled; - int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets; - bool audio_jitter_buffer_fast_accelerate = false; - int ice_connection_receiving_timeout = kUndefined; // ms - int ice_backup_candidate_pair_ping_interval = kUndefined; // ms - ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; + RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire; std::vector> certificates; - bool prioritize_most_likely_ice_candidate_pairs = false; - struct cricket::MediaConfig media_config; - // Flags corresponding to values set by constraint flags. - // rtc::Optional flags can be "missing", in which case the webrtc - // default applies. + int ice_candidate_pool_size = 0; + + ////////////////////////////////////////////////////////////////////////// + // The below fields correspond to constraints from the deprecated + // constraints interface for constructing a PeerConnection. + // + // rtc::Optional fields can be "missing", in which case the implementation + // default will be used. + ////////////////////////////////////////////////////////////////////////// + + // If set to true, don't gather IPv6 ICE candidates. + // TODO(deadbeef): Remove this? IPv6 support has long stopped being + // experimental bool disable_ipv6 = false; + + // If set to true, use RTP data channels instead of SCTP. + // TODO(deadbeef): Remove this. We no longer commit to supporting RTP data + // channels, though some applications are still working on moving off of + // them. bool enable_rtp_data_channel = false; + + // Minimum bitrate at which screencast video tracks will be encoded at. + // This means adding padding bits up to this bitrate, which can help + // when switching from a static scene to one with motion. rtc::Optional screencast_min_bitrate; + + // Use new combined audio/video bandwidth estimation? rtc::Optional combined_audio_video_bwe; + + // Can be used to disable DTLS-SRTP. This should never be done, but can be + // useful for testing purposes, for example in setting up a loopback call + // with a single PeerConnection. rtc::Optional enable_dtls_srtp; - int ice_candidate_pool_size = 0; + + ///////////////////////////////////////////////// + // The below fields are not part of the standard. + ///////////////////////////////////////////////// + + // Can be used to disable TCP candidate generation. + TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled; + + // Can be used to avoid gathering candidates for a "higher cost" network, + // if a lower cost one exists. For example, if both Wi-Fi and cellular + // interfaces are available, this could be used to avoid using the cellular + // interface. + CandidateNetworkPolicy candidate_network_policy = + kCandidateNetworkPolicyAll; + + // The maximum number of packets that can be stored in the NetEq audio + // jitter buffer. Can be reduced to lower tolerated audio latency. + int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets; + + // Whether to use the NetEq "fast mode" which will accelerate audio quicker + // if it falls behind. + bool audio_jitter_buffer_fast_accelerate = false; + + // Timeout in milliseconds before an ICE candidate pair is considered to be + // "not receiving", after which a lower priority candidate pair may be + // selected. + int ice_connection_receiving_timeout = kUndefined; + + // Interval in milliseconds at which an ICE "backup" candidate pair will be + // pinged. This is a candidate pair which is not actively in use, but may + // be switched to if the active candidate pair becomes unusable. + // + // This is relevant mainly to Wi-Fi/cell handoff; the application may not + // want this backup cellular candidate pair pinged frequently, since it + // consumes data/battery. + int ice_backup_candidate_pair_ping_interval = kUndefined; + + // Can be used to enable continual gathering, which means new candidates + // will be gathered as network interfaces change. Note that if continual + // gathering is used, the candidate removal API should also be used, to + // avoid an ever-growing list of candidates. + ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; + + // If set to true, candidate pairs will be pinged in order of most likely + // to work (which means using a TURN server, generally), rather than in + // standard priority order. + bool prioritize_most_likely_ice_candidate_pairs = false; + + struct cricket::MediaConfig media_config; + + // This doesn't currently work. For a while we were working on adding QUIC + // data channel support to PeerConnection, but decided on a different + // approach, and that code hasn't been updated for a while. + bool enable_quic = false; + + // If set to true, only one preferred TURN allocation will be used per + // network interface. UDP is preferred over TCP and IPv6 over IPv4. This + // can be used to cut down on the number of candidate pairings. + bool prune_turn_ports = false; + + // If set to true, this means the ICE transport should presume TURN-to-TURN + // candidate pairs will succeed, even before a binding response is received. + // This can be used to optimize the initial connection time, since the DTLS + // handshake can begin immediately. + bool presume_writable_when_fully_relayed = false; + + // If true, "renomination" will be added to the ice options in the transport + // description. + // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 + bool enable_ice_renomination = false; + + // If true, the ICE role is re-determined when the PeerConnection sets a + // local transport description that indicates an ICE restart. + // + // This is standard RFC5245 ICE behavior, but causes unnecessary role + // thrashing, so an application may wish to avoid it. This role + // re-determining was removed in ICEbis (ICE v2). + bool redetermine_role_on_ice_restart = true; + + // If set, the min interval (max rate) at which we will send ICE checks + // (STUN pings), in milliseconds. + rtc::Optional ice_check_min_interval; + + // + // Don't forget to update operator== if adding something. + // }; + // See: https://www.w3.org/TR/webrtc/#idl-def-rtcofferansweroptions struct RTCOfferAnswerOptions { static const int kUndefined = -1; static const int kMaxOfferToReceiveMedia = 1; @@ -302,18 +446,26 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // The default value for constraint offerToReceiveX:true. static const int kOfferToReceiveMediaTrue = 1; - int offer_to_receive_video; - int offer_to_receive_audio; - bool voice_activity_detection; - bool ice_restart; - bool use_rtp_mux; + // These have been removed from the standard in favor of the "transceiver" + // API, but given that we don't support that API, we still have them here. + // + // offer_to_receive_X set to 1 will cause a media description to be + // generated in the offer, even if no tracks of that type have been added. + // Values greater than 1 are treated the same. + // + // If set to 0, the generated directional attribute will not include the + // "recv" direction (meaning it will be "sendonly" or "inactive". + int offer_to_receive_video = kUndefined; + int offer_to_receive_audio = kUndefined; - RTCOfferAnswerOptions() - : offer_to_receive_video(kUndefined), - offer_to_receive_audio(kUndefined), - voice_activity_detection(true), - ice_restart(false), - use_rtp_mux(true) {} + bool voice_activity_detection = true; + bool ice_restart = false; + + // If true, will offer to BUNDLE audio/video/data together. Not to be + // confused with RTCP mux (multiplexing RTP and RTCP together). + bool use_rtp_mux = true; + + RTCOfferAnswerOptions() = default; RTCOfferAnswerOptions(int offer_to_receive_video, int offer_to_receive_audio, @@ -347,16 +499,25 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // Add a new MediaStream to be sent on this PeerConnection. // Note that a SessionDescription negotiation is needed before the // remote peer can receive the stream. + // + // This has been removed from the standard in favor of a track-based API. So, + // this is equivalent to simply calling AddTrack for each track within the + // stream, with the one difference that if "stream->AddTrack(...)" is called + // later, the PeerConnection will automatically pick up the new track. Though + // this functionality will be deprecated in the future. virtual bool AddStream(MediaStreamInterface* stream) = 0; // Remove a MediaStream from this PeerConnection. - // Note that a SessionDescription negotiation is need before the + // Note that a SessionDescription negotiation is needed before the // remote peer is notified. virtual void RemoveStream(MediaStreamInterface* stream) = 0; // TODO(deadbeef): Make the following two methods pure virtual once // implemented by all subclasses of PeerConnectionInterface. - // Add a new MediaStreamTrack to be sent on this PeerConnection. + + // Add a new MediaStreamTrack to be sent on this PeerConnection, and return + // the newly created RtpSender. + // // |streams| indicates which stream labels the track should be associated // with. virtual rtc::scoped_refptr AddTrack( @@ -371,13 +532,25 @@ class PeerConnectionInterface : public rtc::RefCountInterface { return false; } - // Returns pointer to the created DtmfSender on success. - // Otherwise returns NULL. + // Returns pointer to a DtmfSender on success. Otherwise returns null. + // + // This API is no longer part of the standard; instead DtmfSenders are + // obtained from RtpSenders. Which is what the implementation does; it finds + // an RtpSender for |track| and just returns its DtmfSender. virtual rtc::scoped_refptr CreateDtmfSender( AudioTrackInterface* track) = 0; // TODO(deadbeef): Make these pure virtual once all subclasses implement them. + + // Creates a sender without a track. Can be used for "early media"/"warmup" + // use cases, where the application may want to negotiate video attributes + // before a track is available to send. + // + // The standard way to do this would be through "addTransceiver", but we + // don't support that API yet. + // // |kind| must be "audio" or "video". + // // |stream_id| is used to populate the msid attribute; if empty, one will // be generated automatically. virtual rtc::scoped_refptr CreateSender( @@ -386,11 +559,23 @@ class PeerConnectionInterface : public rtc::RefCountInterface { return rtc::scoped_refptr(); } + // Get all RtpSenders, created either through AddStream, AddTrack, or + // CreateSender. Note that these are "Plan B SDP" RtpSenders, not "Unified + // Plan SDP" RtpSenders, which means that all senders of a specific media + // type share the same media description. virtual std::vector> GetSenders() const { return std::vector>(); } + // Get all RtpReceivers, created when a remote description is applied. + // Note that these are "Plan B SDP" RtpReceivers, not "Unified Plan SDP" + // RtpReceivers, which means that all receivers of a specific media type + // share the same media description. + // + // It is also possible to have a media description with no associated + // RtpReceivers, if the directional attribute does not indicate that the + // remote peer is sending any media. virtual std::vector> GetReceivers() const { return std::vector>(); @@ -399,14 +584,50 @@ class PeerConnectionInterface : public rtc::RefCountInterface { virtual bool GetStats(StatsObserver* observer, MediaStreamTrackInterface* track, StatsOutputLevel level) = 0; - + // Gets stats using the new stats collection API, see webrtc/api/stats/. These + // will replace old stats collection API when the new API has matured enough. + // TODO(hbos): Default implementation that does nothing only exists as to not + // break third party projects. As soon as they have been updated this should + // be changed to "= 0;". + virtual void GetStats(RTCStatsCollectorCallback* callback) {} + + // Create a data channel with the provided config, or default config if none + // is provided. Note that an offer/answer negotiation is still necessary + // before the data channel can be used. + // + // Also, calling CreateDataChannel is the only way to get a data "m=" section + // in SDP, so it should be done before CreateOffer is called, if the + // application plans to use data channels. virtual rtc::scoped_refptr CreateDataChannel( const std::string& label, const DataChannelInit* config) = 0; + // Returns the more recently applied description; "pending" if it exists, and + // otherwise "current". See below. virtual const SessionDescriptionInterface* local_description() const = 0; virtual const SessionDescriptionInterface* remote_description() const = 0; + // A "current" description the one currently negotiated from a complete + // offer/answer exchange. + virtual const SessionDescriptionInterface* current_local_description() const { + return nullptr; + } + virtual const SessionDescriptionInterface* current_remote_description() + const { + return nullptr; + } + + // A "pending" description is one that's part of an incomplete offer/answer + // exchange (thus, either an offer or a pranswer). Once the offer/answer + // exchange is finished, the "pending" description will become "current". + virtual const SessionDescriptionInterface* pending_local_description() const { + return nullptr; + } + virtual const SessionDescriptionInterface* pending_remote_description() + const { + return nullptr; + } + // Create a new offer. // The CreateSessionDescriptionObserver callback will be called when done. virtual void CreateOffer(CreateSessionDescriptionObserver* observer, @@ -437,52 +658,97 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // The |observer| callback will be called when done. virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer, SessionDescriptionInterface* desc) = 0; - // Restarts or updates the ICE Agent process of gathering local candidates - // and pinging remote candidates. + // Deprecated; Replaced by SetConfiguration. // TODO(deadbeef): Remove once Chrome is moved over to SetConfiguration. virtual bool UpdateIce(const IceServers& configuration, const MediaConstraintsInterface* constraints) { return false; } virtual bool UpdateIce(const IceServers& configuration) { return false; } + + // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of + // PeerConnectionInterface implement it. + virtual PeerConnectionInterface::RTCConfiguration GetConfiguration() { + return PeerConnectionInterface::RTCConfiguration(); + } + // Sets the PeerConnection's global configuration to |config|. + // + // The members of |config| that may be changed are |type|, |servers|, + // |ice_candidate_pool_size| and |prune_turn_ports| (though the candidate + // pool size can't be changed after the first call to SetLocalDescription). + // Note that this means the BUNDLE and RTCP-multiplexing policies cannot be + // changed with this method. + // // Any changes to STUN/TURN servers or ICE candidate policy will affect the // next gathering phase, and cause the next call to createOffer to generate - // new ICE credentials. Note that the BUNDLE and RTCP-multiplexing policies - // cannot be changed with this method. + // new ICE credentials, as described in JSEP. This also occurs when + // |prune_turn_ports| changes, for the same reasoning. + // + // If an error occurs, returns false and populates |error| if non-null: + // - INVALID_MODIFICATION if |config| contains a modified parameter other + // than one of the parameters listed above. + // - INVALID_RANGE if |ice_candidate_pool_size| is out of range. + // - SYNTAX_ERROR if parsing an ICE server URL failed. + // - INVALID_PARAMETER if a TURN server is missing |username| or |password|. + // - INTERNAL_ERROR if an unexpected error occurred. + // // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of // PeerConnectionInterface implement it. + virtual bool SetConfiguration( + const PeerConnectionInterface::RTCConfiguration& config, + RTCError* error) { + return false; + } + // Version without error output param for backwards compatibility. + // TODO(deadbeef): Remove once chromium is updated. virtual bool SetConfiguration( const PeerConnectionInterface::RTCConfiguration& config) { return false; } + // Provides a remote candidate to the ICE Agent. // A copy of the |candidate| will be created and added to the remote // description. So the caller of this method still has the ownership of the // |candidate|. - // TODO(ronghuawu): Consider to change this so that the AddIceCandidate will - // take the ownership of the |candidate|. virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0; - // Removes a group of remote candidates from the ICE agent. + // Removes a group of remote candidates from the ICE agent. Needed mainly for + // continual gathering, to avoid an ever-growing list of candidates as + // networks come and go. virtual bool RemoveIceCandidates( const std::vector& candidates) { return false; } + // Register a metric observer (used by chromium). + // + // There can only be one observer at a time. Before the observer is + // destroyed, RegisterUMAOberver(nullptr) should be called. virtual void RegisterUMAObserver(UMAObserver* observer) = 0; // Returns the current SignalingState. virtual SignalingState signaling_state() = 0; - - // TODO(bemasc): Remove ice_state when callers are changed to - // IceConnection/GatheringState. - // Returns the current IceState. - virtual IceState ice_state() = 0; virtual IceConnectionState ice_connection_state() = 0; virtual IceGatheringState ice_gathering_state() = 0; - // Terminates all media and closes the transport. + // Starts RtcEventLog using existing file. Takes ownership of |file| and + // passes it on to Call, which will take the ownership. If the + // operation fails the file will be closed. The logging will stop + // automatically after 10 minutes have passed, or when the StopRtcEventLog + // function is called. + // TODO(ivoc): Make this pure virtual when Chrome is updated. + virtual bool StartRtcEventLog(rtc::PlatformFile file, + int64_t max_size_bytes) { + return false; + } + + // Stops logging the RtcEventLog. + // TODO(ivoc): Make this pure virtual when Chrome is updated. + virtual void StopRtcEventLog() {} + + // Terminates all media, closes the transports, and in general releases any + // resources used by the PeerConnection. This is an irreversible operation. virtual void Close() = 0; protected: @@ -490,8 +756,8 @@ class PeerConnectionInterface : public rtc::RefCountInterface { ~PeerConnectionInterface() {} }; -// PeerConnection callback interface. Application should implement these -// methods. +// PeerConnection callback interface, used for RTCPeerConnection events. +// Application should implement these methods. class PeerConnectionObserver { public: enum StateType { @@ -503,27 +769,45 @@ class PeerConnectionObserver { virtual void OnSignalingChange( PeerConnectionInterface::SignalingState new_state) = 0; + // TODO(deadbeef): Once all subclasses override the scoped_refptr versions + // of the below three methods, make them pure virtual and remove the raw + // pointer version. + // Triggered when media is received on a new stream from remote peer. - virtual void OnAddStream(MediaStreamInterface* stream) = 0; + virtual void OnAddStream(rtc::scoped_refptr stream) {} + // Deprecated; please use the version that uses a scoped_refptr. + virtual void OnAddStream(MediaStreamInterface* stream) {} // Triggered when a remote peer close a stream. - virtual void OnRemoveStream(MediaStreamInterface* stream) = 0; + virtual void OnRemoveStream(rtc::scoped_refptr stream) { + } + // Deprecated; please use the version that uses a scoped_refptr. + virtual void OnRemoveStream(MediaStreamInterface* stream) {} - // Triggered when a remote peer open a data channel. - virtual void OnDataChannel(DataChannelInterface* data_channel) = 0; + // Triggered when a remote peer opens a data channel. + virtual void OnDataChannel( + rtc::scoped_refptr data_channel) {} + // Deprecated; please use the version that uses a scoped_refptr. + virtual void OnDataChannel(DataChannelInterface* data_channel) {} - // Triggered when renegotiation is needed, for example the ICE has restarted. + // Triggered when renegotiation is needed. For example, an ICE restart + // has begun. virtual void OnRenegotiationNeeded() = 0; - // Called any time the IceConnectionState changes + // Called any time the IceConnectionState changes. + // + // Note that our ICE states lag behind the standard slightly. The most + // notable differences include the fact that "failed" occurs after 15 + // seconds, not 30, and this actually represents a combination ICE + DTLS + // state, so it may be "failed" if DTLS fails while ICE succeeds. virtual void OnIceConnectionChange( PeerConnectionInterface::IceConnectionState new_state) = 0; - // Called any time the IceGatheringState changes + // Called any time the IceGatheringState changes. virtual void OnIceGatheringChange( PeerConnectionInterface::IceGatheringState new_state) = 0; - // New Ice candidate have been found. + // A new ICE candidate has been gathered. virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0; // Ice candidates have been removed. @@ -535,82 +819,132 @@ class PeerConnectionObserver { // Called when the ICE connection receiving status changes. virtual void OnIceConnectionReceivingChange(bool receiving) {} + // Called when a track is added to streams. + // TODO(zhihuang) Make this a pure virtual method when all its subclasses + // implement it. + virtual void OnAddTrack( + rtc::scoped_refptr receiver, + const std::vector>& streams) {} + protected: // Dtor protected as objects shouldn't be deleted via this interface. ~PeerConnectionObserver() {} }; -// PeerConnectionFactoryInterface is the factory interface use for creating -// PeerConnection, MediaStream and media tracks. -// PeerConnectionFactoryInterface will create required libjingle threads, -// socket and network manager factory classes for networking. -// If an application decides to provide its own threads and network -// implementation of these classes it should use the alternate -// CreatePeerConnectionFactory method which accepts threads as input and use the -// CreatePeerConnection version that takes a PortAllocator as an -// argument. +// PeerConnectionFactoryInterface is the factory interface used for creating +// PeerConnection, MediaStream and MediaStreamTrack objects. +// +// The simplest method for obtaiing one, CreatePeerConnectionFactory will +// create the required libjingle threads, socket and network manager factory +// classes for networking if none are provided, though it requires that the +// application runs a message loop on the thread that called the method (see +// explanation below) +// +// If an application decides to provide its own threads and/or implementation +// of networking classes, it should use the alternate +// CreatePeerConnectionFactory method which accepts threads as input, and use +// the CreatePeerConnection version that takes a PortAllocator as an argument. class PeerConnectionFactoryInterface : public rtc::RefCountInterface { public: class Options { public: - Options() - : disable_encryption(false), - disable_sctp_data_channels(false), - disable_network_monitor(false), - network_ignore_mask(rtc::kDefaultNetworkIgnoreMask), - ssl_max_version(rtc::SSL_PROTOCOL_DTLS_12) {} - bool disable_encryption; - bool disable_sctp_data_channels; - bool disable_network_monitor; + Options() : crypto_options(rtc::CryptoOptions::NoGcm()) {} + + // If set to true, created PeerConnections won't enforce any SRTP + // requirement, allowing unsecured media. Should only be used for + // testing/debugging. + bool disable_encryption = false; + + // Deprecated. The only effect of setting this to true is that + // CreateDataChannel will fail, which is not that useful. + bool disable_sctp_data_channels = false; + + // If set to true, any platform-supported network monitoring capability + // won't be used, and instead networks will only be updated via polling. + // + // This only has an effect if a PeerConnection is created with the default + // PortAllocator implementation. + bool disable_network_monitor = false; // Sets the network types to ignore. For instance, calling this with // ADAPTER_TYPE_ETHERNET | ADAPTER_TYPE_LOOPBACK will ignore Ethernet and // loopback interfaces. - int network_ignore_mask; + int network_ignore_mask = rtc::kDefaultNetworkIgnoreMask; // Sets the maximum supported protocol version. The highest version // supported by both ends will be used for the connection, i.e. if one // party supports DTLS 1.0 and the other DTLS 1.2, DTLS 1.0 will be used. - rtc::SSLProtocolVersion ssl_max_version; + rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; + + // Sets crypto related options, e.g. enabled cipher suites. + rtc::CryptoOptions crypto_options; }; virtual void SetOptions(const Options& options) = 0; virtual rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, - const MediaConstraintsInterface* constraints, std::unique_ptr allocator, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, PeerConnectionObserver* observer) = 0; + // Deprecated; should use RTCConfiguration for everything that previously + // used constraints. virtual rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, + const MediaConstraintsInterface* constraints, std::unique_ptr allocator, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, PeerConnectionObserver* observer) = 0; virtual rtc::scoped_refptr CreateLocalMediaStream(const std::string& label) = 0; - // Creates a AudioSourceInterface. - // |constraints| decides audio processing settings but can be NULL. + // Creates an AudioSourceInterface. + // |options| decides audio processing settings. virtual rtc::scoped_refptr CreateAudioSource( const cricket::AudioOptions& options) = 0; // Deprecated - use version above. + // Can use CopyConstraintsIntoAudioOptions to bridge the gap. virtual rtc::scoped_refptr CreateAudioSource( const MediaConstraintsInterface* constraints) = 0; - // Creates a VideoTrackSourceInterface. The new source take ownership of - // |capturer|. + // Creates a VideoTrackSourceInterface from |capturer|. + // TODO(deadbeef): We should aim to remove cricket::VideoCapturer from the + // API. It's mainly used as a wrapper around webrtc's provided + // platform-specific capturers, but these should be refactored to use + // VideoTrackSourceInterface directly. + // TODO(deadbeef): Make pure virtual once downstream mock PC factory classes + // are updated. virtual rtc::scoped_refptr CreateVideoSource( - cricket::VideoCapturer* capturer) = 0; + std::unique_ptr capturer) { + return nullptr; + } + // A video source creator that allows selection of resolution and frame rate. - // |constraints| decides video resolution and frame rate but can - // be NULL. - // In the NULL case, use the version above. + // |constraints| decides video resolution and frame rate but can be null. + // In the null case, use the version above. + // + // |constraints| is only used for the invocation of this method, and can + // safely be destroyed afterwards. + virtual rtc::scoped_refptr CreateVideoSource( + std::unique_ptr capturer, + const MediaConstraintsInterface* constraints) { + return nullptr; + } + + // Deprecated; please use the versions that take unique_ptrs above. + // TODO(deadbeef): Remove these once safe to do so. + virtual rtc::scoped_refptr CreateVideoSource( + cricket::VideoCapturer* capturer) { + return CreateVideoSource(std::unique_ptr(capturer)); + } virtual rtc::scoped_refptr CreateVideoSource( cricket::VideoCapturer* capturer, - const MediaConstraintsInterface* constraints) = 0; + const MediaConstraintsInterface* constraints) { + return CreateVideoSource(std::unique_ptr(capturer), + constraints); + } // Creates a new local VideoTrack. The same |source| can be used in several // tracks. @@ -618,7 +952,7 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { const std::string& label, VideoTrackSourceInterface* source) = 0; - // Creates an new AudioTrack. At the moment |source| can be NULL. + // Creates an new AudioTrack. At the moment |source| can be null. virtual rtc::scoped_refptr CreateAudioTrack(const std::string& label, AudioSourceInterface* source) = 0; @@ -635,25 +969,19 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { // Stops logging the AEC dump. virtual void StopAecDump() = 0; - // Starts RtcEventLog using existing file. Takes ownership of |file| and - // passes it on to VoiceEngine, which will take the ownership. If the - // operation fails the file will be closed. The logging will stop - // automatically after 10 minutes have passed, or when the StopRtcEventLog - // function is called. A maximum filesize in bytes can be set, the logging - // will be stopped before exceeding this limit. If max_size_bytes is set to a - // value <= 0, no limit will be used. - // This function as well as the StopRtcEventLog don't really belong on this - // interface, this is a temporary solution until we move the logging object - // from inside voice engine to webrtc::Call, which will happen when the VoE - // restructuring effort is further along. - // TODO(ivoc): Move this into being: - // PeerConnection => MediaController => webrtc::Call. + // This function is deprecated and will be removed when Chrome is updated to + // use the equivalent function on PeerConnectionInterface. + // TODO(ivoc) Remove after Chrome is updated. virtual bool StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes) = 0; - // Deprecated, use the version above. + // This function is deprecated and will be removed when Chrome is updated to + // use the equivalent function on PeerConnectionInterface. + // TODO(ivoc) Remove after Chrome is updated. virtual bool StartRtcEventLog(rtc::PlatformFile file) = 0; - // Stops logging the RtcEventLog. + // This function is deprecated and will be removed when Chrome is updated to + // use the equivalent function on PeerConnectionInterface. + // TODO(ivoc) Remove after Chrome is updated. virtual void StopRtcEventLog() = 0; protected: @@ -663,6 +991,14 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { ~PeerConnectionFactoryInterface() {} // NOLINT }; +// TODO(ossu): Remove these and define a real builtin audio encoder factory +// instead. +class AudioEncoderFactory : public rtc::RefCountInterface {}; +inline rtc::scoped_refptr +CreateBuiltinAudioEncoderFactory() { + return nullptr; +} + // Create a new instance of PeerConnectionFactoryInterface. // // This method relies on the thread it's called on as the "signaling thread" @@ -673,6 +1009,12 @@ class PeerConnectionFactoryInterface : public rtc::RefCountInterface { // rtc::Thread::Current()->Run(), or call // rtc::Thread::Current()->ProcessMessages() within the application's own // message loop. +rtc::scoped_refptr CreatePeerConnectionFactory( + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory); + +// Deprecated variant of the above. +// TODO(kwiberg): Remove. rtc::scoped_refptr CreatePeerConnectionFactory(); @@ -681,8 +1023,23 @@ CreatePeerConnectionFactory(); // |network_thread|, |worker_thread| and |signaling_thread| are // the only mandatory parameters. // -// If non-null, ownership of |default_adm|, |encoder_factory| and -// |decoder_factory| are transferred to the returned factory. +// If non-null, a reference is added to |default_adm|, and ownership of +// |video_encoder_factory| and |video_decoder_factory| is transferred to the +// returned factory. +// TODO(deadbeef): Use rtc::scoped_refptr<> and std::unique_ptr<> to make this +// ownership transfer and ref counting more obvious. +rtc::scoped_refptr CreatePeerConnectionFactory( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory, + cricket::WebRtcVideoEncoderFactory* video_encoder_factory, + cricket::WebRtcVideoDecoderFactory* video_decoder_factory); + +// Deprecated variant of the above. +// TODO(kwiberg): Remove. rtc::scoped_refptr CreatePeerConnectionFactory( rtc::Thread* network_thread, rtc::Thread* worker_thread, @@ -691,9 +1048,54 @@ rtc::scoped_refptr CreatePeerConnectionFactory( cricket::WebRtcVideoEncoderFactory* encoder_factory, cricket::WebRtcVideoDecoderFactory* decoder_factory); +// Create a new instance of PeerConnectionFactoryInterface with external audio +// mixer. +// +// If |audio_mixer| is null, an internal audio mixer will be created and used. +rtc::scoped_refptr +CreatePeerConnectionFactoryWithAudioMixer( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory, + cricket::WebRtcVideoEncoderFactory* video_encoder_factory, + cricket::WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer); + +// Deprecated variant of the above. +// TODO(kwiberg): Remove. +rtc::scoped_refptr +CreatePeerConnectionFactoryWithAudioMixer( + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + cricket::WebRtcVideoEncoderFactory* encoder_factory, + cricket::WebRtcVideoDecoderFactory* decoder_factory, + rtc::scoped_refptr audio_mixer); + // Create a new instance of PeerConnectionFactoryInterface. // Same thread is used as worker and network thread. inline rtc::scoped_refptr +CreatePeerConnectionFactory( + rtc::Thread* worker_and_network_thread, + rtc::Thread* signaling_thread, + AudioDeviceModule* default_adm, + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory, + cricket::WebRtcVideoEncoderFactory* video_encoder_factory, + cricket::WebRtcVideoDecoderFactory* video_decoder_factory) { + return CreatePeerConnectionFactory( + worker_and_network_thread, worker_and_network_thread, signaling_thread, + default_adm, audio_encoder_factory, audio_decoder_factory, + video_encoder_factory, video_decoder_factory); +} + +// Deprecated variant of the above. +// TODO(kwiberg): Remove. +inline rtc::scoped_refptr CreatePeerConnectionFactory( rtc::Thread* worker_and_network_thread, rtc::Thread* signaling_thread, diff --git a/include/webrtc/api/peerconnectionproxy.h b/include/webrtc/api/peerconnectionproxy.h index d35d5ba..2375dd4 100644 --- a/include/webrtc/api/peerconnectionproxy.h +++ b/include/webrtc/api/peerconnectionproxy.h @@ -11,17 +11,20 @@ #ifndef WEBRTC_API_PEERCONNECTIONPROXY_H_ #define WEBRTC_API_PEERCONNECTIONPROXY_H_ +#include +#include + #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/api/proxy.h" namespace webrtc { -// Define proxy for PeerConnectionInterface. +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_SIGNALING_PROXY_MAP(PeerConnection) - PROXY_METHOD0(rtc::scoped_refptr, - local_streams) - PROXY_METHOD0(rtc::scoped_refptr, - remote_streams) + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD0(rtc::scoped_refptr, local_streams) + PROXY_METHOD0(rtc::scoped_refptr, remote_streams) PROXY_METHOD1(bool, AddStream, MediaStreamInterface*) PROXY_METHOD1(void, RemoveStream, MediaStreamInterface*) PROXY_METHOD2(rtc::scoped_refptr, @@ -30,7 +33,8 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) std::vector) PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*) PROXY_METHOD1(rtc::scoped_refptr, - CreateDtmfSender, AudioTrackInterface*) + CreateDtmfSender, + AudioTrackInterface*) PROXY_METHOD2(rtc::scoped_refptr, CreateSender, const std::string&, @@ -39,16 +43,33 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) GetSenders) PROXY_CONSTMETHOD0(std::vector>, GetReceivers) - PROXY_METHOD3(bool, GetStats, StatsObserver*, + PROXY_METHOD3(bool, + GetStats, + StatsObserver*, MediaStreamTrackInterface*, StatsOutputLevel) + PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*) PROXY_METHOD2(rtc::scoped_refptr, - CreateDataChannel, const std::string&, const DataChannelInit*) + CreateDataChannel, + const std::string&, + const DataChannelInit*) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, remote_description) - PROXY_METHOD2(void, CreateOffer, CreateSessionDescriptionObserver*, + PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, + pending_local_description) + PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, + pending_remote_description) + PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, + current_local_description) + PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, + current_remote_description) + PROXY_METHOD2(void, + CreateOffer, + CreateSessionDescriptionObserver*, const MediaConstraintsInterface*) - PROXY_METHOD2(void, CreateAnswer, CreateSessionDescriptionObserver*, + PROXY_METHOD2(void, + CreateAnswer, + CreateSessionDescriptionObserver*, const MediaConstraintsInterface*) PROXY_METHOD2(void, CreateOffer, @@ -58,10 +79,19 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) CreateAnswer, CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&) - PROXY_METHOD2(void, SetLocalDescription, SetSessionDescriptionObserver*, + PROXY_METHOD2(void, + SetLocalDescription, + SetSessionDescriptionObserver*, SessionDescriptionInterface*) - PROXY_METHOD2(void, SetRemoteDescription, SetSessionDescriptionObserver*, + PROXY_METHOD2(void, + SetRemoteDescription, + SetSessionDescriptionObserver*, SessionDescriptionInterface*) + PROXY_METHOD0(PeerConnectionInterface::RTCConfiguration, GetConfiguration); + PROXY_METHOD2(bool, + SetConfiguration, + const PeerConnectionInterface::RTCConfiguration&, + RTCError*); PROXY_METHOD1(bool, SetConfiguration, const PeerConnectionInterface::RTCConfiguration&); @@ -71,11 +101,12 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) const std::vector&); PROXY_METHOD1(void, RegisterUMAObserver, UMAObserver*) PROXY_METHOD0(SignalingState, signaling_state) - PROXY_METHOD0(IceState, ice_state) PROXY_METHOD0(IceConnectionState, ice_connection_state) PROXY_METHOD0(IceGatheringState, ice_gathering_state) + PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t) + PROXY_METHOD0(void, StopRtcEventLog) PROXY_METHOD0(void, Close) -END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/portallocatorfactory.h b/include/webrtc/api/portallocatorfactory.h deleted file mode 100644 index cefd750..0000000 --- a/include/webrtc/api/portallocatorfactory.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -// TODO(deadbeef): Remove this file once chromium build files no longer -// reference it. - -#ifndef WEBRTC_API_PORTALLOCATORFACTORY_H_ -#define WEBRTC_API_PORTALLOCATORFACTORY_H_ - -#endif // WEBRTC_API_PORTALLOCATORFACTORY_H_ diff --git a/include/webrtc/api/proxy.h b/include/webrtc/api/proxy.h index 2df85c4..862de87 100644 --- a/include/webrtc/api/proxy.h +++ b/include/webrtc/api/proxy.h @@ -10,6 +10,7 @@ // This file contains Macros for creating proxies for webrtc MediaStream and // PeerConnection classes. +// TODO(deadbeef): Move this to pc/; this is part of the implementation. // // Example usage: @@ -28,13 +29,14 @@ // }; // // BEGIN_PROXY_MAP(Test) +// PROXY_SIGNALING_THREAD_DESTRUCTOR() // PROXY_METHOD0(std::string, FooA) // PROXY_CONSTMETHOD1(std::string, FooB, arg1) // PROXY_WORKER_METHOD1(std::string, FooC, arg1) -// END_PROXY() +// END_PROXY_MAP() // -// where the first two methods are invoked on the signaling thread, -// and the third is invoked on the worker thread. +// Where the destructor and first two methods are invoked on the signaling +// thread, and the third is invoked on the worker thread. // // The proxy can be created using // @@ -43,11 +45,15 @@ // // The variant defined with BEGIN_SIGNALING_PROXY_MAP is unaware of // the worker thread, and invokes all methods on the signaling thread. +// +// The variant defined with BEGIN_OWNED_PROXY_MAP does not use +// refcounting, and instead just takes ownership of the object being proxied. #ifndef WEBRTC_API_PROXY_H_ #define WEBRTC_API_PROXY_H_ #include +#include #include "webrtc/base/event.h" #include "webrtc/base/thread.h" @@ -59,24 +65,31 @@ class ReturnType { public: template void Invoke(C* c, M m) { r_ = (c->*m)(); } - template - void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); } - template - void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); } - template - void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); } + template + void Invoke(C* c, M m, T1 a1) { + r_ = (c->*m)(std::move(a1)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2) { + r_ = (c->*m)(std::move(a1), std::move(a2)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3)); + } template void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) { - r_ = (c->*m)(a1, a2, a3, a4); + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4)); } template void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { - r_ = (c->*m)(a1, a2, a3, a4, a5); + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4), + std::move(a5)); } - R value() { return r_; } + R moved_result() { return std::move(r_); } private: R r_; @@ -87,14 +100,20 @@ class ReturnType { public: template void Invoke(C* c, M m) { (c->*m)(); } - template - void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); } - template - void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); } - template - void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); } - - void value() {} + template + void Invoke(C* c, M m, T1 a1) { + (c->*m)(std::move(a1)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2) { + (c->*m)(std::move(a1), std::move(a2)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { + (c->*m)(std::move(a1), std::move(a2), std::move(a3)); + } + + void moved_result() {} }; namespace internal { @@ -107,18 +126,21 @@ class SynchronousMethodCall : e_(), proxy_(proxy) {} ~SynchronousMethodCall() {} - void Invoke(rtc::Thread* t) { + void Invoke(const rtc::Location& posted_from, rtc::Thread* t) { if (t->IsCurrent()) { - proxy_->OnMessage(NULL); + proxy_->OnMessage(nullptr); } else { e_.reset(new rtc::Event(false, false)); - t->Post(this, 0); + t->Post(posted_from, this, 0); e_->Wait(rtc::Event::kForever); } } private: - void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); } + void OnMessage(rtc::Message*) { + proxy_->OnMessage(nullptr); + e_->Set(); + } std::unique_ptr e_; rtc::MessageHandler* proxy_; }; @@ -132,9 +154,9 @@ class MethodCall0 : public rtc::Message, typedef R (C::*Method)(); MethodCall0(C* c, Method m) : c_(c), m_(m) {} - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: @@ -152,9 +174,9 @@ class ConstMethodCall0 : public rtc::Message, typedef R (C::*Method)() const; ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {} - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: @@ -170,15 +192,15 @@ class MethodCall1 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1); - MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} + MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {} - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); } C* c_; Method m_; @@ -191,15 +213,15 @@ class ConstMethodCall1 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1) const; - ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} + ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {} - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); } C* c_; Method m_; @@ -212,15 +234,18 @@ class MethodCall2 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1, T2 a2); - MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {} + MethodCall2(C* c, Method m, T1 a1, T2 a2) + : c_(c), m_(m), a1_(std::move(a1)), a2_(std::move(a2)) {} - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_)); + } C* c_; Method m_; @@ -235,15 +260,21 @@ class MethodCall3 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3); MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {} - - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)) {} + + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_)); + } C* c_; Method m_; @@ -260,15 +291,23 @@ class MethodCall4 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4); MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)), + a4_(std::move(a4)) {} + + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_), + std::move(a4_)); + } C* c_; Method m_; @@ -286,15 +325,24 @@ class MethodCall5 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - - R Marshal(rtc::Thread* t) { - internal::SynchronousMethodCall(this).Invoke(t); - return r_.value(); + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)), + a4_(std::move(a4)), + a5_(std::move(a5)) {} + + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_, a5_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_), + std::move(a4_), std::move(a5_)); + } C* c_; Method m_; @@ -306,125 +354,228 @@ class MethodCall5 : public rtc::Message, T5 a5_; }; -#define BEGIN_SIGNALING_PROXY_MAP(c) \ - class c##Proxy : public c##Interface { \ - protected: \ - typedef c##Interface C; \ - c##Proxy(rtc::Thread* signaling_thread, C* c) \ - : signaling_thread_(signaling_thread), c_(c) {} \ - ~c##Proxy() { \ - MethodCall0 call( \ - this, &c##Proxy::Release_s); \ - call.Marshal(signaling_thread_); \ - } \ - \ - public: \ - static rtc::scoped_refptr Create(rtc::Thread* signaling_thread, C* c) { \ - return new rtc::RefCountedObject( \ - signaling_thread, c); \ - } -#define BEGIN_PROXY_MAP(c) \ - class c##Proxy : public c##Interface { \ - protected: \ - typedef c##Interface C; \ - c##Proxy(rtc::Thread* signaling_thread, rtc::Thread* worker_thread, C* c) \ - : signaling_thread_(signaling_thread), \ - worker_thread_(worker_thread), \ - c_(c) {} \ - ~c##Proxy() { \ - MethodCall0 call(this, &c##Proxy::Release_s); \ - call.Marshal(signaling_thread_); \ - } \ - \ - public: \ - static rtc::scoped_refptr Create( \ - rtc::Thread* signaling_thread, rtc::Thread* worker_thread, C* c) { \ - return new rtc::RefCountedObject( \ - signaling_thread, worker_thread, c); \ - } +// Helper macros to reduce code duplication. +#define PROXY_MAP_BOILERPLATE(c) \ + template \ + class c##ProxyWithInternal; \ + typedef c##ProxyWithInternal c##Proxy; \ + template \ + class c##ProxyWithInternal : public c##Interface { \ + protected: \ + typedef c##Interface C; \ + \ + public: \ + const INTERNAL_CLASS* internal() const { return c_; } \ + INTERNAL_CLASS* internal() { return c_; } + +#define END_PROXY_MAP() \ + }; + +#define SIGNALING_PROXY_MAP_BOILERPLATE(c) \ + protected: \ + c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \ + : signaling_thread_(signaling_thread), c_(c) {} \ + \ + private: \ + mutable rtc::Thread* signaling_thread_; + +#define WORKER_PROXY_MAP_BOILERPLATE(c) \ + protected: \ + c##ProxyWithInternal(rtc::Thread* signaling_thread, \ + rtc::Thread* worker_thread, INTERNAL_CLASS* c) \ + : signaling_thread_(signaling_thread), \ + worker_thread_(worker_thread), \ + c_(c) {} \ + \ + private: \ + mutable rtc::Thread* signaling_thread_; \ + mutable rtc::Thread* worker_thread_; + +// Note that the destructor is protected so that the proxy can only be +// destroyed via RefCountInterface. +#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ + protected: \ + ~c##ProxyWithInternal() { \ + MethodCall0 call( \ + this, &c##ProxyWithInternal::DestroyInternal); \ + call.Marshal(RTC_FROM_HERE, destructor_thread()); \ + } \ + \ + private: \ + void DestroyInternal() { c_ = nullptr; } \ + rtc::scoped_refptr c_; + +// Note: This doesn't use a unique_ptr, because it intends to handle a corner +// case where an object's deletion triggers a callback that calls back into +// this proxy object. If relying on a unique_ptr to delete the object, its +// inner pointer would be set to null before this reentrant callback would have +// a chance to run, resulting in a segfault. +#define OWNED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + ~c##ProxyWithInternal() { \ + MethodCall0 call( \ + this, &c##ProxyWithInternal::DestroyInternal); \ + call.Marshal(RTC_FROM_HERE, destructor_thread()); \ + } \ + \ + private: \ + void DestroyInternal() { delete c_; } \ + INTERNAL_CLASS* c_; + +#define BEGIN_SIGNALING_PROXY_MAP(c) \ + PROXY_MAP_BOILERPLATE(c) \ + SIGNALING_PROXY_MAP_BOILERPLATE(c) \ + REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + static rtc::scoped_refptr Create( \ + rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \ + return new rtc::RefCountedObject(signaling_thread, \ + c); \ + } + +#define BEGIN_PROXY_MAP(c) \ + PROXY_MAP_BOILERPLATE(c) \ + WORKER_PROXY_MAP_BOILERPLATE(c) \ + REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + static rtc::scoped_refptr Create( \ + rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \ + INTERNAL_CLASS* c) { \ + return new rtc::RefCountedObject(signaling_thread, \ + worker_thread, c); \ + } -#define PROXY_METHOD0(r, method) \ - r method() override { \ - MethodCall0 call(c_.get(), &C::method); \ - return call.Marshal(signaling_thread_); \ +#define BEGIN_OWNED_PROXY_MAP(c) \ + PROXY_MAP_BOILERPLATE(c) \ + WORKER_PROXY_MAP_BOILERPLATE(c) \ + OWNED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + static std::unique_ptr Create( \ + rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \ + std::unique_ptr c) { \ + return std::unique_ptr(new c##ProxyWithInternal( \ + signaling_thread, worker_thread, c.release())); \ } -#define PROXY_CONSTMETHOD0(r, method) \ - r method() const override { \ - ConstMethodCall0 call(c_.get(), &C::method); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_SIGNALING_THREAD_DESTRUCTOR() \ + private: \ + rtc::Thread* destructor_thread() const { return signaling_thread_; } \ + \ + public: // NOLINTNEXTLINE + +#define PROXY_WORKER_THREAD_DESTRUCTOR() \ + private: \ + rtc::Thread* destructor_thread() const { return worker_thread_; } \ + \ + public: // NOLINTNEXTLINE + +#define PROXY_METHOD0(r, method) \ + r method() override { \ + MethodCall0 call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD1(r, method, t1) \ - r method(t1 a1) override { \ - MethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_CONSTMETHOD0(r, method) \ + r method() const override { \ + ConstMethodCall0 call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_CONSTMETHOD1(r, method, t1) \ - r method(t1 a1) const override { \ - ConstMethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall1 call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ + } + +#define PROXY_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall1 call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } #define PROXY_METHOD2(r, method, t1, t2) \ r method(t1 a1, t2 a2) override { \ - MethodCall2 call(c_.get(), &C::method, a1, a2); \ - return call.Marshal(signaling_thread_); \ + MethodCall2 call(c_, &C::method, std::move(a1), \ + std::move(a2)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD3(r, method, t1, t2, t3) \ - r method(t1 a1, t2 a2, t3 a3) override { \ - MethodCall3 call(c_.get(), &C::method, a1, a2, a3); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_METHOD3(r, method, t1, t2, t3) \ + r method(t1 a1, t2 a2, t3 a3) override { \ + MethodCall3 call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \ - r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \ - MethodCall4 call(c_.get(), &C::method, a1, a2, a3, \ - a4); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \ + r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \ + MethodCall4 call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3), \ + std::move(a4)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \ - r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \ - MethodCall5 call(c_.get(), &C::method, a1, a2, \ - a3, a4, a5); \ - return call.Marshal(signaling_thread_); \ +#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \ + r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \ + MethodCall5 call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3), \ + std::move(a4), std::move(a5)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } // Define methods which should be invoked on the worker thread. -#define PROXY_WORKER_METHOD1(r, method, t1) \ - r method(t1 a1) override { \ - MethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(worker_thread_); \ +#define PROXY_WORKER_METHOD0(r, method) \ + r method() override { \ + MethodCall0 call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } + +#define PROXY_WORKER_CONSTMETHOD0(r, method) \ + r method() const override { \ + ConstMethodCall0 call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } + +#define PROXY_WORKER_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall1 call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } + +#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall1 call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ } #define PROXY_WORKER_METHOD2(r, method, t1, t2) \ r method(t1 a1, t2 a2) override { \ - MethodCall2 call(c_.get(), &C::method, a1, a2); \ - return call.Marshal(worker_thread_); \ + MethodCall2 call(c_, &C::method, std::move(a1), \ + std::move(a2)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ } -#define END_SIGNALING_PROXY() \ - private:\ - void Release_s() {\ - c_ = NULL;\ - }\ - mutable rtc::Thread* signaling_thread_;\ - rtc::scoped_refptr c_;\ - }; +#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \ + r method(t1 a1, t2 a2) const override { \ + ConstMethodCall2 call(c_, &C::method, std::move(a1), \ + std::move(a2)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } + +#define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \ + r method(t1 a1, t2 a2, t3 a3) override { \ + MethodCall3 call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define END_PROXY() \ - private: \ - void Release_s() { \ - c_ = NULL; \ - } \ - mutable rtc::Thread* signaling_thread_; \ - mutable rtc::Thread* worker_thread_; \ - rtc::scoped_refptr c_; \ - }; \ +#define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \ + r method(t1 a1, t2 a2, t3 a3) const override { \ + ConstMethodCall3 call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } } // namespace webrtc diff --git a/include/webrtc/api/remoteaudiotrack.h b/include/webrtc/api/remoteaudiotrack.h deleted file mode 100644 index 47de1b4..0000000 --- a/include/webrtc/api/remoteaudiotrack.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// TODO(tommi): Delete this file when removed from build files in Chromium. diff --git a/include/webrtc/api/rtcerror.h b/include/webrtc/api/rtcerror.h new file mode 100644 index 0000000..2ba7837 --- /dev/null +++ b/include/webrtc/api/rtcerror.h @@ -0,0 +1,300 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_RTCERROR_H_ +#define WEBRTC_API_RTCERROR_H_ + +#include +#include +#include // For std::move. + +#include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" + +namespace webrtc { + +// Enumeration to represent distinct classes of errors that an application +// may wish to act upon differently. These roughly map to DOMExceptions or +// RTCError "errorDetailEnum" values in the web API, as described in the +// comments below. +enum class RTCErrorType { + // No error. + NONE, + + // An operation is valid, but currently unsupported. + // Maps to OperationError DOMException. + UNSUPPORTED_OPERATION, + + // A supplied parameter is valid, but currently unsupported. + // Maps to OperationError DOMException. + UNSUPPORTED_PARAMETER, + + // General error indicating that a supplied parameter is invalid. + // Maps to InvalidAccessError or TypeError DOMException depending on context. + INVALID_PARAMETER, + + // Slightly more specific than INVALID_PARAMETER; a parameter's value was + // outside the allowed range. + // Maps to RangeError DOMException. + INVALID_RANGE, + + // Slightly more specific than INVALID_PARAMETER; an error occurred while + // parsing string input. + // Maps to SyntaxError DOMException. + SYNTAX_ERROR, + + // The object does not support this operation in its current state. + // Maps to InvalidStateError DOMException. + INVALID_STATE, + + // An attempt was made to modify the object in an invalid way. + // Maps to InvalidModificationError DOMException. + INVALID_MODIFICATION, + + // An error occurred within an underlying network protocol. + // Maps to NetworkError DOMException. + NETWORK_ERROR, + + // Some resource has been exhausted; file handles, hardware resources, ports, + // etc. + // Maps to OperationError DOMException. + RESOURCE_EXHAUSTED, + + // The operation failed due to an internal error. + // Maps to OperationError DOMException. + INTERNAL_ERROR, +}; + +// Roughly corresponds to RTCError in the web api. Holds an error type, a +// message, and possibly additional information specific to that error. +// +// Doesn't contain anything beyond a type and message now, but will in the +// future as more errors are implemented. +class RTCError { + public: + // Constructors. + + // Creates a "no error" error. + RTCError() {} + explicit RTCError(RTCErrorType type) : type_(type) {} + // For performance, prefer using the constructor that takes a const char* if + // the message is a static string. + RTCError(RTCErrorType type, const char* message) + : type_(type), static_message_(message), have_string_message_(false) {} + RTCError(RTCErrorType type, std::string&& message) + : type_(type), string_message_(message), have_string_message_(true) {} + + // Delete the copy constructor and assignment operator; there aren't any use + // cases where you should need to copy an RTCError, as opposed to moving it. + // Can revisit this decision if use cases arise in the future. + RTCError(const RTCError& other) = delete; + RTCError& operator=(const RTCError& other) = delete; + + // Move constructor and move-assignment operator. + RTCError(RTCError&& other); + RTCError& operator=(RTCError&& other); + + ~RTCError(); + + // Identical to default constructed error. + // + // Preferred over the default constructor for code readability. + static RTCError OK(); + + // Error type. + RTCErrorType type() const { return type_; } + void set_type(RTCErrorType type) { type_ = type; } + + // Human-readable message describing the error. Shouldn't be used for + // anything but logging/diagnostics, since messages are not guaranteed to be + // stable. + const char* message() const; + // For performance, prefer using the method that takes a const char* if the + // message is a static string. + void set_message(const char* message); + void set_message(std::string&& message); + + // Convenience method for situations where you only care whether or not an + // error occurred. + bool ok() const { return type_ == RTCErrorType::NONE; } + + private: + RTCErrorType type_ = RTCErrorType::NONE; + // For performance, we use static strings wherever possible. But in some + // cases the error string may need to be constructed, in which case an + // std::string is used. + union { + const char* static_message_ = ""; + std::string string_message_; + }; + // Whether or not |static_message_| or |string_message_| is being used in the + // above union. + bool have_string_message_ = false; +}; + +// Outputs the error as a friendly string. Update this method when adding a new +// error type. +// +// Only intended to be used for logging/disagnostics. +std::ostream& operator<<(std::ostream& stream, RTCErrorType error); + +// Helper macro that can be used by implementations to create an error with a +// message and log it. |message| should be a string literal or movable +// std::string. +#define LOG_AND_RETURN_ERROR_EX(type, message, severity) \ + { \ + RTC_DCHECK(type != RTCErrorType::NONE); \ + LOG(severity) << message << " (" << type << ")"; \ + return webrtc::RTCError(type, message); \ + } + +#define LOG_AND_RETURN_ERROR(type, message) \ + LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR) + +// RTCErrorOr is the union of an RTCError object and a T object. RTCErrorOr +// models the concept of an object that is either a usable value, or an error +// Status explaining why such a value is not present. To this end RTCErrorOr +// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is +// enforced by a debug check in most cases. +// +// The primary use-case for RTCErrorOr is as the return value of a function +// which may fail. For example, CreateRtpSender will fail if the parameters +// could not be successfully applied at the media engine level, but if +// successful will return a unique_ptr to an RtpSender. +// +// Example client usage for a RTCErrorOr>: +// +// RTCErrorOr> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr foo = result.ConsumeValue(); +// foo->DoSomethingCool(); +// } else { +// LOG(LS_ERROR) << result.error(); +// } +// +// Example factory implementation returning RTCErrorOr>: +// +// RTCErrorOr> FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive"); +// } else { +// return std::unique_ptr(new Foo(arg)); +// } +// } +// +template +class RTCErrorOr { + // Used to convert between RTCErrorOr/RtcErrorOr, when an implicit + // conversion from Foo to Bar exists. + template + friend class RTCErrorOr; + + public: + typedef T element_type; + + // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This + // is marked 'explicit' to try to catch cases like 'return {};', where people + // think RTCErrorOr> will be initialized with an empty + // vector, instead of a RTCErrorType::INTERNAL_ERROR error. + explicit RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {} + + // Constructs a new RTCErrorOr with the given non-ok error. After calling + // this constructor, calls to value() will DCHECK-fail. + // + // NOTE: Not explicit - we want to use RTCErrorOr as a return + // value, so it is convenient and sensible to be able to do 'return + // RTCError(...)' when the return type is RTCErrorOr. + // + // REQUIRES: !error.ok(). This requirement is DCHECKed. + RTCErrorOr(RTCError&& error) : error_(std::move(error)) { + RTC_DCHECK(!error.ok()); + } + + // Constructs a new RTCErrorOr with the given value. After calling this + // constructor, calls to value() will succeed, and calls to error() will + // return a default-constructed RTCError. + // + // NOTE: Not explicit - we want to use RTCErrorOr as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when the return type is RTCErrorOr. + RTCErrorOr(T&& value) : value_(std::move(value)) {} + + // Delete the copy constructor and assignment operator; there aren't any use + // cases where you should need to copy an RTCErrorOr, as opposed to moving + // it. Can revisit this decision if use cases arise in the future. + RTCErrorOr(const RTCErrorOr& other) = delete; + RTCErrorOr& operator=(const RTCErrorOr& other) = delete; + + // Move constructor and move-assignment operator. + // + // Visual Studio doesn't support "= default" with move constructors or + // assignment operators (even though they compile, they segfault), so define + // them explicitly. + RTCErrorOr(RTCErrorOr&& other) + : error_(std::move(other.error_)), value_(std::move(other.value_)) {} + RTCErrorOr& operator=(RTCErrorOr&& other) { + error_ = std::move(other.error_); + value_ = std::move(other.value_); + return *this; + } + + // Conversion constructor and assignment operator; T must be copy or move + // constructible from U. + template + RTCErrorOr(RTCErrorOr other) + : error_(std::move(other.error_)), value_(std::move(other.value_)) {} + template + RTCErrorOr& operator=(RTCErrorOr other) { + error_ = std::move(other.error_); + value_ = std::move(other.value_); + return *this; + } + + // Returns a reference to our error. If this contains a T, then returns + // default-constructed RTCError. + const RTCError& error() const { return error_; } + + // Moves the error. Can be useful if, say "CreateFoo" returns an + // RTCErrorOr, and internally calls "CreateBar" which returns an + // RTCErrorOr, and wants to forward the error up the stack. + RTCError MoveError() { return std::move(error_); } + + // Returns this->error().ok() + bool ok() const { return error_.ok(); } + + // Returns a reference to our current value, or DCHECK-fails if !this->ok(). + // + // Can be convenient for the implementation; for example, a method may want + // to access the value in some way before returning it to the next method on + // the stack. + const T& value() const { + RTC_DCHECK(ok()); + return value_; + } + T& value() { + RTC_DCHECK(ok()); + return value_; + } + + // Moves our current value out of this object and returns it, or DCHECK-fails + // if !this->ok(). + T MoveValue() { + RTC_DCHECK(ok()); + return std::move(value_); + } + + private: + RTCError error_; + T value_; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_RTCERROR_H_ diff --git a/include/webrtc/api/rtpparameters.h b/include/webrtc/api/rtpparameters.h index 5c79ab4..e4fe47b 100644 --- a/include/webrtc/api/rtpparameters.h +++ b/include/webrtc/api/rtpparameters.h @@ -12,18 +12,325 @@ #define WEBRTC_API_RTPPARAMETERS_H_ #include +#include #include +#include "webrtc/api/mediatypes.h" +#include "webrtc/config.h" +#include "webrtc/base/optional.h" + namespace webrtc { -// These structures are defined as part of the RtpSender interface. -// See http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface for details. +// These structures are intended to mirror those defined by: +// http://draft.ortc.org/#rtcrtpdictionaries* +// Contains everything specified as of 2017 Jan 24. +// +// They are used when retrieving or modifying the parameters of an +// RtpSender/RtpReceiver, or retrieving capabilities. +// +// Note on conventions: Where ORTC may use "octet", "short" and "unsigned" +// types, we typically use "int", in keeping with our style guidelines. The +// parameter's actual valid range will be enforced when the parameters are set, +// rather than when the parameters struct is built. An exception is made for +// SSRCs, since they use the full unsigned 32-bit range, and aren't expected to +// be used for any numeric comparisons/operations. +// +// Additionally, where ORTC uses strings, we may use enums for things that have +// a fixed number of supported values. However, for things that can be extended +// (such as codecs, by providing an external encoder factory), a string +// identifier is used. + +enum class FecMechanism { + RED, + RED_AND_ULPFEC, + FLEXFEC, +}; + +// Used in RtcpFeedback struct. +enum class RtcpFeedbackType { + CCM, + NACK, + REMB, // "goog-remb" + TRANSPORT_CC, +}; + +// Used in RtcpFeedback struct when type is NACK or CCM. +enum class RtcpFeedbackMessageType { + // Equivalent to {type: "nack", parameter: undefined} in ORTC. + GENERIC_NACK, + PLI, // Usable with NACK. + FIR, // Usable with CCM. +}; + +enum class DtxStatus { + DISABLED, + ENABLED, +}; + +enum class DegradationPreference { + MAINTAIN_FRAMERATE, + MAINTAIN_RESOLUTION, + BALANCED, +}; + +enum class PriorityType { VERY_LOW, LOW, MEDIUM, HIGH }; + +struct RtcpFeedback { + RtcpFeedbackType type = RtcpFeedbackType::CCM; + + // Equivalent to ORTC "parameter" field with slight differences: + // 1. It's an enum instead of a string. + // 2. Generic NACK feedback is represented by a GENERIC_NACK message type, + // rather than an unset "parameter" value. + rtc::Optional message_type; + + // Constructors for convenience. + RtcpFeedback() {} + explicit RtcpFeedback(RtcpFeedbackType type) : type(type) {} + RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type) + : type(type), message_type(message_type) {} + + bool operator==(const RtcpFeedback& o) const { + return type == o.type && message_type == o.message_type; + } + bool operator!=(const RtcpFeedback& o) const { return !(*this == o); } +}; + +// RtpCodecCapability is to RtpCodecParameters as RtpCapabilities is to +// RtpParameters. This represents the static capabilities of an endpoint's +// implementation of a codec. +struct RtpCodecCapability { + // Build MIME "type/subtype" string from |name| and |kind|. + std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; } + + // Used to identify the codec. Equivalent to MIME subtype. + std::string name; + + // The media type of this codec. Equivalent to MIME top-level type. + cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO; + + // Clock rate in Hertz. If unset, the codec is applicable to any clock rate. + rtc::Optional clock_rate; + + // Default payload type for this codec. Mainly needed for codecs that use + // that have statically assigned payload types. + rtc::Optional preferred_payload_type; + + // Maximum packetization time supported by an RtpReceiver for this codec. + // TODO(deadbeef): Not implemented. + rtc::Optional max_ptime; + + // Preferred packetization time for an RtpReceiver or RtpSender of this + // codec. + // TODO(deadbeef): Not implemented. + rtc::Optional ptime; + + // The number of audio channels supported. Unused for video codecs. + rtc::Optional num_channels; + + // Feedback mechanisms supported for this codec. + std::vector rtcp_feedback; + + // Codec-specific parameters that must be signaled to the remote party. + // + // Corresponds to "a=fmtp" parameters in SDP. + // + // Contrary to ORTC, these parameters are named using all lowercase strings. + // This helps make the mapping to SDP simpler, if an application is using + // SDP. Boolean values are represented by the string "1". + std::unordered_map parameters; + + // Codec-specific parameters that may optionally be signaled to the remote + // party. + // TODO(deadbeef): Not implemented. + std::unordered_map options; + + // Maximum number of temporal layer extensions supported by this codec. + // For example, a value of 1 indicates that 2 total layers are supported. + // TODO(deadbeef): Not implemented. + int max_temporal_layer_extensions = 0; + + // Maximum number of spatial layer extensions supported by this codec. + // For example, a value of 1 indicates that 2 total layers are supported. + // TODO(deadbeef): Not implemented. + int max_spatial_layer_extensions = 0; + + // Whether the implementation can send/receive SVC layers with distinct + // SSRCs. Always false for audio codecs. True for video codecs that support + // scalable video coding with MRST. + // TODO(deadbeef): Not implemented. + bool svc_multi_stream_support = false; + + bool operator==(const RtpCodecCapability& o) const { + return name == o.name && kind == o.kind && clock_rate == o.clock_rate && + preferred_payload_type == o.preferred_payload_type && + max_ptime == o.max_ptime && ptime == o.ptime && + num_channels == o.num_channels && rtcp_feedback == o.rtcp_feedback && + parameters == o.parameters && options == o.options && + max_temporal_layer_extensions == o.max_temporal_layer_extensions && + max_spatial_layer_extensions == o.max_spatial_layer_extensions && + svc_multi_stream_support == o.svc_multi_stream_support; + } + bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); } +}; + +// Used in RtpCapabilities; represents the capabilities/preferences of an +// implementation for a header extension. +// +// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was +// added here for consistency and to avoid confusion with +// RtpHeaderExtensionParameters. +// +// Note that ORTC includes a "kind" field, but we omit this because it's +// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)", +// you know you're getting audio capabilities. +struct RtpHeaderExtensionCapability { + // URI of this extension, as defined in RFC5285. + std::string uri; + + // Preferred value of ID that goes in the packet. + rtc::Optional preferred_id; + + // If true, it's preferred that the value in the header is encrypted. + // TODO(deadbeef): Not implemented. + bool preferred_encrypt = false; + + // Constructors for convenience. + RtpHeaderExtensionCapability() = default; + explicit RtpHeaderExtensionCapability(const std::string& uri) : uri(uri) {} + RtpHeaderExtensionCapability(const std::string& uri, int preferred_id) + : uri(uri), preferred_id(preferred_id) {} + + bool operator==(const RtpHeaderExtensionCapability& o) const { + return uri == o.uri && preferred_id == o.preferred_id && + preferred_encrypt == o.preferred_encrypt; + } + bool operator!=(const RtpHeaderExtensionCapability& o) const { + return !(*this == o); + } +}; + +// See webrtc/config.h. Has "uri" and "id" fields. +// TODO(deadbeef): This is missing the "encrypt" flag, which is unimplemented. +typedef RtpExtension RtpHeaderExtensionParameters; + +struct RtpFecParameters { + // If unset, a value is chosen by the implementation. + // Works just like RtpEncodingParameters::ssrc. + rtc::Optional ssrc; + + FecMechanism mechanism = FecMechanism::RED; + + // Constructors for convenience. + RtpFecParameters() = default; + explicit RtpFecParameters(FecMechanism mechanism) : mechanism(mechanism) {} + RtpFecParameters(FecMechanism mechanism, uint32_t ssrc) + : ssrc(ssrc), mechanism(mechanism) {} + + bool operator==(const RtpFecParameters& o) const { + return ssrc == o.ssrc && mechanism == o.mechanism; + } + bool operator!=(const RtpFecParameters& o) const { return !(*this == o); } +}; + +struct RtpRtxParameters { + // If unset, a value is chosen by the implementation. + // Works just like RtpEncodingParameters::ssrc. + rtc::Optional ssrc; + + // Constructors for convenience. + RtpRtxParameters() = default; + explicit RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {} + + bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; } + bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); } +}; + struct RtpEncodingParameters { + // If unset, a value is chosen by the implementation. + // + // Note that the chosen value is NOT returned by GetParameters, because it + // may change due to an SSRC conflict, in which case the conflict is handled + // internally without any event. Another way of looking at this is that an + // unset SSRC acts as a "wildcard" SSRC. + rtc::Optional ssrc; + + // Can be used to reference a codec in the |codecs| member of the + // RtpParameters that contains this RtpEncodingParameters. If unset, the + // implementation will choose the first possible codec (if a sender), or + // prepare to receive any codec (for a receiver). + // TODO(deadbeef): Not implemented. Implementation of RtpSender will always + // choose the first codec from the list. + rtc::Optional codec_payload_type; + + // Specifies the FEC mechanism, if set. + // TODO(deadbeef): Not implemented. Current implementation will use whatever + // FEC codecs are available, including red+ulpfec. + rtc::Optional fec; + + // Specifies the RTX parameters, if set. + // TODO(deadbeef): Not implemented with PeerConnection senders/receivers. + rtc::Optional rtx; + + // Only used for audio. If set, determines whether or not discontinuous + // transmission will be used, if an available codec supports it. If not + // set, the implementation default setting will be used. + // TODO(deadbeef): Not implemented. Current implementation will use a CN + // codec as long as it's present. + rtc::Optional dtx; + + // The relative priority of this encoding. + // TODO(deadbeef): Not implemented. + rtc::Optional priority; + + // If set, this represents the Transport Independent Application Specific + // maximum bandwidth defined in RFC3890. If unset, there is no maximum + // bitrate. + // + // Just called "maxBitrate" in ORTC spec. + // + // TODO(deadbeef): With ORTC RtpSenders, this currently sets the total + // bandwidth for the entire bandwidth estimator (audio and video). This is + // just always how "b=AS" was handled, but it's not correct and should be + // fixed. + rtc::Optional max_bitrate_bps; + + // TODO(deadbeef): Not implemented. + rtc::Optional max_framerate; + + // For video, scale the resolution down by this factor. + // TODO(deadbeef): Not implemented. + double scale_resolution_down_by = 1.0; + + // Scale the framerate down by this factor. + // TODO(deadbeef): Not implemented. + double scale_framerate_down_by = 1.0; + + // For an RtpSender, set to true to cause this encoding to be sent, and false + // for it not to be sent. For an RtpReceiver, set to true to cause the + // encoding to be decoded, and false for it to be ignored. + // TODO(deadbeef): Not implemented for PeerConnection RtpReceivers. bool active = true; - int max_bitrate_bps = -1; + + // Value to use for RID RTP header extension. + // Called "encodingId" in ORTC. + // TODO(deadbeef): Not implemented. + std::string rid; + + // RIDs of encodings on which this layer depends. + // Called "dependencyEncodingIds" in ORTC spec. + // TODO(deadbeef): Not implemented. + std::vector dependency_rids; bool operator==(const RtpEncodingParameters& o) const { - return active == o.active && max_bitrate_bps == o.max_bitrate_bps; + return ssrc == o.ssrc && codec_payload_type == o.codec_payload_type && + fec == o.fec && rtx == o.rtx && dtx == o.dtx && + priority == o.priority && max_bitrate_bps == o.max_bitrate_bps && + max_framerate == o.max_framerate && + scale_resolution_down_by == o.scale_resolution_down_by && + scale_framerate_down_by == o.scale_framerate_down_by && + active == o.active && rid == o.rid && + dependency_rids == o.dependency_rids; } bool operator!=(const RtpEncodingParameters& o) const { return !(*this == o); @@ -31,25 +338,117 @@ struct RtpEncodingParameters { }; struct RtpCodecParameters { - int payload_type; - std::string mime_type; - int clock_rate; - int channels = 1; - // TODO(deadbeef): Add sdpFmtpLine field. + // Build MIME "type/subtype" string from |name| and |kind|. + std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; } + + // Used to identify the codec. Equivalent to MIME subtype. + std::string name; + + // The media type of this codec. Equivalent to MIME top-level type. + cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO; + + // Payload type used to identify this codec in RTP packets. + // This must always be present, and must be unique across all codecs using + // the same transport. + int payload_type = 0; + + // If unset, the implementation default is used. + rtc::Optional clock_rate; + + // The number of audio channels used. Unset for video codecs. If unset for + // audio, the implementation default is used. + // TODO(deadbeef): The "implementation default" part isn't fully implemented. + // Only defaults to 1, even though some codecs (such as opus) should really + // default to 2. + rtc::Optional num_channels; + + // The maximum packetization time to be used by an RtpSender. + // If |ptime| is also set, this will be ignored. + // TODO(deadbeef): Not implemented. + rtc::Optional max_ptime; + + // The packetization time to be used by an RtpSender. + // If unset, will use any time up to max_ptime. + // TODO(deadbeef): Not implemented. + rtc::Optional ptime; + + // Feedback mechanisms to be used for this codec. + // TODO(deadbeef): Not implemented with PeerConnection senders/receivers. + std::vector rtcp_feedback; + + // Codec-specific parameters that must be signaled to the remote party. + // + // Corresponds to "a=fmtp" parameters in SDP. + // + // Contrary to ORTC, these parameters are named using all lowercase strings. + // This helps make the mapping to SDP simpler, if an application is using + // SDP. Boolean values are represented by the string "1". + // + // TODO(deadbeef): Not implemented with PeerConnection senders/receivers. + std::unordered_map parameters; bool operator==(const RtpCodecParameters& o) const { - return payload_type == o.payload_type && mime_type == o.mime_type && - clock_rate == o.clock_rate && channels == o.channels; + return name == o.name && kind == o.kind && payload_type == o.payload_type && + clock_rate == o.clock_rate && num_channels == o.num_channels && + max_ptime == o.max_ptime && ptime == o.ptime && + rtcp_feedback == o.rtcp_feedback && parameters == o.parameters; } bool operator!=(const RtpCodecParameters& o) const { return !(*this == o); } }; +// RtpCapabilities is used to represent the static capabilities of an +// endpoint. An application can use these capabilities to construct an +// RtpParameters. +struct RtpCapabilities { + // Supported codecs. + std::vector codecs; + + // Supported RTP header extensions. + std::vector header_extensions; + + // Supported Forward Error Correction (FEC) mechanisms. Note that the RED, + // ulpfec and flexfec codecs used by these mechanisms will still appear in + // |codecs|. + std::vector fec; + + bool operator==(const RtpCapabilities& o) const { + return codecs == o.codecs && header_extensions == o.header_extensions && + fec == o.fec; + } + bool operator!=(const RtpCapabilities& o) const { return !(*this == o); } +}; + +// Note that unlike in ORTC, an RtcpParameters structure is not included in +// RtpParameters, because our API includes an additional "RtpTransport" +// abstraction on which RTCP parameters are set. struct RtpParameters { - std::vector encodings; + // Used when calling getParameters/setParameters with a PeerConnection + // RtpSender, to ensure that outdated parameters are not unintentionally + // applied successfully. + // TODO(deadbeef): Not implemented. + std::string transaction_id; + + // Value to use for MID RTP header extension. + // Called "muxId" in ORTC. + // TODO(deadbeef): Not implemented. + std::string mid; + std::vector codecs; + // TODO(deadbeef): Not implemented with PeerConnection senders/receivers. + std::vector header_extensions; + + std::vector encodings; + + // TODO(deadbeef): Not implemented. + DegradationPreference degradation_preference = + DegradationPreference::BALANCED; + bool operator==(const RtpParameters& o) const { - return encodings == o.encodings && codecs == o.codecs; + return mid == o.mid && codecs == o.codecs && + header_extensions == o.header_extensions && + encodings == o.encodings && + degradation_preference == o.degradation_preference; } bool operator!=(const RtpParameters& o) const { return !(*this == o); } }; diff --git a/include/webrtc/api/rtpreceiverinterface.h b/include/webrtc/api/rtpreceiverinterface.h index ef4f0e1..8607d93 100644 --- a/include/webrtc/api/rtpreceiverinterface.h +++ b/include/webrtc/api/rtpreceiverinterface.h @@ -16,41 +16,67 @@ #include +#include "webrtc/api/mediatypes.h" #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/proxy.h" +#include "webrtc/api/rtpparameters.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" namespace webrtc { +class RtpReceiverObserverInterface { + public: + // Note: Currently if there are multiple RtpReceivers of the same media type, + // they will all call OnFirstPacketReceived at once. + // + // In the future, it's likely that an RtpReceiver will only call + // OnFirstPacketReceived when a packet is received specifically for its + // SSRC/mid. + virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0; + + protected: + virtual ~RtpReceiverObserverInterface() {} +}; + class RtpReceiverInterface : public rtc::RefCountInterface { public: virtual rtc::scoped_refptr track() const = 0; + // Audio or video receiver? + virtual cricket::MediaType media_type() const = 0; + // Not to be confused with "mid", this is a field we can temporarily use // to uniquely identify a receiver until we implement Unified Plan SDP. virtual std::string id() const = 0; - virtual void Stop() = 0; - // The WebRTC specification only defines RTCRtpParameters in terms of senders, // but this API also applies them to receivers, similar to ORTC: // http://ortc.org/wp-content/uploads/2016/03/ortc.html#rtcrtpparameters*. virtual RtpParameters GetParameters() const = 0; + // Currently, doesn't support changing any parameters, but may in the future. virtual bool SetParameters(const RtpParameters& parameters) = 0; + // Does not take ownership of observer. + // Must call SetObserver(nullptr) before the observer is destroyed. + virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0; + protected: virtual ~RtpReceiverInterface() {} }; // Define proxy for RtpReceiverInterface. +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_SIGNALING_PROXY_MAP(RtpReceiver) -PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) -PROXY_CONSTMETHOD0(std::string, id) -PROXY_METHOD0(void, Stop) -PROXY_CONSTMETHOD0(RtpParameters, GetParameters); -PROXY_METHOD1(bool, SetParameters, const RtpParameters&) -END_SIGNALING_PROXY() + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) + PROXY_CONSTMETHOD0(cricket::MediaType, media_type) + PROXY_CONSTMETHOD0(std::string, id) + PROXY_CONSTMETHOD0(RtpParameters, GetParameters); + PROXY_METHOD1(bool, SetParameters, const RtpParameters&) + PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*); +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/rtpsender.h b/include/webrtc/api/rtpsender.h index ffe5dae..3b7faec 100644 --- a/include/webrtc/api/rtpsender.h +++ b/include/webrtc/api/rtpsender.h @@ -8,179 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -// This file contains classes that implement RtpSenderInterface. -// An RtpSender associates a MediaStreamTrackInterface with an underlying -// transport (provided by AudioProviderInterface/VideoProviderInterface) - #ifndef WEBRTC_API_RTPSENDER_H_ #define WEBRTC_API_RTPSENDER_H_ -#include -#include - -#include "webrtc/api/mediastreamprovider.h" -#include "webrtc/api/rtpsenderinterface.h" -#include "webrtc/api/statscollector.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/media/base/audiosource.h" - -namespace webrtc { - -// LocalAudioSinkAdapter receives data callback as a sink to the local -// AudioTrack, and passes the data to the sink of AudioSource. -class LocalAudioSinkAdapter : public AudioTrackSinkInterface, - public cricket::AudioSource { - public: - LocalAudioSinkAdapter(); - virtual ~LocalAudioSinkAdapter(); - - private: - // AudioSinkInterface implementation. - void OnData(const void* audio_data, - int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames) override; - - // cricket::AudioSource implementation. - void SetSink(cricket::AudioSource::Sink* sink) override; - - cricket::AudioSource::Sink* sink_; - // Critical section protecting |sink_|. - rtc::CriticalSection lock_; -}; - -class AudioRtpSender : public ObserverInterface, - public rtc::RefCountedObject { - public: - // StatsCollector provided so that Add/RemoveLocalAudioTrack can be called - // at the appropriate times. - AudioRtpSender(AudioTrackInterface* track, - const std::string& stream_id, - AudioProviderInterface* provider, - StatsCollector* stats); - - // Randomly generates stream_id. - AudioRtpSender(AudioTrackInterface* track, - AudioProviderInterface* provider, - StatsCollector* stats); - - // Randomly generates id and stream_id. - AudioRtpSender(AudioProviderInterface* provider, StatsCollector* stats); - - virtual ~AudioRtpSender(); - - // ObserverInterface implementation - void OnChanged() override; - - // RtpSenderInterface implementation - bool SetTrack(MediaStreamTrackInterface* track) override; - rtc::scoped_refptr track() const override { - return track_.get(); - } - - void SetSsrc(uint32_t ssrc) override; - - uint32_t ssrc() const override { return ssrc_; } - - cricket::MediaType media_type() const override { - return cricket::MEDIA_TYPE_AUDIO; - } - - std::string id() const override { return id_; } - - void set_stream_id(const std::string& stream_id) override { - stream_id_ = stream_id; - } - std::string stream_id() const override { return stream_id_; } - - void Stop() override; - - RtpParameters GetParameters() const override; - bool SetParameters(const RtpParameters& parameters) override; - - private: - // TODO(nisse): Since SSRC == 0 is technically valid, figure out - // some other way to test if we have a valid SSRC. - bool can_send_track() const { return track_ && ssrc_; } - // Helper function to construct options for - // AudioProviderInterface::SetAudioSend. - void SetAudioSend(); - - std::string id_; - std::string stream_id_; - AudioProviderInterface* provider_; - StatsCollector* stats_; - rtc::scoped_refptr track_; - uint32_t ssrc_ = 0; - bool cached_track_enabled_ = false; - bool stopped_ = false; - - // Used to pass the data callback from the |track_| to the other end of - // cricket::AudioSource. - std::unique_ptr sink_adapter_; -}; - -class VideoRtpSender : public ObserverInterface, - public rtc::RefCountedObject { - public: - VideoRtpSender(VideoTrackInterface* track, - const std::string& stream_id, - VideoProviderInterface* provider); - - // Randomly generates stream_id. - VideoRtpSender(VideoTrackInterface* track, VideoProviderInterface* provider); - - // Randomly generates id and stream_id. - explicit VideoRtpSender(VideoProviderInterface* provider); - - virtual ~VideoRtpSender(); - - // ObserverInterface implementation - void OnChanged() override; - - // RtpSenderInterface implementation - bool SetTrack(MediaStreamTrackInterface* track) override; - rtc::scoped_refptr track() const override { - return track_.get(); - } - - void SetSsrc(uint32_t ssrc) override; - - uint32_t ssrc() const override { return ssrc_; } - - cricket::MediaType media_type() const override { - return cricket::MEDIA_TYPE_VIDEO; - } - - std::string id() const override { return id_; } - - void set_stream_id(const std::string& stream_id) override { - stream_id_ = stream_id; - } - std::string stream_id() const override { return stream_id_; } - - void Stop() override; - - RtpParameters GetParameters() const override; - bool SetParameters(const RtpParameters& parameters) override; - - private: - bool can_send_track() const { return track_ && ssrc_; } - // Helper function to construct options for - // VideoProviderInterface::SetVideoSend. - void SetVideoSend(); - - std::string id_; - std::string stream_id_; - VideoProviderInterface* provider_; - rtc::scoped_refptr track_; - uint32_t ssrc_ = 0; - bool cached_track_enabled_ = false; - bool stopped_ = false; -}; - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/rtpsender.h" #endif // WEBRTC_API_RTPSENDER_H_ diff --git a/include/webrtc/api/rtpsenderinterface.h b/include/webrtc/api/rtpsenderinterface.h index 2291bb4..f2b6766 100644 --- a/include/webrtc/api/rtpsenderinterface.h +++ b/include/webrtc/api/rtpsenderinterface.h @@ -15,13 +15,15 @@ #define WEBRTC_API_RTPSENDERINTERFACE_H_ #include +#include +#include "webrtc/api/dtmfsenderinterface.h" +#include "webrtc/api/mediatypes.h" #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/proxy.h" #include "webrtc/api/rtpparameters.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/pc/mediasession.h" namespace webrtc { @@ -32,11 +34,10 @@ class RtpSenderInterface : public rtc::RefCountInterface { virtual bool SetTrack(MediaStreamTrackInterface* track) = 0; virtual rtc::scoped_refptr track() const = 0; - // Used to set the SSRC of the sender, once a local description has been set. - // If |ssrc| is 0, this indiates that the sender should disconnect from the - // underlying transport (this occurs if the sender isn't seen in a local - // description). - virtual void SetSsrc(uint32_t ssrc) = 0; + // Returns primary SSRC used by this sender for sending media. + // Returns 0 if not yet determined. + // TODO(deadbeef): Change to rtc::Optional. + // TODO(deadbeef): Remove? With GetParameters this should be redundant. virtual uint32_t ssrc() const = 0; // Audio or video sender? @@ -46,33 +47,37 @@ class RtpSenderInterface : public rtc::RefCountInterface { // to uniquely identify a receiver until we implement Unified Plan SDP. virtual std::string id() const = 0; - // TODO(deadbeef): Support one sender having multiple stream ids. - virtual void set_stream_id(const std::string& stream_id) = 0; - virtual std::string stream_id() const = 0; - - virtual void Stop() = 0; + // Returns a list of streams associated with this sender's track. Although we + // only support one track per stream, in theory the API allows for multiple. + virtual std::vector stream_ids() const = 0; virtual RtpParameters GetParameters() const = 0; + // Note that only a subset of the parameters can currently be changed. See + // rtpparameters.h virtual bool SetParameters(const RtpParameters& parameters) = 0; + // Returns null for a video sender. + virtual rtc::scoped_refptr GetDtmfSender() const = 0; + protected: virtual ~RtpSenderInterface() {} }; // Define proxy for RtpSenderInterface. +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_SIGNALING_PROXY_MAP(RtpSender) -PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*) -PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) -PROXY_METHOD1(void, SetSsrc, uint32_t) -PROXY_CONSTMETHOD0(uint32_t, ssrc) -PROXY_CONSTMETHOD0(cricket::MediaType, media_type) -PROXY_CONSTMETHOD0(std::string, id) -PROXY_METHOD1(void, set_stream_id, const std::string&) -PROXY_CONSTMETHOD0(std::string, stream_id) -PROXY_METHOD0(void, Stop) -PROXY_CONSTMETHOD0(RtpParameters, GetParameters); -PROXY_METHOD1(bool, SetParameters, const RtpParameters&) -END_SIGNALING_PROXY() + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*) + PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) + PROXY_CONSTMETHOD0(uint32_t, ssrc) + PROXY_CONSTMETHOD0(cricket::MediaType, media_type) + PROXY_CONSTMETHOD0(std::string, id) + PROXY_CONSTMETHOD0(std::vector, stream_ids) + PROXY_CONSTMETHOD0(RtpParameters, GetParameters); + PROXY_METHOD1(bool, SetParameters, const RtpParameters&) + PROXY_CONSTMETHOD0(rtc::scoped_refptr, GetDtmfSender); +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/stats/rtcstats.h b/include/webrtc/api/stats/rtcstats.h new file mode 100644 index 0000000..b3afee0 --- /dev/null +++ b/include/webrtc/api/stats/rtcstats.h @@ -0,0 +1,325 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_STATS_RTCSTATS_H_ +#define WEBRTC_API_STATS_RTCSTATS_H_ + +#include +#include +#include +#include +#include + +#include "webrtc/base/checks.h" + +namespace webrtc { + +class RTCStatsMemberInterface; + +// Abstract base class for RTCStats-derived dictionaries, see +// https://w3c.github.io/webrtc-stats/. +// +// All derived classes must have the following static variable defined: +// static const char kType[]; +// It is used as a unique class identifier and a string representation of the +// class type, see https://w3c.github.io/webrtc-stats/#rtcstatstype-str*. +// Use the |WEBRTC_RTCSTATS_IMPL| macro when implementing subclasses, see macro +// for details. +// +// Derived classes list their dictionary members, RTCStatsMember, as public +// fields, allowing the following: +// +// RTCFooStats foo("fooId", GetCurrentTime()); +// foo.bar = 42; +// foo.baz = std::vector(); +// foo.baz->push_back("hello world"); +// uint32_t x = *foo.bar; +// +// Pointers to all the members are available with |Members|, allowing iteration: +// +// for (const RTCStatsMemberInterface* member : foo.Members()) { +// printf("%s = %s\n", member->name(), member->ValueToString().c_str()); +// } +class RTCStats { + public: + RTCStats(const std::string& id, int64_t timestamp_us) + : id_(id), timestamp_us_(timestamp_us) {} + RTCStats(std::string&& id, int64_t timestamp_us) + : id_(std::move(id)), timestamp_us_(timestamp_us) {} + virtual ~RTCStats() {} + + virtual std::unique_ptr copy() const = 0; + + const std::string& id() const { return id_; } + // Time relative to the UNIX epoch (Jan 1, 1970, UTC), in microseconds. + int64_t timestamp_us() const { return timestamp_us_; } + // Returns the static member variable |kType| of the implementing class. + virtual const char* type() const = 0; + // Returns a vector of pointers to all the |RTCStatsMemberInterface| members + // of this class. This allows for iteration of members. For a given class, + // |Members| always returns the same members in the same order. + std::vector Members() const; + // Checks if the two stats objects are of the same type and have the same + // member values. Timestamps are not compared. These operators are exposed for + // testing. + bool operator==(const RTCStats& other) const; + bool operator!=(const RTCStats& other) const; + + // Creates a human readable string representation of the stats object, listing + // all of its members (names and values). + std::string ToString() const; + + // Downcasts the stats object to an |RTCStats| subclass |T|. DCHECKs that the + // object is of type |T|. + template + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::kType); + return static_cast(*this); + } + + protected: + // Gets a vector of all members of this |RTCStats| object, including members + // derived from parent classes. |additional_capacity| is how many more members + // shall be reserved in the vector (so that subclasses can allocate a vector + // with room for both parent and child members without it having to resize). + virtual std::vector + MembersOfThisObjectAndAncestors( + size_t additional_capacity) const; + + std::string const id_; + int64_t timestamp_us_; +}; + +// All |RTCStats| classes should use these macros. +// |WEBRTC_RTCSTATS_DECL| is placed in a public section of the class definition. +// |WEBRTC_RTCSTATS_IMPL| is placed outside the class definition (in a .cc). +// +// These macros declare (in _DECL) and define (in _IMPL) the static |kType| and +// overrides methods as required by subclasses of |RTCStats|: |copy|, |type| and +// |MembersOfThisObjectAndAncestors|. The |...| argument is a list of addresses +// to each member defined in the implementing class. The list must have at least +// one member. +// +// (Since class names need to be known to implement these methods this cannot be +// part of the base |RTCStats|. While these methods could be implemented using +// templates, that would only work for immediate subclasses. Subclasses of +// subclasses also have to override these methods, resulting in boilerplate +// code. Using a macro avoids this and works for any |RTCStats| class, including +// grandchildren.) +// +// Sample usage: +// +// rtcfoostats.h: +// class RTCFooStats : public RTCStats { +// public: +// WEBRTC_RTCSTATS_DECL(); +// +// RTCFooStats(const std::string& id, int64_t timestamp_us); +// +// RTCStatsMember foo; +// RTCStatsMember bar; +// }; +// +// rtcfoostats.cc: +// WEBRTC_RTCSTATS_IMPL(RTCFooStats, RTCStats, "foo-stats" +// &foo, +// &bar); +// +// RTCFooStats::RTCFooStats(const std::string& id, int64_t timestamp_us) +// : RTCStats(id, timestamp_us), +// foo("foo"), +// bar("bar") { +// } +// +#define WEBRTC_RTCSTATS_DECL() \ + public: \ + static const char kType[]; \ + \ + std::unique_ptr copy() const override; \ + const char* type() const override; \ + \ + protected: \ + std::vector \ + MembersOfThisObjectAndAncestors( \ + size_t local_var_additional_capacity) const override; \ + \ + public: + +#define WEBRTC_RTCSTATS_IMPL(this_class, parent_class, type_str, ...) \ + const char this_class::kType[] = type_str; \ + \ + std::unique_ptr this_class::copy() const { \ + return std::unique_ptr(new this_class(*this)); \ + } \ + \ + const char* this_class::type() const { \ + return this_class::kType; \ + } \ + \ + std::vector \ + this_class::MembersOfThisObjectAndAncestors( \ + size_t local_var_additional_capacity) const { \ + const webrtc::RTCStatsMemberInterface* local_var_members[] = { \ + __VA_ARGS__ \ + }; \ + size_t local_var_members_count = \ + sizeof(local_var_members) / sizeof(local_var_members[0]); \ + std::vector local_var_members_vec =\ + parent_class::MembersOfThisObjectAndAncestors( \ + local_var_members_count + local_var_additional_capacity); \ + RTC_DCHECK_GE( \ + local_var_members_vec.capacity() - local_var_members_vec.size(), \ + local_var_members_count + local_var_additional_capacity); \ + local_var_members_vec.insert(local_var_members_vec.end(), \ + &local_var_members[0], \ + &local_var_members[local_var_members_count]); \ + return local_var_members_vec; \ + } + +// Interface for |RTCStats| members, which have a name and a value of a type +// defined in a subclass. Only the types listed in |Type| are supported, these +// are implemented by |RTCStatsMember|. The value of a member may be +// undefined, the value can only be read if |is_defined|. +class RTCStatsMemberInterface { + public: + // Member value types. + enum Type { + kBool, // bool + kInt32, // int32_t + kUint32, // uint32_t + kInt64, // int64_t + kUint64, // uint64_t + kDouble, // double + kString, // std::string + + kSequenceBool, // std::vector + kSequenceInt32, // std::vector + kSequenceUint32, // std::vector + kSequenceInt64, // std::vector + kSequenceUint64, // std::vector + kSequenceDouble, // std::vector + kSequenceString, // std::vector + }; + + virtual ~RTCStatsMemberInterface() {} + + const char* name() const { return name_; } + virtual Type type() const = 0; + virtual bool is_sequence() const = 0; + virtual bool is_string() const = 0; + bool is_defined() const { return is_defined_; } + // Type and value comparator. The names are not compared. These operators are + // exposed for testing. + virtual bool operator==(const RTCStatsMemberInterface& other) const = 0; + bool operator!=(const RTCStatsMemberInterface& other) const { + return !(*this == other); + } + virtual std::string ValueToString() const = 0; + + template + const T& cast_to() const { + RTC_DCHECK_EQ(type(), T::kType); + return static_cast(*this); + } + + protected: + RTCStatsMemberInterface(const char* name, bool is_defined) + : name_(name), is_defined_(is_defined) {} + + const char* const name_; + bool is_defined_; +}; + +// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is +// specialized in rtcstats.cc, using a different |T| results in a linker error +// (undefined reference to |kType|). The supported types are the ones described +// by |RTCStatsMemberInterface::Type|. +template +class RTCStatsMember : public RTCStatsMemberInterface { + public: + static const Type kType; + + explicit RTCStatsMember(const char* name) + : RTCStatsMemberInterface(name, false), + value_() {} + RTCStatsMember(const char* name, const T& value) + : RTCStatsMemberInterface(name, true), + value_(value) {} + RTCStatsMember(const char* name, T&& value) + : RTCStatsMemberInterface(name, true), + value_(std::move(value)) {} + explicit RTCStatsMember(const RTCStatsMember& other) + : RTCStatsMemberInterface(other.name_, other.is_defined_), + value_(other.value_) {} + explicit RTCStatsMember(RTCStatsMember&& other) + : RTCStatsMemberInterface(other.name_, other.is_defined_), + value_(std::move(other.value_)) {} + + Type type() const override { return kType; } + bool is_sequence() const override; + bool is_string() const override; + bool operator==(const RTCStatsMemberInterface& other) const override { + if (type() != other.type()) + return false; + const RTCStatsMember& other_t = + static_cast&>(other); + if (!is_defined_) + return !other_t.is_defined(); + if (!other.is_defined()) + return false; + return value_ == other_t.value_; + } + std::string ValueToString() const override; + + // Assignment operators. + T& operator=(const T& value) { + value_ = value; + is_defined_ = true; + return value_; + } + T& operator=(const T&& value) { + value_ = std::move(value); + is_defined_ = true; + return value_; + } + T& operator=(const RTCStatsMember& other) { + RTC_DCHECK(other.is_defined_); + value_ = other.is_defined_; + is_defined_ = true; + return value_; + } + + // Value getters. + T& operator*() { + RTC_DCHECK(is_defined_); + return value_; + } + const T& operator*() const { + RTC_DCHECK(is_defined_); + return value_; + } + + // Value getters, arrow operator. + T* operator->() { + RTC_DCHECK(is_defined_); + return &value_; + } + const T* operator->() const { + RTC_DCHECK(is_defined_); + return &value_; + } + + private: + T value_; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_STATS_RTCSTATS_H_ diff --git a/include/webrtc/api/stats/rtcstats_objects.h b/include/webrtc/api/stats/rtcstats_objects.h new file mode 100644 index 0000000..49135f8 --- /dev/null +++ b/include/webrtc/api/stats/rtcstats_objects.h @@ -0,0 +1,414 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_ +#define WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_ + +#include +#include + +#include "webrtc/api/stats/rtcstats.h" + +namespace webrtc { + +// https://w3c.github.io/webrtc-pc/#idl-def-rtcdatachannelstate +struct RTCDataChannelState { + static const char* kConnecting; + static const char* kOpen; + static const char* kClosing; + static const char* kClosed; +}; + +// https://w3c.github.io/webrtc-stats/#dom-rtcstatsicecandidatepairstate +struct RTCStatsIceCandidatePairState { + static const char* kFrozen; + static const char* kWaiting; + static const char* kInProgress; + static const char* kFailed; + static const char* kSucceeded; +}; + +// https://w3c.github.io/webrtc-pc/#rtcicecandidatetype-enum +struct RTCIceCandidateType { + static const char* kHost; + static const char* kSrflx; + static const char* kPrflx; + static const char* kRelay; +}; + +// https://w3c.github.io/webrtc-pc/#idl-def-rtcdtlstransportstate +struct RTCDtlsTransportState { + static const char* kNew; + static const char* kConnecting; + static const char* kConnected; + static const char* kClosed; + static const char* kFailed; +}; + +// |RTCMediaStreamTrackStats::kind| is not an enum in the spec but the only +// valid values are "audio" and "video". +// https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-kind +struct RTCMediaStreamTrackKind { + static const char* kAudio; + static const char* kVideo; +}; + +// https://w3c.github.io/webrtc-stats/#certificatestats-dict* +class RTCCertificateStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCCertificateStats(const std::string& id, int64_t timestamp_us); + RTCCertificateStats(std::string&& id, int64_t timestamp_us); + RTCCertificateStats(const RTCCertificateStats& other); + ~RTCCertificateStats() override; + + RTCStatsMember fingerprint; + RTCStatsMember fingerprint_algorithm; + RTCStatsMember base64_certificate; + RTCStatsMember issuer_certificate_id; +}; + +// https://w3c.github.io/webrtc-stats/#codec-dict* +class RTCCodecStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCCodecStats(const std::string& id, int64_t timestamp_us); + RTCCodecStats(std::string&& id, int64_t timestamp_us); + RTCCodecStats(const RTCCodecStats& other); + ~RTCCodecStats() override; + + RTCStatsMember payload_type; + RTCStatsMember mime_type; + RTCStatsMember clock_rate; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7061 + RTCStatsMember channels; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7061 + RTCStatsMember sdp_fmtp_line; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7061 + RTCStatsMember implementation; +}; + +// https://w3c.github.io/webrtc-stats/#dcstats-dict* +class RTCDataChannelStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCDataChannelStats(const std::string& id, int64_t timestamp_us); + RTCDataChannelStats(std::string&& id, int64_t timestamp_us); + RTCDataChannelStats(const RTCDataChannelStats& other); + ~RTCDataChannelStats() override; + + RTCStatsMember label; + RTCStatsMember protocol; + RTCStatsMember datachannelid; + // TODO(hbos): Support enum types? "RTCStatsMember"? + RTCStatsMember state; + RTCStatsMember messages_sent; + RTCStatsMember bytes_sent; + RTCStatsMember messages_received; + RTCStatsMember bytes_received; +}; + +// https://w3c.github.io/webrtc-stats/#candidatepair-dict* +// TODO(hbos): Tracking bug https://bugs.webrtc.org/7062 +class RTCIceCandidatePairStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCIceCandidatePairStats(const std::string& id, int64_t timestamp_us); + RTCIceCandidatePairStats(std::string&& id, int64_t timestamp_us); + RTCIceCandidatePairStats(const RTCIceCandidatePairStats& other); + ~RTCIceCandidatePairStats() override; + + RTCStatsMember transport_id; + RTCStatsMember local_candidate_id; + RTCStatsMember remote_candidate_id; + // TODO(hbos): Support enum types? + // "RTCStatsMember"? + RTCStatsMember state; + RTCStatsMember priority; + RTCStatsMember nominated; + // TODO(hbos): Collect this the way the spec describes it. We have a value for + // it but it is not spec-compliant. https://bugs.webrtc.org/7062 + RTCStatsMember writable; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember readable; + RTCStatsMember bytes_sent; + RTCStatsMember bytes_received; + RTCStatsMember total_round_trip_time; + RTCStatsMember current_round_trip_time; + RTCStatsMember available_outgoing_bitrate; + // TODO(hbos): Populate this value. It is wired up and collected the same way + // "VideoBwe.googAvailableReceiveBandwidth" is, but that value is always + // undefined. https://bugs.webrtc.org/7062 + RTCStatsMember available_incoming_bitrate; + RTCStatsMember requests_received; + RTCStatsMember requests_sent; + RTCStatsMember responses_received; + RTCStatsMember responses_sent; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember retransmissions_received; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember retransmissions_sent; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember consent_requests_received; + RTCStatsMember consent_requests_sent; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember consent_responses_received; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 + RTCStatsMember consent_responses_sent; +}; + +// https://w3c.github.io/webrtc-stats/#icecandidate-dict* +// TODO(hbos): |RTCStatsCollector| only collects candidates that are part of +// ice candidate pairs, but there could be candidates not paired with anything. +// crbug.com/632723 +class RTCIceCandidateStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCIceCandidateStats(const RTCIceCandidateStats& other); + ~RTCIceCandidateStats() override; + + RTCStatsMember transport_id; + RTCStatsMember is_remote; + RTCStatsMember ip; + RTCStatsMember port; + RTCStatsMember protocol; + // TODO(hbos): Support enum types? "RTCStatsMember"? + RTCStatsMember candidate_type; + RTCStatsMember priority; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/632723 + RTCStatsMember url; + // TODO(hbos): |deleted = true| case is not supported by |RTCStatsCollector|. + // crbug.com/632723 + RTCStatsMember deleted; // = false + + protected: + RTCIceCandidateStats( + const std::string& id, int64_t timestamp_us, bool is_remote); + RTCIceCandidateStats(std::string&& id, int64_t timestamp_us, bool is_remote); +}; + +// In the spec both local and remote varieties are of type RTCIceCandidateStats. +// But here we define them as subclasses of |RTCIceCandidateStats| because the +// |kType| need to be different ("RTCStatsType type") in the local/remote case. +// https://w3c.github.io/webrtc-stats/#rtcstatstype-str* +class RTCLocalIceCandidateStats final : public RTCIceCandidateStats { + public: + static const char kType[]; + RTCLocalIceCandidateStats(const std::string& id, int64_t timestamp_us); + RTCLocalIceCandidateStats(std::string&& id, int64_t timestamp_us); + const char* type() const override; +}; + +class RTCRemoteIceCandidateStats final : public RTCIceCandidateStats { + public: + static const char kType[]; + RTCRemoteIceCandidateStats(const std::string& id, int64_t timestamp_us); + RTCRemoteIceCandidateStats(std::string&& id, int64_t timestamp_us); + const char* type() const override; +}; + +// https://w3c.github.io/webrtc-stats/#msstats-dict* +// TODO(hbos): Tracking bug crbug.com/660827 +class RTCMediaStreamStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCMediaStreamStats(const std::string& id, int64_t timestamp_us); + RTCMediaStreamStats(std::string&& id, int64_t timestamp_us); + RTCMediaStreamStats(const RTCMediaStreamStats& other); + ~RTCMediaStreamStats() override; + + RTCStatsMember stream_identifier; + RTCStatsMember> track_ids; +}; + +// https://w3c.github.io/webrtc-stats/#mststats-dict* +// TODO(hbos): Tracking bug crbug.com/659137 +class RTCMediaStreamTrackStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCMediaStreamTrackStats(const std::string& id, int64_t timestamp_us, + const char* kind); + RTCMediaStreamTrackStats(std::string&& id, int64_t timestamp_us, + const char* kind); + RTCMediaStreamTrackStats(const RTCMediaStreamTrackStats& other); + ~RTCMediaStreamTrackStats() override; + + RTCStatsMember track_identifier; + RTCStatsMember remote_source; + RTCStatsMember ended; + // TODO(hbos): |RTCStatsCollector| does not return stats for detached tracks. + // crbug.com/659137 + RTCStatsMember detached; + // See |RTCMediaStreamTrackKind| for valid values. + RTCStatsMember kind; + // Video-only members + RTCStatsMember frame_width; + RTCStatsMember frame_height; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_per_second; + RTCStatsMember frames_sent; + RTCStatsMember frames_received; + RTCStatsMember frames_decoded; + RTCStatsMember frames_dropped; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember frames_corrupted; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember partial_frames_lost; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/659137 + RTCStatsMember full_frames_lost; + // Audio-only members + RTCStatsMember audio_level; + RTCStatsMember echo_return_loss; + RTCStatsMember echo_return_loss_enhancement; +}; + +// https://w3c.github.io/webrtc-stats/#pcstats-dict* +class RTCPeerConnectionStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCPeerConnectionStats(const std::string& id, int64_t timestamp_us); + RTCPeerConnectionStats(std::string&& id, int64_t timestamp_us); + RTCPeerConnectionStats(const RTCPeerConnectionStats& other); + ~RTCPeerConnectionStats() override; + + RTCStatsMember data_channels_opened; + RTCStatsMember data_channels_closed; +}; + +// https://w3c.github.io/webrtc-stats/#streamstats-dict* +// TODO(hbos): Tracking bug crbug.com/657854 +class RTCRTPStreamStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCRTPStreamStats(const RTCRTPStreamStats& other); + ~RTCRTPStreamStats() override; + + RTCStatsMember ssrc; + // TODO(hbos): When the remote case is supported |RTCStatsCollector| needs to + // set this. crbug.com/657855, 657856 + RTCStatsMember associate_stats_id; + // TODO(hbos): Remote case not supported by |RTCStatsCollector|. + // crbug.com/657855, 657856 + RTCStatsMember is_remote; // = false + RTCStatsMember media_type; + RTCStatsMember track_id; + RTCStatsMember transport_id; + RTCStatsMember codec_id; + // FIR and PLI counts are only defined for |media_type == "video"|. + RTCStatsMember fir_count; + RTCStatsMember pli_count; + // TODO(hbos): NACK count should be collected by |RTCStatsCollector| for both + // audio and video but is only defined in the "video" case. crbug.com/657856 + RTCStatsMember nack_count; + // TODO(hbos): Not collected by |RTCStatsCollector|. crbug.com/657854 + // SLI count is only defined for |media_type == "video"|. + RTCStatsMember sli_count; + RTCStatsMember qp_sum; + + protected: + RTCRTPStreamStats(const std::string& id, int64_t timestamp_us); + RTCRTPStreamStats(std::string&& id, int64_t timestamp_us); +}; + +// https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict* +// TODO(hbos): Support the remote case |is_remote = true|. +// https://bugs.webrtc.org/7065 +class RTCInboundRTPStreamStats final : public RTCRTPStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCInboundRTPStreamStats(const std::string& id, int64_t timestamp_us); + RTCInboundRTPStreamStats(std::string&& id, int64_t timestamp_us); + RTCInboundRTPStreamStats(const RTCInboundRTPStreamStats& other); + ~RTCInboundRTPStreamStats() override; + + RTCStatsMember packets_received; + RTCStatsMember bytes_received; + RTCStatsMember packets_lost; + // TODO(hbos): Collect and populate this value for both "audio" and "video", + // currently not collected for "video". https://bugs.webrtc.org/7065 + RTCStatsMember jitter; + RTCStatsMember fraction_lost; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember round_trip_time; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember packets_discarded; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember packets_repaired; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_packets_lost; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_packets_discarded; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_loss_count; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_discard_count; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_loss_rate; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember burst_discard_rate; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember gap_loss_rate; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7065 + RTCStatsMember gap_discard_rate; + RTCStatsMember frames_decoded; +}; + +// https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict* +// TODO(hbos): Support the remote case |is_remote = true|. +// https://bugs.webrtc.org/7066 +class RTCOutboundRTPStreamStats final : public RTCRTPStreamStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCOutboundRTPStreamStats(const std::string& id, int64_t timestamp_us); + RTCOutboundRTPStreamStats(std::string&& id, int64_t timestamp_us); + RTCOutboundRTPStreamStats(const RTCOutboundRTPStreamStats& other); + ~RTCOutboundRTPStreamStats() override; + + RTCStatsMember packets_sent; + RTCStatsMember bytes_sent; + // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7066 + RTCStatsMember target_bitrate; + RTCStatsMember frames_encoded; +}; + +// https://w3c.github.io/webrtc-stats/#transportstats-dict* +class RTCTransportStats final : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCTransportStats(const std::string& id, int64_t timestamp_us); + RTCTransportStats(std::string&& id, int64_t timestamp_us); + RTCTransportStats(const RTCTransportStats& other); + ~RTCTransportStats() override; + + RTCStatsMember bytes_sent; + RTCStatsMember bytes_received; + RTCStatsMember rtcp_transport_stats_id; + // TODO(hbos): Support enum types? "RTCStatsMember"? + RTCStatsMember dtls_state; + RTCStatsMember selected_candidate_pair_id; + RTCStatsMember local_certificate_id; + RTCStatsMember remote_certificate_id; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_STATS_RTCSTATS_OBJECTS_H_ diff --git a/include/webrtc/api/stats/rtcstatscollectorcallback.h b/include/webrtc/api/stats/rtcstatscollectorcallback.h new file mode 100644 index 0000000..2493e49 --- /dev/null +++ b/include/webrtc/api/stats/rtcstatscollectorcallback.h @@ -0,0 +1,30 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_STATS_RTCSTATSCOLLECTORCALLBACK_H_ +#define WEBRTC_API_STATS_RTCSTATSCOLLECTORCALLBACK_H_ + +#include "webrtc/api/stats/rtcstatsreport.h" +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" + +namespace webrtc { + +class RTCStatsCollectorCallback : public virtual rtc::RefCountInterface { + public: + virtual ~RTCStatsCollectorCallback() {} + + virtual void OnStatsDelivered( + const rtc::scoped_refptr& report) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_STATS_RTCSTATSCOLLECTORCALLBACK_H_ diff --git a/include/webrtc/api/stats/rtcstatsreport.h b/include/webrtc/api/stats/rtcstatsreport.h new file mode 100644 index 0000000..6d9ae6d --- /dev/null +++ b/include/webrtc/api/stats/rtcstatsreport.h @@ -0,0 +1,99 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_STATS_RTCSTATSREPORT_H_ +#define WEBRTC_API_STATS_RTCSTATSREPORT_H_ + +#include +#include +#include +#include + +#include "webrtc/api/stats/rtcstats.h" +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" + +namespace webrtc { + +// A collection of stats. +// This is accessible as a map from |RTCStats::id| to |RTCStats|. +class RTCStatsReport : public rtc::RefCountInterface { + public: + typedef std::map> StatsMap; + + class ConstIterator { + public: + ConstIterator(const ConstIterator&& other); + ~ConstIterator(); + + ConstIterator& operator++(); + ConstIterator& operator++(int); + const RTCStats& operator*() const; + const RTCStats* operator->() const; + bool operator==(const ConstIterator& other) const; + bool operator!=(const ConstIterator& other) const; + + private: + friend class RTCStatsReport; + ConstIterator(const rtc::scoped_refptr& report, + StatsMap::const_iterator it); + + // Reference report to make sure it is kept alive. + rtc::scoped_refptr report_; + StatsMap::const_iterator it_; + }; + + // TODO(hbos): Remove "= 0" once Chromium unittest has been updated to call + // with a parameter. crbug.com/627816 + static rtc::scoped_refptr Create(int64_t timestamp_us = 0); + + explicit RTCStatsReport(int64_t timestamp_us); + RTCStatsReport(const RTCStatsReport& other) = delete; + + int64_t timestamp_us() const { return timestamp_us_; } + void AddStats(std::unique_ptr stats); + const RTCStats* Get(const std::string& id) const; + size_t size() const { return stats_.size(); } + + // Takes ownership of all the stats in |victim|, leaving it empty. + void TakeMembersFrom(rtc::scoped_refptr victim); + + // Stats iterators. Stats are ordered lexicographically on |RTCStats::id|. + ConstIterator begin() const; + ConstIterator end() const; + + // Gets the subset of stats that are of type |T|, where |T| is any class + // descending from |RTCStats|. + template + std::vector GetStatsOfType() const { + std::vector stats_of_type; + for (const RTCStats& stats : *this) { + if (stats.type() == T::kType) + stats_of_type.push_back(&stats.cast_to()); + } + return stats_of_type; + } + + // Creates a human readable string representation of the report, listing all + // of its stats objects. + std::string ToString() const; + + friend class rtc::RefCountedObject; + + private: + ~RTCStatsReport() override; + + int64_t timestamp_us_; + StatsMap stats_; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_STATS_RTCSTATSREPORT_H_ diff --git a/include/webrtc/api/statstypes.h b/include/webrtc/api/statstypes.h index 4f58b97..8ef79d9 100644 --- a/include/webrtc/api/statstypes.h +++ b/include/webrtc/api/statstypes.h @@ -18,11 +18,10 @@ #include #include #include +#include #include "webrtc/base/basictypes.h" -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/base/linked_ptr.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/stringencode.h" @@ -106,16 +105,24 @@ class StatsReport { kStatsValueNameBytesSent, kStatsValueNameCodecImplementationName, kStatsValueNameDataChannelId, + kStatsValueNameFramesDecoded, + kStatsValueNameFramesEncoded, kStatsValueNameMediaType, kStatsValueNamePacketsLost, kStatsValueNamePacketsReceived, kStatsValueNamePacketsSent, kStatsValueNameProtocol, + kStatsValueNameQpSum, kStatsValueNameReceiving, kStatsValueNameSelectedCandidatePairId, kStatsValueNameSsrc, kStatsValueNameState, kStatsValueNameTransportId, + kStatsValueNameSentPingRequestsTotal, + kStatsValueNameSentPingRequestsBeforeFirstResponse, + kStatsValueNameSentPingResponses, + kStatsValueNameRecvPingRequests, + kStatsValueNameRecvPingResponses, // Internal StatsValue names. kStatsValueNameAccelerateRate, @@ -143,6 +150,7 @@ class StatsReport { kStatsValueNameDecodingCNG, kStatsValueNameDecodingCTN, kStatsValueNameDecodingCTSG, + kStatsValueNameDecodingMutedOutput, kStatsValueNameDecodingNormal, kStatsValueNameDecodingPLC, kStatsValueNameDecodingPLCCNG, @@ -192,6 +200,8 @@ class StatsReport { kStatsValueNameRemoteCandidateType, kStatsValueNameRemoteCertificateId, kStatsValueNameRenderDelayMs, + kStatsValueNameResidualEchoLikelihood, + kStatsValueNameResidualEchoLikelihoodRecentMax, kStatsValueNameRetransmitBitrate, kStatsValueNameRtt, kStatsValueNameSecondaryDecodedRate, @@ -204,7 +214,6 @@ class StatsReport { kStatsValueNameTransmitBitrate, kStatsValueNameTransportType, kStatsValueNameTypingNoiseState, - kStatsValueNameViewLimitedResolution, kStatsValueNameWritable, }; @@ -226,7 +235,7 @@ class StatsReport { // Protected since users of the IdBase type will be using the Id typedef. virtual bool Equals(const IdBase& other) const; - IdBase(StatsType type); // Only meant for derived classes. + explicit IdBase(StatsType type); // Only meant for derived classes. const StatsType type_; static const char kSeparator = '_'; @@ -254,6 +263,22 @@ class StatsReport { ~Value(); + // Support ref counting. Note that for performance reasons, we + // don't use thread safe operations. Therefore, all operations + // affecting the ref count (in practice, creation and copying of + // the Values mapping) must occur on webrtc's signalling thread. + int AddRef() const { + RTC_DCHECK_RUN_ON(&thread_checker_); + return ++ref_count_; + } + int Release() const { + RTC_DCHECK_RUN_ON(&thread_checker_); + int count = --ref_count_; + if (!count) + delete this; + return count; + } + // TODO(tommi): This compares name as well as value... // I think we should only need to compare the value part and // move the name part into a hash map. @@ -294,6 +319,9 @@ class StatsReport { const StatsValueName name; private: + rtc::ThreadChecker thread_checker_; + mutable int ref_count_ ACCESS_ON(thread_checker_) = 0; + const Type type_; // TODO(tommi): Use C++ 11 union and make value_ const. union InternalType { @@ -306,17 +334,15 @@ class StatsReport { Id* id_; } value_; - private: RTC_DISALLOW_COPY_AND_ASSIGN(Value); }; - // TODO(tommi): Consider using a similar approach to how we store Ids using - // scoped_refptr for values. - typedef rtc::linked_ptr ValuePtr; + typedef rtc::scoped_refptr ValuePtr; typedef std::map Values; // Ownership of |id| is passed to |this|. explicit StatsReport(const Id& id); + ~StatsReport(); // Factory functions for various types of stats IDs. static Id NewBandwidthEstimationId(); @@ -389,7 +415,7 @@ class StatsCollection { StatsReport* FindOrAddNew(const StatsReport::Id& id); StatsReport* ReplaceOrAddNew(const StatsReport::Id& id); - // Looks for a report with the given |id|. If one is not found, NULL + // Looks for a report with the given |id|. If one is not found, null // will be returned. StatsReport* Find(const StatsReport::Id& id); diff --git a/include/webrtc/api/streamcollection.h b/include/webrtc/api/streamcollection.h index bedad83..0f847f1 100644 --- a/include/webrtc/api/streamcollection.h +++ b/include/webrtc/api/streamcollection.h @@ -11,98 +11,8 @@ #ifndef WEBRTC_API_STREAMCOLLECTION_H_ #define WEBRTC_API_STREAMCOLLECTION_H_ -#include -#include - -#include "webrtc/api/peerconnectioninterface.h" - -namespace webrtc { - -// Implementation of StreamCollection. -class StreamCollection : public StreamCollectionInterface { - public: - static rtc::scoped_refptr Create() { - rtc::RefCountedObject* implementation = - new rtc::RefCountedObject(); - return implementation; - } - - static rtc::scoped_refptr Create( - StreamCollection* streams) { - rtc::RefCountedObject* implementation = - new rtc::RefCountedObject(streams); - return implementation; - } - - virtual size_t count() { - return media_streams_.size(); - } - - virtual MediaStreamInterface* at(size_t index) { - return media_streams_.at(index); - } - - virtual MediaStreamInterface* find(const std::string& label) { - for (StreamVector::iterator it = media_streams_.begin(); - it != media_streams_.end(); ++it) { - if ((*it)->label().compare(label) == 0) { - return (*it); - } - } - return NULL; - } - - virtual MediaStreamTrackInterface* FindAudioTrack( - const std::string& id) { - for (size_t i = 0; i < media_streams_.size(); ++i) { - MediaStreamTrackInterface* track = media_streams_[i]->FindAudioTrack(id); - if (track) { - return track; - } - } - return NULL; - } - - virtual MediaStreamTrackInterface* FindVideoTrack( - const std::string& id) { - for (size_t i = 0; i < media_streams_.size(); ++i) { - MediaStreamTrackInterface* track = media_streams_[i]->FindVideoTrack(id); - if (track) { - return track; - } - } - return NULL; - } - - void AddStream(MediaStreamInterface* stream) { - for (StreamVector::iterator it = media_streams_.begin(); - it != media_streams_.end(); ++it) { - if ((*it)->label().compare(stream->label()) == 0) - return; - } - media_streams_.push_back(stream); - } - - void RemoveStream(MediaStreamInterface* remove_stream) { - for (StreamVector::iterator it = media_streams_.begin(); - it != media_streams_.end(); ++it) { - if ((*it)->label().compare(remove_stream->label()) == 0) { - media_streams_.erase(it); - break; - } - } - } - - protected: - StreamCollection() {} - explicit StreamCollection(StreamCollection* original) - : media_streams_(original->media_streams_) { - } - typedef std::vector > - StreamVector; - StreamVector media_streams_; -}; - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/streamcollection.h" #endif // WEBRTC_API_STREAMCOLLECTION_H_ diff --git a/include/webrtc/api/test/mock_audio_mixer.h b/include/webrtc/api/test/mock_audio_mixer.h new file mode 100644 index 0000000..189455f --- /dev/null +++ b/include/webrtc/api/test/mock_audio_mixer.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_TEST_MOCK_AUDIO_MIXER_H_ +#define WEBRTC_API_TEST_MOCK_AUDIO_MIXER_H_ + +#include "webrtc/api/audio/audio_mixer.h" + +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockAudioMixer : public AudioMixer { + public: + MOCK_METHOD1(AddSource, bool(Source* audio_source)); + MOCK_METHOD1(RemoveSource, void(Source* audio_source)); + MOCK_METHOD2(Mix, + void(size_t number_of_channels, + AudioFrame* audio_frame_for_mixing)); +}; +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_API_TEST_MOCK_AUDIO_MIXER_H_ diff --git a/include/webrtc/api/test/mock_rtpreceiver.h b/include/webrtc/api/test/mock_rtpreceiver.h new file mode 100644 index 0000000..25f5c28 --- /dev/null +++ b/include/webrtc/api/test/mock_rtpreceiver.h @@ -0,0 +1,34 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_TEST_MOCK_RTPRECEIVER_H_ +#define WEBRTC_API_TEST_MOCK_RTPRECEIVER_H_ + +#include + +#include "webrtc/api/rtpreceiverinterface.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRtpReceiver : public rtc::RefCountedObject { + public: + MOCK_METHOD1(SetTrack, void(MediaStreamTrackInterface*)); + MOCK_CONST_METHOD0(track, rtc::scoped_refptr()); + MOCK_CONST_METHOD0(media_type, cricket::MediaType()); + MOCK_CONST_METHOD0(id, std::string()); + MOCK_CONST_METHOD0(GetParameters, RtpParameters()); + MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); + MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*)); +}; + +} // namespace webrtc + +#endif // WEBRTC_API_TEST_MOCK_RTPRECEIVER_H_ diff --git a/include/webrtc/api/test/mock_rtpsender.h b/include/webrtc/api/test/mock_rtpsender.h new file mode 100644 index 0000000..7458f45 --- /dev/null +++ b/include/webrtc/api/test/mock_rtpsender.h @@ -0,0 +1,37 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_TEST_MOCK_RTPSENDER_H_ +#define WEBRTC_API_TEST_MOCK_RTPSENDER_H_ + +#include +#include + +#include "webrtc/api/rtpsenderinterface.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRtpSender : public rtc::RefCountedObject { + public: + MOCK_METHOD1(SetTrack, bool(MediaStreamTrackInterface*)); + MOCK_CONST_METHOD0(track, rtc::scoped_refptr()); + MOCK_CONST_METHOD0(ssrc, uint32_t()); + MOCK_CONST_METHOD0(media_type, cricket::MediaType()); + MOCK_CONST_METHOD0(id, std::string()); + MOCK_CONST_METHOD0(stream_ids, std::vector()); + MOCK_CONST_METHOD0(GetParameters, RtpParameters()); + MOCK_METHOD1(SetParameters, bool(const RtpParameters&)); + MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr()); +}; + +} // namespace webrtc + +#endif // WEBRTC_API_TEST_MOCK_RTPSENDER_H_ diff --git a/include/webrtc/api/umametrics.h b/include/webrtc/api/umametrics.h index 5374716..8999447 100644 --- a/include/webrtc/api/umametrics.h +++ b/include/webrtc/api/umametrics.h @@ -13,6 +13,8 @@ #ifndef WEBRTC_API_UMAMETRICS_H_ #define WEBRTC_API_UMAMETRICS_H_ +#include "webrtc/base/refcount.h" + namespace webrtc { // Used to specify which enum counter type we're incrementing in @@ -32,6 +34,9 @@ enum PeerConnectionEnumCounterType { kEnumCounterVideoSslCipher, kEnumCounterDataSrtpCipher, kEnumCounterDataSslCipher, + kEnumCounterDtlsHandshakeError, + kEnumCounterIceRegathering, + kEnumCounterIceRestart, kPeerConnectionEnumCounterMax }; @@ -106,6 +111,32 @@ enum IceCandidatePairType { kIceCandidatePairMax }; +class MetricsObserverInterface : public rtc::RefCountInterface { + public: + // |type| is the type of the enum counter to be incremented. |counter| + // is the particular counter in that type. |counter_max| is the next sequence + // number after the highest counter. + virtual void IncrementEnumCounter(PeerConnectionEnumCounterType type, + int counter, + int counter_max) {} + + // This is used to handle sparse counters like SSL cipher suites. + // TODO(guoweis): Remove the implementation once the dependency's interface + // definition is updated. + virtual void IncrementSparseEnumCounter(PeerConnectionEnumCounterType type, + int counter) { + IncrementEnumCounter(type, counter, 0 /* Ignored */); + } + + virtual void AddHistogramSample(PeerConnectionMetricsName type, + int value) = 0; + + protected: + virtual ~MetricsObserverInterface() {} +}; + +typedef MetricsObserverInterface UMAObserver; + } // namespace webrtc #endif // WEBRTC_API_UMAMETRICS_H_ diff --git a/include/webrtc/api/video/i420_buffer.h b/include/webrtc/api/video/i420_buffer.h new file mode 100644 index 0000000..388a3dd --- /dev/null +++ b/include/webrtc/api/video/i420_buffer.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_VIDEO_I420_BUFFER_H_ +#define WEBRTC_API_VIDEO_I420_BUFFER_H_ + +#include + +#include "webrtc/api/video/video_rotation.h" +#include "webrtc/api/video/video_frame_buffer.h" +#include "webrtc/system_wrappers/include/aligned_malloc.h" + +namespace webrtc { + +// Plain I420 buffer in standard memory. +class I420Buffer : public VideoFrameBuffer { + public: + static rtc::scoped_refptr Create(int width, int height); + static rtc::scoped_refptr Create(int width, + int height, + int stride_y, + int stride_u, + int stride_v); + + // Create a new buffer and copy the pixel data. + static rtc::scoped_refptr Copy(const VideoFrameBuffer& buffer); + + static rtc::scoped_refptr Copy( + int width, int height, + const uint8_t* data_y, int stride_y, + const uint8_t* data_u, int stride_u, + const uint8_t* data_v, int stride_v); + + // Returns a rotated copy of |src|. + static rtc::scoped_refptr Rotate(const VideoFrameBuffer& src, + VideoRotation rotation); + + // Sets the buffer to all black. + static void SetBlack(I420Buffer* buffer); + + // Sets all three planes to all zeros. Used to work around for + // quirks in memory checkers + // (https://bugs.chromium.org/p/libyuv/issues/detail?id=377) and + // ffmpeg (http://crbug.com/390941). + // TODO(nisse): Deprecated. Should be deleted if/when those issues + // are resolved in a better way. Or in the mean time, use SetBlack. + void InitializeData(); + + // TODO(nisse): Deprecated, use static method instead. + void SetToBlack() { SetBlack(this); } + + int width() const override; + int height() const override; + const uint8_t* DataY() const override; + const uint8_t* DataU() const override; + const uint8_t* DataV() const override; + + int StrideY() const override; + int StrideU() const override; + int StrideV() const override; + + void* native_handle() const override; + rtc::scoped_refptr NativeToI420Buffer() override; + + uint8_t* MutableDataY(); + uint8_t* MutableDataU(); + uint8_t* MutableDataV(); + + // Scale the cropped area of |src| to the size of |this| buffer, and + // write the result into |this|. + void CropAndScaleFrom(const VideoFrameBuffer& src, + int offset_x, + int offset_y, + int crop_width, + int crop_height); + + // The common case of a center crop, when needed to adjust the + // aspect ratio without distorting the image. + void CropAndScaleFrom(const VideoFrameBuffer& src); + + // Scale all of |src| to the size of |this| buffer, with no cropping. + void ScaleFrom(const VideoFrameBuffer& src); + + // TODO(nisse): Deprecated, delete once downstream applications are updated. + // Returns a rotated versions of |src|. Native buffers are not + // supported. The reason this function doesn't return an I420Buffer, + // is that it returns |src| unchanged in case |rotation| is zero. + static rtc::scoped_refptr Rotate( + rtc::scoped_refptr src, + VideoRotation rotation); + + protected: + I420Buffer(int width, int height); + I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v); + + ~I420Buffer() override; + + private: + const int width_; + const int height_; + const int stride_y_; + const int stride_u_; + const int stride_v_; + const std::unique_ptr data_; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_VIDEO_I420_BUFFER_H_ diff --git a/include/webrtc/api/video/video_frame.h b/include/webrtc/api/video/video_frame.h new file mode 100644 index 0000000..8840782 --- /dev/null +++ b/include/webrtc/api/video/video_frame.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_VIDEO_VIDEO_FRAME_H_ +#define WEBRTC_API_VIDEO_VIDEO_FRAME_H_ + +#include + +#include "webrtc/api/video/video_rotation.h" +#include "webrtc/api/video/video_frame_buffer.h" + +// TODO(nisse): Transition hack, some downstream applications expect +// that including this file also defines base/timeutils.h constants. +// Delete after applications are fixed to include the right headers. +#include "webrtc/base/timeutils.h" + +namespace webrtc { + +class VideoFrame { + public: + // TODO(nisse): This constructor is consistent with the now deleted + // cricket::WebRtcVideoFrame. We should consider whether or not we + // want to stick to this style and deprecate the other constructor. + VideoFrame(const rtc::scoped_refptr& buffer, + webrtc::VideoRotation rotation, + int64_t timestamp_us); + + // Preferred constructor. + VideoFrame(const rtc::scoped_refptr& buffer, + uint32_t timestamp, + int64_t render_time_ms, + VideoRotation rotation); + + ~VideoFrame(); + + // Support move and copy. + VideoFrame(const VideoFrame&); + VideoFrame(VideoFrame&&); + VideoFrame& operator=(const VideoFrame&); + VideoFrame& operator=(VideoFrame&&); + + // Get frame width. + int width() const; + // Get frame height. + int height() const; + // Get frame size in pixels. + uint32_t size() const; + + // System monotonic clock, same timebase as rtc::TimeMicros(). + int64_t timestamp_us() const { return timestamp_us_; } + void set_timestamp_us(int64_t timestamp_us) { timestamp_us_ = timestamp_us; } + + // TODO(nisse): After the cricket::VideoFrame and webrtc::VideoFrame + // merge, timestamps other than timestamp_us will likely be + // deprecated. + + // Set frame timestamp (90kHz). + void set_timestamp(uint32_t timestamp) { timestamp_rtp_ = timestamp; } + + // Get frame timestamp (90kHz). + uint32_t timestamp() const { return timestamp_rtp_; } + + // For now, transport_frame_id and rtp timestamp are the same. + // TODO(nisse): Must be handled differently for QUIC. + uint32_t transport_frame_id() const { return timestamp(); } + + // Set capture ntp time in milliseconds. + // TODO(nisse): Deprecated. Migrate all users to timestamp_us(). + void set_ntp_time_ms(int64_t ntp_time_ms) { ntp_time_ms_ = ntp_time_ms; } + + // Get capture ntp time in milliseconds. + // TODO(nisse): Deprecated. Migrate all users to timestamp_us(). + int64_t ntp_time_ms() const { return ntp_time_ms_; } + + // Naming convention for Coordination of Video Orientation. Please see + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + // + // "pending rotation" or "pending" = a frame that has a VideoRotation > 0. + // + // "not pending" = a frame that has a VideoRotation == 0. + // + // "apply rotation" = modify a frame from being "pending" to being "not + // pending" rotation (a no-op for "unrotated"). + // + VideoRotation rotation() const { return rotation_; } + void set_rotation(VideoRotation rotation) { rotation_ = rotation; } + + // Get render time in milliseconds. + // TODO(nisse): Deprecated. Migrate all users to timestamp_us(). + int64_t render_time_ms() const; + + // Return the underlying buffer. Never nullptr for a properly + // initialized VideoFrame. + rtc::scoped_refptr video_frame_buffer() const; + + // TODO(nisse): Deprecated. + // Return true if the frame is stored in a texture. + bool is_texture() const { + return video_frame_buffer()->native_handle() != nullptr; + } + + private: + // An opaque reference counted handle that stores the pixel data. + rtc::scoped_refptr video_frame_buffer_; + uint32_t timestamp_rtp_; + int64_t ntp_time_ms_; + int64_t timestamp_us_; + VideoRotation rotation_; +}; + +} // namespace webrtc + +#endif // WEBRTC_API_VIDEO_VIDEO_FRAME_H_ diff --git a/include/webrtc/api/video/video_frame_buffer.h b/include/webrtc/api/video/video_frame_buffer.h new file mode 100644 index 0000000..c8c2e5d --- /dev/null +++ b/include/webrtc/api/video/video_frame_buffer.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_VIDEO_VIDEO_FRAME_BUFFER_H_ +#define WEBRTC_API_VIDEO_VIDEO_FRAME_BUFFER_H_ + +#include + +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" + +namespace webrtc { + +// Interface of a simple frame buffer containing pixel data. This interface does +// not contain any frame metadata such as rotation, timestamp, pixel_width, etc. +class VideoFrameBuffer : public rtc::RefCountInterface { + public: + // The resolution of the frame in pixels. For formats where some planes are + // subsampled, this is the highest-resolution plane. + virtual int width() const = 0; + virtual int height() const = 0; + + // Returns pointer to the pixel data for a given plane. The memory is owned by + // the VideoFrameBuffer object and must not be freed by the caller. + virtual const uint8_t* DataY() const = 0; + virtual const uint8_t* DataU() const = 0; + virtual const uint8_t* DataV() const = 0; + + // Returns the number of bytes between successive rows for a given plane. + virtual int StrideY() const = 0; + virtual int StrideU() const = 0; + virtual int StrideV() const = 0; + + // Return the handle of the underlying video frame. This is used when the + // frame is backed by a texture. + virtual void* native_handle() const = 0; + + // Returns a new memory-backed frame buffer converted from this buffer's + // native handle. + virtual rtc::scoped_refptr NativeToI420Buffer() = 0; + + protected: + ~VideoFrameBuffer() override {} +}; + +} // namespace webrtc + +#endif // WEBRTC_API_VIDEO_VIDEO_FRAME_BUFFER_H_ diff --git a/include/webrtc/api/video/video_rotation.h b/include/webrtc/api/video/video_rotation.h new file mode 100644 index 0000000..b8b2767 --- /dev/null +++ b/include/webrtc/api/video/video_rotation.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_API_VIDEO_VIDEO_ROTATION_H_ +#define WEBRTC_API_VIDEO_VIDEO_ROTATION_H_ + +namespace webrtc { + +// enum for clockwise rotation. +enum VideoRotation { + kVideoRotation_0 = 0, + kVideoRotation_90 = 90, + kVideoRotation_180 = 180, + kVideoRotation_270 = 270 +}; + +} // namespace webrtc + +#endif // WEBRTC_API_VIDEO_VIDEO_ROTATION_H_ diff --git a/include/webrtc/api/videosourceproxy.h b/include/webrtc/api/videosourceproxy.h index 6d4dfcb..a00a21d 100644 --- a/include/webrtc/api/videosourceproxy.h +++ b/include/webrtc/api/videosourceproxy.h @@ -16,28 +16,25 @@ namespace webrtc { -// VideoTrackSourceInterface makes sure the real VideoTrackSourceInterface -// implementation is -// destroyed on the signaling thread and marshals all method calls to the -// signaling thread. +// Makes sure the real VideoTrackSourceInterface implementation is destroyed on +// the signaling thread and marshals all method calls to the signaling thread. +// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods +// are called on is an implementation detail. BEGIN_PROXY_MAP(VideoTrackSource) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(SourceState, state) PROXY_CONSTMETHOD0(bool, remote) - PROXY_METHOD0(void, Stop) - PROXY_METHOD0(void, Restart) PROXY_CONSTMETHOD0(bool, is_screencast) PROXY_CONSTMETHOD0(rtc::Optional, needs_denoising) PROXY_METHOD1(bool, GetStats, Stats*) PROXY_WORKER_METHOD2(void, AddOrUpdateSink, - rtc::VideoSinkInterface*, + rtc::VideoSinkInterface*, const rtc::VideoSinkWants&) - PROXY_WORKER_METHOD1(void, - RemoveSink, - rtc::VideoSinkInterface*) + PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface*) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/include/webrtc/api/videotracksource.h b/include/webrtc/api/videotracksource.h index 10e24ab..45366cd 100644 --- a/include/webrtc/api/videotracksource.h +++ b/include/webrtc/api/videotracksource.h @@ -11,49 +11,8 @@ #ifndef WEBRTC_API_VIDEOTRACKSOURCE_H_ #define WEBRTC_API_VIDEOTRACKSOURCE_H_ -#include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/notifier.h" -#include "webrtc/base/thread_checker.h" -#include "webrtc/media/base/mediachannel.h" -#include "webrtc/media/base/videosinkinterface.h" - -// VideoTrackSource implements VideoTrackSourceInterface. -namespace webrtc { - -class VideoTrackSource : public Notifier { - public: - VideoTrackSource(rtc::VideoSourceInterface* source, - bool remote); - void SetState(SourceState new_state); - // OnSourceDestroyed clears this instance pointer to |source_|. It is useful - // when the underlying rtc::VideoSourceInterface is destroyed before the - // reference counted VideoTrackSource. - void OnSourceDestroyed(); - - SourceState state() const override { return state_; } - bool remote() const override { return remote_; } - - void Stop() override{}; - void Restart() override{}; - - bool is_screencast() const override { return false; } - rtc::Optional needs_denoising() const override { - return rtc::Optional(); } - - bool GetStats(Stats* stats) override { return false; } - - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; - - private: - rtc::ThreadChecker worker_thread_checker_; - rtc::VideoSourceInterface* source_; - cricket::VideoOptions options_; - SourceState state_; - const bool remote_; -}; - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/videotracksource.h" #endif // WEBRTC_API_VIDEOTRACKSOURCE_H_ diff --git a/include/webrtc/api/webrtcsdp.h b/include/webrtc/api/webrtcsdp.h index e7fdb34..bd7809a 100644 --- a/include/webrtc/api/webrtcsdp.h +++ b/include/webrtc/api/webrtcsdp.h @@ -8,80 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -// This file contain functions for parsing and serializing SDP messages. -// Related RFC/draft including: -// * RFC 4566 - SDP -// * RFC 5245 - ICE -// * RFC 3388 - Grouping of Media Lines in SDP -// * RFC 4568 - SDP Security Descriptions for Media Streams -// * draft-lennox-mmusic-sdp-source-selection-02 - -// Mechanisms for Media Source Selection in SDP - #ifndef WEBRTC_API_WEBRTCSDP_H_ #define WEBRTC_API_WEBRTCSDP_H_ -#include - -namespace cricket { -class Candidate; -} // namespace cricket - -namespace webrtc { -class IceCandidateInterface; -class JsepIceCandidate; -class JsepSessionDescription; -struct SdpParseError; - -// Serializes the passed in JsepSessionDescription. -// Serialize SessionDescription including candidates if -// JsepSessionDescription has candidates. -// jdesc - The JsepSessionDescription object to be serialized. -// unified_plan_sdp - If set to true, include "a=msid" lines where appropriate. -// return - SDP string serialized from the arguments. -std::string SdpSerialize(const JsepSessionDescription& jdesc, - bool unified_plan_sdp); - -// Serializes the passed in IceCandidateInterface to a SDP string. -// candidate - The candidate to be serialized. -std::string SdpSerializeCandidate(const IceCandidateInterface& candidate); - -// Serializes a cricket Candidate. -// candidate - The candidate to be serialized. -std::string SdpSerializeCandidate(const cricket::Candidate& candidate); - -// Deserializes the passed in SDP string to a JsepSessionDescription. -// message - SDP string to be Deserialized. -// jdesc - The JsepSessionDescription deserialized from the SDP string. -// error - The detail error information when parsing fails. -// return - true on success, false on failure. -bool SdpDeserialize(const std::string& message, - JsepSessionDescription* jdesc, - SdpParseError* error); - -// Deserializes the passed in SDP string to one JsepIceCandidate. -// The first line must be a=candidate line and only the first line will be -// parsed. -// message - The SDP string to be Deserialized. -// candidates - The JsepIceCandidate from the SDP string. -// error - The detail error information when parsing fails. -// return - true on success, false on failure. -bool SdpDeserializeCandidate(const std::string& message, - JsepIceCandidate* candidate, - SdpParseError* error); - -// Deserializes the passed in SDP string to a cricket Candidate. -// The first line must be a=candidate line and only the first line will be -// parsed. -// transport_name - The transport name (MID) of the candidate. -// message - The SDP string to be deserialized. -// candidate - The cricket Candidate from the SDP string. -// error - The detail error information when parsing fails. -// return - true on success, false on failure. -bool SdpDeserializeCandidate(const std::string& transport_name, - const std::string& message, - cricket::Candidate* candidate, - SdpParseError* error); - -} // namespace webrtc +// Including this file is deprecated. It is no longer part of the public API. +// This only includes the file in its new location for backwards compatibility. +#include "webrtc/pc/webrtcsdp.h" #endif // WEBRTC_API_WEBRTCSDP_H_ diff --git a/include/webrtc/audio/audio_receive_stream.h b/include/webrtc/audio/audio_receive_stream.h index d99956c..e344e22 100644 --- a/include/webrtc/audio/audio_receive_stream.h +++ b/include/webrtc/audio/audio_receive_stream.h @@ -13,27 +13,33 @@ #include -#include "webrtc/audio_receive_stream.h" -#include "webrtc/audio_state.h" +#include "webrtc/api/audio/audio_mixer.h" +#include "webrtc/audio/audio_state.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/thread_checker.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" +#include "webrtc/call/audio_receive_stream.h" +#include "webrtc/call/syncable.h" namespace webrtc { -class CongestionController; -class RemoteBitrateEstimator; +class PacketRouter; +class RtcEventLog; +class RtpPacketReceived; namespace voe { class ChannelProxy; } // namespace voe namespace internal { +class AudioSendStream; -class AudioReceiveStream final : public webrtc::AudioReceiveStream { +class AudioReceiveStream final : public webrtc::AudioReceiveStream, + public AudioMixer::Source, + public Syncable { public: - AudioReceiveStream(CongestionController* congestion_controller, + AudioReceiveStream(PacketRouter* packet_router, const webrtc::AudioReceiveStream::Config& config, - const rtc::scoped_refptr& audio_state); + const rtc::scoped_refptr& audio_state, + webrtc::RtcEventLog* event_log); ~AudioReceiveStream() override; // webrtc::AudioReceiveStream implementation. @@ -41,24 +47,41 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream { void Stop() override; webrtc::AudioReceiveStream::Stats GetStats() const override; void SetSink(std::unique_ptr sink) override; + void SetGain(float gain) override; + // TODO(nisse): Intended to be part of an RtpPacketReceiver interface. + void OnRtpPacket(const RtpPacketReceived& packet); + + // AudioMixer::Source + AudioFrameInfo GetAudioFrameWithInfo(int sample_rate_hz, + AudioFrame* audio_frame) override; + int Ssrc() const override; + int PreferredSampleRate() const override; + + // Syncable + int id() const override; + rtc::Optional GetInfo() const override; + uint32_t GetPlayoutTimestamp() const override; + void SetMinimumPlayoutDelay(int delay_ms) override; + + void AssociateSendStream(AudioSendStream* send_stream); void SignalNetworkState(NetworkState state); bool DeliverRtcp(const uint8_t* packet, size_t length); - bool DeliverRtp(const uint8_t* packet, - size_t length, - const PacketTime& packet_time); const webrtc::AudioReceiveStream::Config& config() const; private: VoiceEngine* voice_engine() const; + AudioState* audio_state() const; + int SetVoiceEnginePlayout(bool playout); - rtc::ThreadChecker thread_checker_; - RemoteBitrateEstimator* remote_bitrate_estimator_ = nullptr; + rtc::ThreadChecker worker_thread_checker_; + rtc::ThreadChecker module_process_thread_checker_; const webrtc::AudioReceiveStream::Config config_; rtc::scoped_refptr audio_state_; - std::unique_ptr rtp_header_parser_; std::unique_ptr channel_proxy_; + bool playing_ ACCESS_ON(worker_thread_checker_) = false; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioReceiveStream); }; } // namespace internal diff --git a/include/webrtc/audio/audio_send_stream.h b/include/webrtc/audio/audio_send_stream.h index 61dd7f2..5ee49da 100644 --- a/include/webrtc/audio/audio_send_stream.h +++ b/include/webrtc/audio/audio_send_stream.h @@ -13,46 +13,73 @@ #include -#include "webrtc/audio_send_stream.h" -#include "webrtc/audio_state.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/thread_checker.h" +#include "webrtc/call/audio_send_stream.h" +#include "webrtc/call/audio_state.h" +#include "webrtc/call/bitrate_allocator.h" namespace webrtc { class CongestionController; class VoiceEngine; +class RtcEventLog; +class RtcpBandwidthObserver; +class RtcpRttStats; +class PacketRouter; namespace voe { class ChannelProxy; } // namespace voe namespace internal { -class AudioSendStream final : public webrtc::AudioSendStream { +class AudioSendStream final : public webrtc::AudioSendStream, + public webrtc::BitrateAllocatorObserver { public: AudioSendStream(const webrtc::AudioSendStream::Config& config, const rtc::scoped_refptr& audio_state, - CongestionController* congestion_controller); + rtc::TaskQueue* worker_queue, + PacketRouter* packet_router, + CongestionController* congestion_controller, + BitrateAllocator* bitrate_allocator, + RtcEventLog* event_log, + RtcpRttStats* rtcp_rtt_stats); ~AudioSendStream() override; // webrtc::AudioSendStream implementation. void Start() override; void Stop() override; - bool SendTelephoneEvent(int payload_type, int event, + bool SendTelephoneEvent(int payload_type, int payload_frequency, int event, int duration_ms) override; + void SetMuted(bool muted) override; webrtc::AudioSendStream::Stats GetStats() const override; void SignalNetworkState(NetworkState state); bool DeliverRtcp(const uint8_t* packet, size_t length); + + // Implements BitrateAllocatorObserver. + uint32_t OnBitrateUpdated(uint32_t bitrate_bps, + uint8_t fraction_loss, + int64_t rtt, + int64_t probing_interval_ms) override; + const webrtc::AudioSendStream::Config& config() const; + void SetTransportOverhead(int transport_overhead_per_packet); private: VoiceEngine* voice_engine() const; + bool SetupSendCodec(); + rtc::ThreadChecker thread_checker_; + rtc::TaskQueue* worker_queue_; const webrtc::AudioSendStream::Config config_; rtc::scoped_refptr audio_state_; std::unique_ptr channel_proxy_; + BitrateAllocator* const bitrate_allocator_; + CongestionController* const congestion_controller_; + std::unique_ptr bandwidth_observer_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream); }; } // namespace internal diff --git a/include/webrtc/audio/audio_state.h b/include/webrtc/audio/audio_state.h index 6bee3c6..29b5a9e 100644 --- a/include/webrtc/audio/audio_state.h +++ b/include/webrtc/audio/audio_state.h @@ -11,11 +11,12 @@ #ifndef WEBRTC_AUDIO_AUDIO_STATE_H_ #define WEBRTC_AUDIO_AUDIO_STATE_H_ -#include "webrtc/audio_state.h" +#include "webrtc/audio/audio_transport_proxy.h" #include "webrtc/audio/scoped_voe_interface.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_checker.h" +#include "webrtc/call/audio_state.h" #include "webrtc/voice_engine/include/voe_base.h" namespace webrtc { @@ -28,6 +29,8 @@ class AudioState final : public webrtc::AudioState, ~AudioState() override; VoiceEngine* voice_engine(); + + rtc::scoped_refptr mixer(); bool typing_noise_detected() const; private: @@ -53,6 +56,10 @@ class AudioState final : public webrtc::AudioState, // Reference count; implementation copied from rtc::RefCountedObject. mutable volatile int ref_count_ = 0; + // Transports mixed audio from the mixer to the audio device and + // recorded audio to the VoE AudioTransport. + AudioTransportProxy audio_transport_proxy_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioState); }; } // namespace internal diff --git a/include/webrtc/audio/audio_transport_proxy.h b/include/webrtc/audio/audio_transport_proxy.h new file mode 100644 index 0000000..1d03378 --- /dev/null +++ b/include/webrtc/audio/audio_transport_proxy.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_AUDIO_AUDIO_TRANSPORT_PROXY_H_ +#define WEBRTC_AUDIO_AUDIO_TRANSPORT_PROXY_H_ + +#include "webrtc/api/audio/audio_mixer.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/common_audio/resampler/include/push_resampler.h" +#include "webrtc/modules/audio_device/include/audio_device_defines.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" + +namespace webrtc { + +class AudioTransportProxy : public AudioTransport { + public: + AudioTransportProxy(AudioTransport* voe_audio_transport, + AudioProcessing* apm, + AudioMixer* mixer); + + ~AudioTransportProxy() override; + + int32_t RecordedDataIsAvailable(const void* audioSamples, + const size_t nSamples, + const size_t nBytesPerSample, + const size_t nChannels, + const uint32_t samplesPerSec, + const uint32_t totalDelayMS, + const int32_t clockDrift, + const uint32_t currentMicLevel, + const bool keyPressed, + uint32_t& newMicLevel) override; + + int32_t NeedMorePlayData(const size_t nSamples, + const size_t nBytesPerSample, + const size_t nChannels, + const uint32_t samplesPerSec, + void* audioSamples, + size_t& nSamplesOut, + int64_t* elapsed_time_ms, + int64_t* ntp_time_ms) override; + + void PushCaptureData(int voe_channel, + const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames) override; + + void PullRenderData(int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames, + void* audio_data, + int64_t* elapsed_time_ms, + int64_t* ntp_time_ms) override; + + private: + AudioTransport* voe_audio_transport_; + AudioProcessing* apm_; + rtc::scoped_refptr mixer_; + AudioFrame mixed_frame_; + // Converts mixed audio to the audio device output rate. + PushResampler resampler_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioTransportProxy); +}; +} // namespace webrtc + +#endif // WEBRTC_AUDIO_AUDIO_TRANSPORT_PROXY_H_ diff --git a/include/webrtc/audio/utility/audio_frame_operations.h b/include/webrtc/audio/utility/audio_frame_operations.h new file mode 100644 index 0000000..d16b163 --- /dev/null +++ b/include/webrtc/audio/utility/audio_frame_operations.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_ +#define WEBRTC_AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_ + +#include + +#include "webrtc/typedefs.h" + +namespace webrtc { + +class AudioFrame; + +// TODO(andrew): consolidate this with utility.h and audio_frame_manipulator.h. +// Change reference parameters to pointers. Consider using a namespace rather +// than a class. +class AudioFrameOperations { + public: + // Add samples in |frame_to_add| with samples in |result_frame| + // putting the results in |results_frame|. The fields + // |vad_activity_| and |speech_type_| of the result frame are + // updated. If |result_frame| is empty (|samples_per_channel_|==0), + // the samples in |frame_to_add| are added to it. The number of + // channels and number of samples per channel must match except when + // |result_frame| is empty. + static void Add(const AudioFrame& frame_to_add, AudioFrame* result_frame); + + // Upmixes mono |src_audio| to stereo |dst_audio|. This is an out-of-place + // operation, meaning src_audio and dst_audio must point to different + // buffers. It is the caller's responsibility to ensure that |dst_audio| is + // sufficiently large. + static void MonoToStereo(const int16_t* src_audio, + size_t samples_per_channel, + int16_t* dst_audio); + // |frame.num_channels_| will be updated. This version checks for sufficient + // buffer size and that |num_channels_| is mono. + static int MonoToStereo(AudioFrame* frame); + + // Downmixes stereo |src_audio| to mono |dst_audio|. This is an in-place + // operation, meaning |src_audio| and |dst_audio| may point to the same + // buffer. + static void StereoToMono(const int16_t* src_audio, + size_t samples_per_channel, + int16_t* dst_audio); + // |frame.num_channels_| will be updated. This version checks that + // |num_channels_| is stereo. + static int StereoToMono(AudioFrame* frame); + + // Swap the left and right channels of |frame|. Fails silently if |frame| is + // not stereo. + static void SwapStereoChannels(AudioFrame* frame); + + // Conditionally zero out contents of |frame| for implementing audio mute: + // |previous_frame_muted| && |current_frame_muted| - Zero out whole frame. + // |previous_frame_muted| && !|current_frame_muted| - Fade-in at frame start. + // !|previous_frame_muted| && |current_frame_muted| - Fade-out at frame end. + // !|previous_frame_muted| && !|current_frame_muted| - Leave frame untouched. + static void Mute(AudioFrame* frame, + bool previous_frame_muted, + bool current_frame_muted); + + // Zero out contents of frame. + static void Mute(AudioFrame* frame); + + // Halve samples in |frame|. + static void ApplyHalfGain(AudioFrame* frame); + + static int Scale(float left, float right, AudioFrame& frame); + + static int ScaleWithSat(float scale, AudioFrame& frame); +}; + +} // namespace webrtc + +#endif // WEBRTC_AUDIO_UTILITY_AUDIO_FRAME_OPERATIONS_H_ diff --git a/include/webrtc/audio_receive_stream.h b/include/webrtc/audio_receive_stream.h deleted file mode 100644 index 6d72b4d..0000000 --- a/include/webrtc/audio_receive_stream.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_AUDIO_RECEIVE_STREAM_H_ -#define WEBRTC_AUDIO_RECEIVE_STREAM_H_ - -#include -#include -#include -#include - -#include "webrtc/common_types.h" -#include "webrtc/config.h" -#include "webrtc/transport.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class AudioDecoder; -class AudioSinkInterface; - -// WORK IN PROGRESS -// This class is under development and is not yet intended for for use outside -// of WebRtc/Libjingle. Please use the VoiceEngine API instead. -// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690 - -class AudioReceiveStream { - public: - struct Stats { - uint32_t remote_ssrc = 0; - int64_t bytes_rcvd = 0; - uint32_t packets_rcvd = 0; - uint32_t packets_lost = 0; - float fraction_lost = 0.0f; - std::string codec_name; - uint32_t ext_seqnum = 0; - uint32_t jitter_ms = 0; - uint32_t jitter_buffer_ms = 0; - uint32_t jitter_buffer_preferred_ms = 0; - uint32_t delay_estimate_ms = 0; - int32_t audio_level = -1; - float expand_rate = 0.0f; - float speech_expand_rate = 0.0f; - float secondary_decoded_rate = 0.0f; - float accelerate_rate = 0.0f; - float preemptive_expand_rate = 0.0f; - int32_t decoding_calls_to_silence_generator = 0; - int32_t decoding_calls_to_neteq = 0; - int32_t decoding_normal = 0; - int32_t decoding_plc = 0; - int32_t decoding_cng = 0; - int32_t decoding_plc_cng = 0; - int64_t capture_start_ntp_time_ms = 0; - }; - - struct Config { - std::string ToString() const; - - // Receive-stream specific RTP settings. - struct Rtp { - std::string ToString() const; - - // Synchronization source (stream identifier) to be received. - uint32_t remote_ssrc = 0; - - // Sender SSRC used for sending RTCP (such as receiver reports). - uint32_t local_ssrc = 0; - - // Enable feedback for send side bandwidth estimation. - // See - // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions - // for details. - bool transport_cc = false; - - // RTP header extensions used for the received stream. - std::vector extensions; - } rtp; - - Transport* rtcp_send_transport = nullptr; - - // Underlying VoiceEngine handle, used to map AudioReceiveStream to lower- - // level components. - // TODO(solenberg): Remove when VoiceEngine channels are created outside - // of Call. - int voe_channel_id = -1; - - // Identifier for an A/V synchronization group. Empty string to disable. - // TODO(pbos): Synchronize streams in a sync group, not just one video - // stream to one audio stream. Tracked by issue webrtc:4762. - std::string sync_group; - - // Decoders for every payload that we can receive. Call owns the - // AudioDecoder instances once the Config is submitted to - // Call::CreateReceiveStream(). - // TODO(solenberg): Use unique_ptr<> once our std lib fully supports C++11. - std::map decoder_map; - }; - - // Starts stream activity. - // When a stream is active, it can receive, process and deliver packets. - virtual void Start() = 0; - // Stops stream activity. - // When a stream is stopped, it can't receive, process or deliver packets. - virtual void Stop() = 0; - - virtual Stats GetStats() const = 0; - - // Sets an audio sink that receives unmixed audio from the receive stream. - // Ownership of the sink is passed to the stream and can be used by the - // caller to do lifetime management (i.e. when the sink's dtor is called). - // Only one sink can be set and passing a null sink clears an existing one. - // NOTE: Audio must still somehow be pulled through AudioTransport for audio - // to stream through this sink. In practice, this happens if mixed audio - // is being pulled+rendered and/or if audio is being pulled for the purposes - // of feeding to the AEC. - virtual void SetSink(std::unique_ptr sink) = 0; - - protected: - virtual ~AudioReceiveStream() {} -}; -} // namespace webrtc - -#endif // WEBRTC_AUDIO_RECEIVE_STREAM_H_ diff --git a/include/webrtc/audio_send_stream.h b/include/webrtc/audio_send_stream.h deleted file mode 100644 index d8e98bb..0000000 --- a/include/webrtc/audio_send_stream.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_AUDIO_SEND_STREAM_H_ -#define WEBRTC_AUDIO_SEND_STREAM_H_ - -#include -#include -#include - -#include "webrtc/config.h" -#include "webrtc/modules/audio_coding/codecs/audio_encoder.h" -#include "webrtc/transport.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -// WORK IN PROGRESS -// This class is under development and is not yet intended for for use outside -// of WebRtc/Libjingle. Please use the VoiceEngine API instead. -// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690 - -class AudioSendStream { - public: - struct Stats { - // TODO(solenberg): Harmonize naming and defaults with receive stream stats. - uint32_t local_ssrc = 0; - int64_t bytes_sent = 0; - int32_t packets_sent = 0; - int32_t packets_lost = -1; - float fraction_lost = -1.0f; - std::string codec_name; - int32_t ext_seqnum = -1; - int32_t jitter_ms = -1; - int64_t rtt_ms = -1; - int32_t audio_level = -1; - float aec_quality_min = -1.0f; - int32_t echo_delay_median_ms = -1; - int32_t echo_delay_std_ms = -1; - int32_t echo_return_loss = -100; - int32_t echo_return_loss_enhancement = -100; - bool typing_noise_detected = false; - }; - - struct Config { - Config() = delete; - explicit Config(Transport* send_transport) - : send_transport(send_transport) {} - - std::string ToString() const; - - // Receive-stream specific RTP settings. - struct Rtp { - std::string ToString() const; - - // Sender SSRC. - uint32_t ssrc = 0; - - // RTP header extensions used for the sent stream. - std::vector extensions; - - // RTCP CNAME, see RFC 3550. - std::string c_name; - } rtp; - - // Transport for outgoing packets. The transport is expected to exist for - // the entire life of the AudioSendStream and is owned by the API client. - Transport* send_transport = nullptr; - - // Underlying VoiceEngine handle, used to map AudioSendStream to lower-level - // components. - // TODO(solenberg): Remove when VoiceEngine channels are created outside - // of Call. - int voe_channel_id = -1; - - // Ownership of the encoder object is transferred to Call when the config is - // passed to Call::CreateAudioSendStream(). - // TODO(solenberg): Implement, once we configure codecs through the new API. - // std::unique_ptr encoder; - int cng_payload_type = -1; // pt, or -1 to disable Comfort Noise Generator. - int red_payload_type = -1; // pt, or -1 to disable REDundant coding. - }; - - // Starts stream activity. - // When a stream is active, it can receive, process and deliver packets. - virtual void Start() = 0; - // Stops stream activity. - // When a stream is stopped, it can't receive, process or deliver packets. - virtual void Stop() = 0; - - // TODO(solenberg): Make payload_type a config property instead. - virtual bool SendTelephoneEvent(int payload_type, int event, - int duration_ms) = 0; - virtual Stats GetStats() const = 0; - - protected: - virtual ~AudioSendStream() {} -}; -} // namespace webrtc - -#endif // WEBRTC_AUDIO_SEND_STREAM_H_ diff --git a/include/webrtc/audio_state.h b/include/webrtc/audio_state.h deleted file mode 100644 index fa5784c..0000000 --- a/include/webrtc/audio_state.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#ifndef WEBRTC_AUDIO_STATE_H_ -#define WEBRTC_AUDIO_STATE_H_ - -#include "webrtc/base/refcount.h" -#include "webrtc/base/scoped_ref_ptr.h" - -namespace webrtc { - -class AudioDeviceModule; -class VoiceEngine; - -// WORK IN PROGRESS -// This class is under development and is not yet intended for for use outside -// of WebRtc/Libjingle. Please use the VoiceEngine API instead. -// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4690 - -// AudioState holds the state which must be shared between multiple instances of -// webrtc::Call for audio processing purposes. -class AudioState : public rtc::RefCountInterface { - public: - struct Config { - // VoiceEngine used for audio streams and audio/video synchronization. - // AudioState will tickle the VoE refcount to keep it alive for as long as - // the AudioState itself. - VoiceEngine* voice_engine = nullptr; - - // The AudioDeviceModule associated with the Calls. - AudioDeviceModule* audio_device_module = nullptr; - }; - - // TODO(solenberg): Replace scoped_refptr with shared_ptr once we can use it. - static rtc::scoped_refptr Create( - const AudioState::Config& config); - - virtual ~AudioState() {} -}; -} // namespace webrtc - -#endif // WEBRTC_AUDIO_STATE_H_ diff --git a/include/webrtc/base/array_view.h b/include/webrtc/base/array_view.h index a7ca66c..aa73ef7 100644 --- a/include/webrtc/base/array_view.h +++ b/include/webrtc/base/array_view.h @@ -12,6 +12,7 @@ #define WEBRTC_BASE_ARRAY_VIEW_H_ #include "webrtc/base/checks.h" +#include "webrtc/base/type_traits.h" namespace rtc { @@ -56,6 +57,7 @@ namespace rtc { // Contains17(arr); // C array // Contains17(arr); // std::vector // Contains17(rtc::ArrayView(arr, size)); // pointer + size +// Contains17(nullptr); // nullptr -> empty ArrayView // ... // // One important point is that ArrayView and ArrayView are @@ -71,8 +73,12 @@ namespace rtc { template class ArrayView final { public: + using value_type = T; + using const_iterator = const T*; + // Construct an empty ArrayView. ArrayView() : ArrayView(static_cast(nullptr), 0) {} + ArrayView(std::nullptr_t) : ArrayView() {} // Construct an ArrayView for a (pointer,size) pair. template @@ -93,7 +99,9 @@ class ArrayView final { // or ArrayView, const std::vector to ArrayView, and // rtc::Buffer to ArrayView (with the same const behavior as // std::vector). - template + template < + typename U, + typename std::enable_if::value>::type* = nullptr> ArrayView(U& u) : ArrayView(u.data(), u.size()) {} // Indexing, size, and iteration. These allow mutation even if the ArrayView @@ -112,6 +120,13 @@ class ArrayView final { const T* cbegin() const { return data_; } const T* cend() const { return data_ + size_; } + ArrayView subview(size_t offset, size_t size) const { + if (offset >= size_) + return ArrayView(); + return ArrayView(data_ + offset, std::min(size, size_ - offset)); + } + ArrayView subview(size_t offset) const { return subview(offset, size_); } + // Comparing two ArrayViews compares their (pointer,size) pairs; it does // *not* dereference the pointers. friend bool operator==(const ArrayView& a, const ArrayView& b) { @@ -128,6 +143,11 @@ class ArrayView final { size_t size_; }; +template +inline ArrayView MakeArrayView(T* data, size_t size) { + return ArrayView(data, size); +} + } // namespace rtc #endif // WEBRTC_BASE_ARRAY_VIEW_H_ diff --git a/include/webrtc/base/asyncfile.h b/include/webrtc/base/asyncfile.h deleted file mode 100644 index dd46766..0000000 --- a/include/webrtc/base/asyncfile.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_ASYNCFILE_H__ -#define WEBRTC_BASE_ASYNCFILE_H__ - -#include "webrtc/base/sigslot.h" - -namespace rtc { - -// Provides the ability to perform file I/O asynchronously. -// TODO: Create a common base class with AsyncSocket. -class AsyncFile { - public: - AsyncFile(); - virtual ~AsyncFile(); - - // Determines whether the file will receive read events. - virtual bool readable() = 0; - virtual void set_readable(bool value) = 0; - - // Determines whether the file will receive write events. - virtual bool writable() = 0; - virtual void set_writable(bool value) = 0; - - sigslot::signal1 SignalReadEvent; - sigslot::signal1 SignalWriteEvent; - sigslot::signal2 SignalCloseEvent; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_ASYNCFILE_H__ diff --git a/include/webrtc/base/asynchttprequest.h b/include/webrtc/base/asynchttprequest.h deleted file mode 100644 index 310d82e..0000000 --- a/include/webrtc/base/asynchttprequest.h +++ /dev/null @@ -1,2 +0,0 @@ -// TODO(pthatcher): Remove this file once chromium's GYP file doesn't -// refer to it. diff --git a/include/webrtc/base/asyncinvoker-inl.h b/include/webrtc/base/asyncinvoker-inl.h index f615f83..bce68d9 100644 --- a/include/webrtc/base/asyncinvoker-inl.h +++ b/include/webrtc/base/asyncinvoker-inl.h @@ -11,12 +11,11 @@ #ifndef WEBRTC_BASE_ASYNCINVOKER_INL_H_ #define WEBRTC_BASE_ASYNCINVOKER_INL_H_ +#include "webrtc/base/atomicops.h" #include "webrtc/base/bind.h" #include "webrtc/base/callback.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/messagehandler.h" -#include "webrtc/base/refcount.h" -#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" @@ -25,23 +24,26 @@ namespace rtc { class AsyncInvoker; // Helper class for AsyncInvoker. Runs a task and triggers a callback -// on the calling thread if necessary. Instances are ref-counted so their -// lifetime can be independent of AsyncInvoker. -class AsyncClosure : public RefCountInterface { +// on the calling thread if necessary. +class AsyncClosure { public: + explicit AsyncClosure(AsyncInvoker* invoker) : invoker_(invoker) {} + virtual ~AsyncClosure(); // Runs the asynchronous task, and triggers a callback to the calling // thread if needed. Should be called from the target thread. virtual void Execute() = 0; + protected: - ~AsyncClosure() override {} + AsyncInvoker* invoker_; }; // Simple closure that doesn't trigger a callback for the calling thread. template class FireAndForgetAsyncClosure : public AsyncClosure { public: - explicit FireAndForgetAsyncClosure(const FunctorT& functor) - : functor_(functor) {} + explicit FireAndForgetAsyncClosure(AsyncInvoker* invoker, + const FunctorT& functor) + : AsyncClosure(invoker), functor_(functor) {} virtual void Execute() { functor_(); } @@ -58,18 +60,20 @@ class NotifyingAsyncClosureBase : public AsyncClosure, ~NotifyingAsyncClosureBase() override; protected: - NotifyingAsyncClosureBase(AsyncInvoker* invoker, Thread* calling_thread); + NotifyingAsyncClosureBase(AsyncInvoker* invoker, + const Location& callback_posted_from, + Thread* calling_thread); void TriggerCallback(); void SetCallback(const Callback0& callback) { CritScope cs(&crit_); callback_ = callback; } - bool CallbackCanceled() const { return calling_thread_ == NULL; } + bool CallbackCanceled() const { return calling_thread_ == nullptr; } private: + Location callback_posted_from_; Callback0 callback_; CriticalSection crit_; - AsyncInvoker* invoker_; Thread* calling_thread_; void CancelCallback(); @@ -80,14 +84,17 @@ template class NotifyingAsyncClosure : public NotifyingAsyncClosureBase { public: NotifyingAsyncClosure(AsyncInvoker* invoker, + const Location& callback_posted_from, Thread* calling_thread, const FunctorT& functor, void (HostT::*callback)(ReturnT), HostT* callback_host) - : NotifyingAsyncClosureBase(invoker, calling_thread), - functor_(functor), - callback_(callback), - callback_host_(callback_host) {} + : NotifyingAsyncClosureBase(invoker, + callback_posted_from, + calling_thread), + functor_(functor), + callback_(callback), + callback_host_(callback_host) {} virtual void Execute() { ReturnT result = functor_(); if (!CallbackCanceled()) { @@ -108,11 +115,14 @@ class NotifyingAsyncClosure : public NotifyingAsyncClosureBase { public: NotifyingAsyncClosure(AsyncInvoker* invoker, + const Location& callback_posted_from, Thread* calling_thread, const FunctorT& functor, void (HostT::*callback)(), HostT* callback_host) - : NotifyingAsyncClosureBase(invoker, calling_thread), + : NotifyingAsyncClosureBase(invoker, + callback_posted_from, + calling_thread), functor_(functor) { SetCallback(Callback0(Bind(callback, callback_host))); } diff --git a/include/webrtc/base/asyncinvoker.h b/include/webrtc/base/asyncinvoker.h index 76e5d92..ed61243 100644 --- a/include/webrtc/base/asyncinvoker.h +++ b/include/webrtc/base/asyncinvoker.h @@ -11,11 +11,14 @@ #ifndef WEBRTC_BASE_ASYNCINVOKER_H_ #define WEBRTC_BASE_ASYNCINVOKER_H_ +#include +#include + #include "webrtc/base/asyncinvoker-inl.h" #include "webrtc/base/bind.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/event.h" #include "webrtc/base/sigslot.h" -#include "webrtc/base/scopedptrcollection.h" #include "webrtc/base/thread.h" namespace rtc { @@ -45,13 +48,13 @@ namespace rtc { // public: // void FireAsyncTaskWithResult(Thread* thread, int x) { // // Specify a callback to get the result upon completion. -// invoker_.AsyncInvoke( +// invoker_.AsyncInvoke(RTC_FROM_HERE, // thread, Bind(&MyClass::AsyncTaskWithResult, this, x), // &MyClass::OnTaskComplete, this); // } // void FireAnotherAsyncTask(Thread* thread) { // // No callback specified means fire-and-forget. -// invoker_.AsyncInvoke( +// invoker_.AsyncInvoke(RTC_FROM_HERE, // thread, Bind(&MyClass::AnotherAsyncTask, this)); // // private: @@ -75,49 +78,63 @@ class AsyncInvoker : public MessageHandler { // Call |functor| asynchronously on |thread|, with no callback upon // completion. Returns immediately. template - void AsyncInvoke(Thread* thread, const FunctorT& functor, uint32_t id = 0) { - scoped_refptr closure( - new RefCountedObject >(functor)); - DoInvoke(thread, closure, id); + void AsyncInvoke(const Location& posted_from, + Thread* thread, + const FunctorT& functor, + uint32_t id = 0) { + std::unique_ptr closure( + new FireAndForgetAsyncClosure(this, functor)); + DoInvoke(posted_from, thread, std::move(closure), id); } // Call |functor| asynchronously on |thread| with |delay_ms|, with no callback // upon completion. Returns immediately. template - void AsyncInvokeDelayed(Thread* thread, + void AsyncInvokeDelayed(const Location& posted_from, + Thread* thread, const FunctorT& functor, uint32_t delay_ms, uint32_t id = 0) { - scoped_refptr closure( - new RefCountedObject >(functor)); - DoInvokeDelayed(thread, closure, delay_ms, id); + std::unique_ptr closure( + new FireAndForgetAsyncClosure(this, functor)); + DoInvokeDelayed(posted_from, thread, std::move(closure), delay_ms, id); } // Call |functor| asynchronously on |thread|, calling |callback| when done. + // Uses a separate Location for |callback_posted_from| so that the functor + // invoke and the callback invoke can be differentiated. template - void AsyncInvoke(Thread* thread, + void AsyncInvoke(const Location& posted_from, + const Location& callback_posted_from, + Thread* thread, const FunctorT& functor, void (HostT::*callback)(ReturnT), HostT* callback_host, uint32_t id = 0) { - scoped_refptr closure( - new RefCountedObject >( - this, Thread::Current(), functor, callback, callback_host)); - DoInvoke(thread, closure, id); + std::unique_ptr closure( + new NotifyingAsyncClosure( + this, callback_posted_from, Thread::Current(), functor, callback, + callback_host)); + DoInvoke(posted_from, thread, std::move(closure), id); } // Call |functor| asynchronously on |thread|, calling |callback| when done. + // Uses a separate Location for |callback_posted_from| so that the functor + // invoke and the callback invoke can be differentiated. // Overloaded for void return. template - void AsyncInvoke(Thread* thread, + void AsyncInvoke(const Location& posted_from, + const Location& callback_posted_from, + Thread* thread, const FunctorT& functor, void (HostT::*callback)(), HostT* callback_host, uint32_t id = 0) { - scoped_refptr closure( - new RefCountedObject >( - this, Thread::Current(), functor, callback, callback_host)); - DoInvoke(thread, closure, id); + std::unique_ptr closure( + new NotifyingAsyncClosure( + this, callback_posted_from, Thread::Current(), functor, callback, + callback_host)); + DoInvoke(posted_from, thread, std::move(closure), id); } // Synchronously execute on |thread| all outstanding calls we own @@ -132,14 +149,19 @@ class AsyncInvoker : public MessageHandler { private: void OnMessage(Message* msg) override; - void DoInvoke(Thread* thread, - const scoped_refptr& closure, + void DoInvoke(const Location& posted_from, + Thread* thread, + std::unique_ptr closure, uint32_t id); - void DoInvokeDelayed(Thread* thread, - const scoped_refptr& closure, + void DoInvokeDelayed(const Location& posted_from, + Thread* thread, + std::unique_ptr closure, uint32_t delay_ms, uint32_t id); - bool destroying_; + volatile int pending_invocations_ = 0; + Event invocation_complete_; + bool destroying_ = false; + friend class AsyncClosure; RTC_DISALLOW_COPY_AND_ASSIGN(AsyncInvoker); }; @@ -164,55 +186,64 @@ class GuardedAsyncInvoker : public sigslot::has_slots<> { // Call |functor| asynchronously with no callback upon completion. Returns // immediately. Returns false if the thread has died. template - bool AsyncInvoke(const FunctorT& functor, uint32_t id = 0) { + bool AsyncInvoke(const Location& posted_from, + const FunctorT& functor, + uint32_t id = 0) { rtc::CritScope cs(&crit_); if (thread_ == nullptr) return false; - invoker_.AsyncInvoke(thread_, functor, id); + invoker_.AsyncInvoke(posted_from, thread_, functor, id); return true; } // Call |functor| asynchronously with |delay_ms|, with no callback upon // completion. Returns immediately. Returns false if the thread has died. template - bool AsyncInvokeDelayed(const FunctorT& functor, + bool AsyncInvokeDelayed(const Location& posted_from, + const FunctorT& functor, uint32_t delay_ms, uint32_t id = 0) { rtc::CritScope cs(&crit_); if (thread_ == nullptr) return false; - invoker_.AsyncInvokeDelayed(thread_, functor, delay_ms, - id); + invoker_.AsyncInvokeDelayed(posted_from, thread_, + functor, delay_ms, id); return true; } // Call |functor| asynchronously, calling |callback| when done. Returns false // if the thread has died. template - bool AsyncInvoke(const FunctorT& functor, + bool AsyncInvoke(const Location& posted_from, + const Location& callback_posted_from, + const FunctorT& functor, void (HostT::*callback)(ReturnT), HostT* callback_host, uint32_t id = 0) { rtc::CritScope cs(&crit_); if (thread_ == nullptr) return false; - invoker_.AsyncInvoke(thread_, functor, callback, - callback_host, id); + invoker_.AsyncInvoke( + posted_from, callback_posted_from, thread_, functor, callback, + callback_host, id); return true; } // Call |functor| asynchronously calling |callback| when done. Overloaded for // void return. Returns false if the thread has died. template - bool AsyncInvoke(const FunctorT& functor, + bool AsyncInvoke(const Location& posted_from, + const Location& callback_posted_from, + const FunctorT& functor, void (HostT::*callback)(), HostT* callback_host, uint32_t id = 0) { rtc::CritScope cs(&crit_); if (thread_ == nullptr) return false; - invoker_.AsyncInvoke(thread_, functor, callback, - callback_host, id); + invoker_.AsyncInvoke( + posted_from, callback_posted_from, thread_, functor, callback, + callback_host, id); return true; } diff --git a/include/webrtc/base/asyncpacketsocket.h b/include/webrtc/base/asyncpacketsocket.h index f18839e..a540947 100644 --- a/include/webrtc/base/asyncpacketsocket.h +++ b/include/webrtc/base/asyncpacketsocket.h @@ -78,7 +78,7 @@ class AsyncPacketSocket : public sigslot::has_slots<> { AsyncPacketSocket(); ~AsyncPacketSocket() override; - // Returns current local address. Address may be set to NULL if the + // Returns current local address. Address may be set to null if the // socket is not bound yet (GetState() returns STATE_BINDING). virtual SocketAddress GetLocalAddress() const = 0; diff --git a/include/webrtc/base/asyncsocket.h b/include/webrtc/base/asyncsocket.h index 7a859be..40cf1b5 100644 --- a/include/webrtc/base/asyncsocket.h +++ b/include/webrtc/base/asyncsocket.h @@ -11,7 +11,6 @@ #ifndef WEBRTC_BASE_ASYNCSOCKET_H_ #define WEBRTC_BASE_ASYNCSOCKET_H_ -#include "webrtc/base/common.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/socket.h" @@ -43,7 +42,7 @@ class AsyncSocket : public Socket { class AsyncSocketAdapter : public AsyncSocket, public sigslot::has_slots<> { public: - // The adapted socket may explicitly be NULL, and later assigned using Attach. + // The adapted socket may explicitly be null, and later assigned using Attach. // However, subclasses which support detached mode must override any methods // that will be called during the detached period (usually GetState()), to // avoid dereferencing a null pointer. @@ -56,8 +55,11 @@ class AsyncSocketAdapter : public AsyncSocket, public sigslot::has_slots<> { int Connect(const SocketAddress& addr) override; int Send(const void* pv, size_t cb) override; int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override; - int Recv(void* pv, size_t cb) override; - int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override; + int Recv(void* pv, size_t cb, int64_t* timestamp) override; + int RecvFrom(void* pv, + size_t cb, + SocketAddress* paddr, + int64_t* timestamp) override; int Listen(int backlog) override; AsyncSocket* Accept(SocketAddress* paddr) override; int Close() override; diff --git a/include/webrtc/base/asynctcpsocket.h b/include/webrtc/base/asynctcpsocket.h index cd5c104..2e4ff9a 100644 --- a/include/webrtc/base/asynctcpsocket.h +++ b/include/webrtc/base/asynctcpsocket.h @@ -51,7 +51,7 @@ class AsyncTCPSocketBase : public AsyncPacketSocket { protected: // Binds and connects |socket| and creates AsyncTCPSocket for - // it. Takes ownership of |socket|. Returns NULL if bind() or + // it. Takes ownership of |socket|. Returns null if bind() or // connect() fail (|socket| is destroyed in that case). static AsyncSocket* ConnectSocket(AsyncSocket* socket, const SocketAddress& bind_address, @@ -85,7 +85,7 @@ class AsyncTCPSocketBase : public AsyncPacketSocket { class AsyncTCPSocket : public AsyncTCPSocketBase { public: // Binds and connects |socket| and creates AsyncTCPSocket for - // it. Takes ownership of |socket|. Returns NULL if bind() or + // it. Takes ownership of |socket|. Returns null if bind() or // connect() fail (|socket| is destroyed in that case). static AsyncTCPSocket* Create(AsyncSocket* socket, const SocketAddress& bind_address, diff --git a/include/webrtc/base/asyncudpsocket.h b/include/webrtc/base/asyncudpsocket.h index aa6a904..e5535e0 100644 --- a/include/webrtc/base/asyncudpsocket.h +++ b/include/webrtc/base/asyncudpsocket.h @@ -23,7 +23,7 @@ namespace rtc { class AsyncUDPSocket : public AsyncPacketSocket { public: // Binds |socket| and creates AsyncUDPSocket for it. Takes ownership - // of |socket|. Returns NULL if bind() fails (|socket| is destroyed + // of |socket|. Returns null if bind() fails (|socket| is destroyed // in that case). static AsyncUDPSocket* Create(AsyncSocket* socket, const SocketAddress& bind_address); diff --git a/include/webrtc/base/autodetectproxy.h b/include/webrtc/base/autodetectproxy.h deleted file mode 100644 index 1bd523f..0000000 --- a/include/webrtc/base/autodetectproxy.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_AUTODETECTPROXY_H_ -#define WEBRTC_BASE_AUTODETECTPROXY_H_ - -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/cryptstring.h" -#include "webrtc/base/proxydetect.h" -#include "webrtc/base/proxyinfo.h" -#include "webrtc/base/signalthread.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// AutoDetectProxy -/////////////////////////////////////////////////////////////////////////////// - -class AsyncResolverInterface; -class AsyncSocket; - -class AutoDetectProxy : public SignalThread { - public: - explicit AutoDetectProxy(const std::string& user_agent); - - const ProxyInfo& proxy() const { return proxy_; } - - void set_server_url(const std::string& url) { - server_url_ = url; - } - void set_proxy(const SocketAddress& proxy) { - proxy_.type = PROXY_UNKNOWN; - proxy_.address = proxy; - } - void set_auth_info(bool use_auth, const std::string& username, - const CryptString& password) { - if (use_auth) { - proxy_.username = username; - proxy_.password = password; - } - } - // Default implementation of GetProxySettingsForUrl. Override for special - // implementation. - virtual bool GetProxyForUrl(const char* agent, - const char* url, - rtc::ProxyInfo* proxy); - enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE, - MSG_UNRESOLVABLE, - ADP_MSG_FIRST_AVAILABLE}; - - protected: - ~AutoDetectProxy() override; - - // SignalThread Interface - void DoWork() override; - void OnMessage(Message* msg) override; - - void Next(); - void Complete(ProxyType type); - - void OnConnectEvent(AsyncSocket * socket); - void OnReadEvent(AsyncSocket * socket); - void OnCloseEvent(AsyncSocket * socket, int error); - void OnResolveResult(AsyncResolverInterface* resolver); - bool DoConnect(); - - private: - std::string agent_; - std::string server_url_; - ProxyInfo proxy_; - AsyncResolverInterface* resolver_; - AsyncSocket* socket_; - int next_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AutoDetectProxy); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_AUTODETECTPROXY_H_ diff --git a/include/webrtc/base/bandwidthsmoother.h b/include/webrtc/base/bandwidthsmoother.h deleted file mode 100644 index eae565e..0000000 --- a/include/webrtc/base/bandwidthsmoother.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_BANDWIDTHSMOOTHER_H_ -#define WEBRTC_BASE_BANDWIDTHSMOOTHER_H_ - -#include "webrtc/base/rollingaccumulator.h" -#include "webrtc/base/timeutils.h" - -namespace rtc { - -// The purpose of BandwidthSmoother is to smooth out bandwidth -// estimations so that 'trstate' messages can be triggered when we -// are "sure" there is sufficient bandwidth. To avoid frequent fluctuations, -// we take a slightly pessimistic view of our bandwidth. We only increase -// our estimation when we have sampled bandwidth measurements of values -// at least as large as the current estimation * percent_increase -// for at least time_between_increase time. If a sampled bandwidth -// is less than our current estimation we immediately decrease our estimation -// to that sampled value. -// We retain the initial bandwidth guess as our current bandwidth estimation -// until we have received (min_sample_count_percent * samples_count_to_average) -// number of samples. Min_sample_count_percent must be in range [0, 1]. -class BandwidthSmoother { - public: - BandwidthSmoother(int initial_bandwidth_guess, - uint32_t time_between_increase, - double percent_increase, - size_t samples_count_to_average, - double min_sample_count_percent); - ~BandwidthSmoother(); - - // Samples a new bandwidth measurement. - // bandwidth is expected to be non-negative. - // returns true if the bandwidth estimation changed - bool Sample(uint32_t sample_time, int bandwidth); - - int get_bandwidth_estimation() const { - return bandwidth_estimation_; - } - - private: - uint32_t time_between_increase_; - double percent_increase_; - uint32_t time_at_last_change_; - int bandwidth_estimation_; - RollingAccumulator accumulator_; - double min_sample_count_percent_; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_BANDWIDTHSMOOTHER_H_ diff --git a/include/webrtc/base/base64.h b/include/webrtc/base/base64.h index d5a7dd8..eba3cc0 100644 --- a/include/webrtc/base/base64.h +++ b/include/webrtc/base/base64.h @@ -17,29 +17,28 @@ namespace rtc { -class Base64 -{ -public: +class Base64 { + public: enum DecodeOption { - DO_PARSE_STRICT = 1, // Parse only base64 characters - DO_PARSE_WHITE = 2, // Parse only base64 and whitespace characters - DO_PARSE_ANY = 3, // Parse all characters - DO_PARSE_MASK = 3, + DO_PARSE_STRICT = 1, // Parse only base64 characters + DO_PARSE_WHITE = 2, // Parse only base64 and whitespace characters + DO_PARSE_ANY = 3, // Parse all characters + DO_PARSE_MASK = 3, - DO_PAD_YES = 4, // Padding is required - DO_PAD_ANY = 8, // Padding is optional - DO_PAD_NO = 12, // Padding is disallowed - DO_PAD_MASK = 12, + DO_PAD_YES = 4, // Padding is required + DO_PAD_ANY = 8, // Padding is optional + DO_PAD_NO = 12, // Padding is disallowed + DO_PAD_MASK = 12, - DO_TERM_BUFFER = 16, // Must termiante at end of buffer - DO_TERM_CHAR = 32, // May terminate at any character boundary - DO_TERM_ANY = 48, // May terminate at a sub-character bit offset - DO_TERM_MASK = 48, + DO_TERM_BUFFER = 16, // Must termiante at end of buffer + DO_TERM_CHAR = 32, // May terminate at any character boundary + DO_TERM_ANY = 48, // May terminate at a sub-character bit offset + DO_TERM_MASK = 48, // Strictest interpretation DO_STRICT = DO_PARSE_STRICT | DO_PAD_YES | DO_TERM_BUFFER, - DO_LAX = DO_PARSE_ANY | DO_PAD_ANY | DO_TERM_CHAR, + DO_LAX = DO_PARSE_ANY | DO_PAD_ANY | DO_TERM_CHAR, }; typedef int DecodeFlags; @@ -57,12 +56,24 @@ class Base64 // encoded characters. static bool IsBase64Encoded(const std::string& str); - static void EncodeFromArray(const void* data, size_t len, + static void EncodeFromArray(const void* data, + size_t len, std::string* result); - static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags, - std::string* result, size_t* data_used); - static bool DecodeFromArray(const char* data, size_t len, DecodeFlags flags, - std::vector* result, size_t* data_used); + static bool DecodeFromArray(const char* data, + size_t len, + DecodeFlags flags, + std::string* result, + size_t* data_used); + static bool DecodeFromArray(const char* data, + size_t len, + DecodeFlags flags, + std::vector* result, + size_t* data_used); + static bool DecodeFromArray(const char* data, + size_t len, + DecodeFlags flags, + std::vector* result, + size_t* data_used); // Convenience Methods static inline std::string Encode(const std::string& data) { @@ -72,33 +83,41 @@ class Base64 } static inline std::string Decode(const std::string& data, DecodeFlags flags) { std::string result; - DecodeFromArray(data.data(), data.size(), flags, &result, NULL); + DecodeFromArray(data.data(), data.size(), flags, &result, nullptr); return result; } - static inline bool Decode(const std::string& data, DecodeFlags flags, - std::string* result, size_t* data_used) - { + static inline bool Decode(const std::string& data, + DecodeFlags flags, + std::string* result, + size_t* data_used) { return DecodeFromArray(data.data(), data.size(), flags, result, data_used); } - static inline bool Decode(const std::string& data, DecodeFlags flags, - std::vector* result, size_t* data_used) - { + static inline bool Decode(const std::string& data, + DecodeFlags flags, + std::vector* result, + size_t* data_used) { return DecodeFromArray(data.data(), data.size(), flags, result, data_used); } -private: + private: static const char Base64Table[]; static const unsigned char DecodeTable[]; - static size_t GetNextQuantum(DecodeFlags parse_flags, bool illegal_pads, - const char* data, size_t len, size_t* dpos, - unsigned char qbuf[4], bool* padded); - template - static bool DecodeFromArrayTemplate(const char* data, size_t len, - DecodeFlags flags, T* result, + static size_t GetNextQuantum(DecodeFlags parse_flags, + bool illegal_pads, + const char* data, + size_t len, + size_t* dpos, + unsigned char qbuf[4], + bool* padded); + template + static bool DecodeFromArrayTemplate(const char* data, + size_t len, + DecodeFlags flags, + T* result, size_t* data_used); }; -} // namespace rtc +} // namespace rtc -#endif // WEBRTC_BASE_BASE64_H__ +#endif // WEBRTC_BASE_BASE64_H__ diff --git a/include/webrtc/base/basictypes.h b/include/webrtc/base/basictypes.h index 6ca09d0..87dcdc6 100644 --- a/include/webrtc/base/basictypes.h +++ b/include/webrtc/base/basictypes.h @@ -31,7 +31,7 @@ #if !defined(RTC_ARCH_CPU_BIG_ENDIAN) && !defined(RTC_ARCH_CPU_LITTLE_ENDIAN) // x86, arm or GCC provided __BYTE_ORDER__ macros -#if CPU_X86 || CPU_ARM || \ +#if defined(CPU_X86) || defined(CPU_ARM) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define RTC_ARCH_CPU_LITTLE_ENDIAN #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ diff --git a/include/webrtc/base/bind.h b/include/webrtc/base/bind.h index b50afc2..94eb164 100644 --- a/include/webrtc/base/bind.h +++ b/include/webrtc/base/bind.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py bind.h.pump -// DO NOT EDIT BY HAND!!! - /* * Copyright 2012 The WebRTC Project Authors. All rights reserved. * @@ -12,9 +8,6 @@ * be found in the AUTHORS file in the root of the source tree. */ -// To generate bind.h from bind.h.pump, execute: -// /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump - // Bind() is an overloaded function that converts method calls into function // objects (aka functors). The method object is captured as a scoped_refptr<> if // possible, and as a raw pointer otherwise. Any arguments to the method are @@ -24,6 +17,10 @@ // ref-counted method object or any arguments passed by pointer, and calling the // functor with a destroyed object will surely do bad things. // +// To prevent the method object from being captured as a scoped_refptr<>, you +// can use Unretained. But this should only be done when absolutely necessary, +// and when the caller knows the extra reference isn't needed. +// // Example usage: // struct Foo { // int Test1() { return 42; } @@ -48,7 +45,7 @@ // void Test() {} // void BindThis() { // // The functor passed to AsyncInvoke() will keep this object alive. -// invoker.AsyncInvoke(rtc::Bind(&Bar::Test, this)); +// invoker.AsyncInvoke(RTC_FROM_HERE,rtc::Bind(&Bar::Test, this)); // } // }; // @@ -64,6 +61,9 @@ #ifndef WEBRTC_BASE_BIND_H_ #define WEBRTC_BASE_BIND_H_ +#include +#include + #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/template_util.h" @@ -129,1408 +129,150 @@ struct PointerType { T*>::type type; }; -} // namespace detail - -template -class MethodFunctor0 { - public: - MethodFunctor0(MethodT method, ObjectT* object) - : method_(method), object_(object) {} - R operator()() const { - return (object_->*method_)(); } - private: - MethodT method_; - typename detail::PointerType::type object_; -}; - -template -class Functor0 { - public: - explicit Functor0(const FunctorT& functor) - : functor_(functor) {} - R operator()() const { - return functor_(); } - private: - FunctorT functor_; -}; - - -#define FP_T(x) R (ObjectT::*x)() - -template -MethodFunctor0 -Bind(FP_T(method), ObjectT* object) { - return MethodFunctor0( - method, object); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)() const - -template -MethodFunctor0 -Bind(FP_T(method), const ObjectT* object) { - return MethodFunctor0( - method, object); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)() - -template -MethodFunctor0 -Bind(FP_T(method), const scoped_refptr& object) { - return MethodFunctor0( - method, object.get()); -} - -#undef FP_T -#define FP_T(x) R (*x)() - -template -Functor0 -Bind(FP_T(function)) { - return Functor0( - function); -} - -#undef FP_T - -template -class MethodFunctor1 { - public: - MethodFunctor1(MethodT method, ObjectT* object, - P1 p1) - : method_(method), object_(object), - p1_(p1) {} - R operator()() const { - return (object_->*method_)(p1_); } - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; -}; - -template -class Functor1 { - public: - Functor1(const FunctorT& functor, P1 p1) - : functor_(functor), - p1_(p1) {} - R operator()() const { - return functor_(p1_); } - private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; -}; - - -#define FP_T(x) R (ObjectT::*x)(P1) - -template -MethodFunctor1 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1) { - return MethodFunctor1( - method, object, p1); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1) const - -template -MethodFunctor1 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1) { - return MethodFunctor1( - method, object, p1); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1) - -template -MethodFunctor1 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1) { - return MethodFunctor1( - method, object.get(), p1); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1) - -template -Functor1 -Bind(FP_T(function), - typename detail::identity::type p1) { - return Functor1( - function, p1); -} - -#undef FP_T - -template -class MethodFunctor2 { - public: - MethodFunctor2(MethodT method, ObjectT* object, - P1 p1, - P2 p2) - : method_(method), object_(object), - p1_(p1), - p2_(p2) {} - R operator()() const { - return (object_->*method_)(p1_, p2_); } - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; -}; - -template -class Functor2 { - public: - Functor2(const FunctorT& functor, P1 p1, P2 p2) - : functor_(functor), - p1_(p1), - p2_(p2) {} - R operator()() const { - return functor_(p1_, p2_); } - private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; -}; - - -#define FP_T(x) R (ObjectT::*x)(P1, P2) - -template -MethodFunctor2 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2) { - return MethodFunctor2( - method, object, p1, p2); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2) const - -template -MethodFunctor2 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2) { - return MethodFunctor2( - method, object, p1, p2); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2) - -template -MethodFunctor2 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2) { - return MethodFunctor2( - method, object.get(), p1, p2); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2) - -template -Functor2 -Bind(FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2) { - return Functor2( - function, p1, p2); -} - -#undef FP_T - -template -class MethodFunctor3 { +template +class UnretainedWrapper { public: - MethodFunctor3(MethodT method, ObjectT* object, - P1 p1, - P2 p2, - P3 p3) - : method_(method), object_(object), - p1_(p1), - p2_(p2), - p3_(p3) {} - R operator()() const { - return (object_->*method_)(p1_, p2_, p3_); } - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; -}; + explicit UnretainedWrapper(T* o) : ptr_(o) {} + T* get() const { return ptr_; } -template -class Functor3 { - public: - Functor3(const FunctorT& functor, P1 p1, P2 p2, P3 p3) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3) {} - R operator()() const { - return functor_(p1_, p2_, p3_); } private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; + T* ptr_; }; +} // namespace detail -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3) - -template -MethodFunctor3 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3) { - return MethodFunctor3( - method, object, p1, p2, p3); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3) const - -template -MethodFunctor3 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3) { - return MethodFunctor3( - method, object, p1, p2, p3); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3) - -template -MethodFunctor3 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3) { - return MethodFunctor3( - method, object.get(), p1, p2, p3); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3) - -template -Functor3 -Bind(FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3) { - return Functor3( - function, p1, p2, p3); +template +static inline detail::UnretainedWrapper Unretained(T* o) { + return detail::UnretainedWrapper(o); } -#undef FP_T - -template -class MethodFunctor4 { +template +class MethodFunctor { public: - MethodFunctor4(MethodT method, ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4) - : method_(method), object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4) {} + MethodFunctor(MethodT method, ObjectT* object, Args... args) + : method_(method), object_(object), args_(args...) {} R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_); } - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; -}; + return CallMethod(typename sequence_generator::type()); + } -template -class Functor4 { - public: - Functor4(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4) {} - R operator()() const { - return functor_(p1_, p2_, p3_, p4_); } private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; -}; - - -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4) - -template -MethodFunctor4 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4) { - return MethodFunctor4( - method, object, p1, p2, p3, p4); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4) const - -template -MethodFunctor4 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4) { - return MethodFunctor4( - method, object, p1, p2, p3, p4); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4) - -template -MethodFunctor4 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4) { - return MethodFunctor4( - method, object.get(), p1, p2, p3, p4); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4) - -template -Functor4 -Bind(FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4) { - return Functor4( - function, p1, p2, p3, p4); -} - -#undef FP_T + // Use sequence_generator (see template_util.h) to expand a MethodFunctor + // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for + // instance. + template + R CallMethod(sequence) const { + return (object_->*method_)(std::get(args_)...); + } -template -class MethodFunctor5 { - public: - MethodFunctor5(MethodT method, ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5) - : method_(method), object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5) {} - R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_, p5_); } - private: MethodT method_; typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; -}; - -template -class Functor5 { - public: - Functor5(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5) {} - R operator()() const { - return functor_(p1_, p2_, p3_, p4_, p5_); } - private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; + typename std::tuple::type...> args_; }; - -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5) - -template -MethodFunctor5 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5) { - return MethodFunctor5( - method, object, p1, p2, p3, p4, p5); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5) const - -template -MethodFunctor5 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5) { - return MethodFunctor5( - method, object, p1, p2, p3, p4, p5); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5) - -template -MethodFunctor5 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5) { - return MethodFunctor5( - method, object.get(), p1, p2, p3, p4, p5); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4, P5) - -template -Functor5 -Bind(FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5) { - return Functor5( - function, p1, p2, p3, p4, p5); -} - -#undef FP_T - -template -class MethodFunctor6 { +template +class UnretainedMethodFunctor { public: - MethodFunctor6(MethodT method, ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6) - : method_(method), object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6) {} + UnretainedMethodFunctor(MethodT method, + detail::UnretainedWrapper object, + Args... args) + : method_(method), object_(object.get()), args_(args...) {} R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_); } - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; -}; + return CallMethod(typename sequence_generator::type()); + } -template -class Functor6 { - public: - Functor6(const FunctorT& functor, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6) {} - R operator()() const { - return functor_(p1_, p2_, p3_, p4_, p5_, p6_); } private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; -}; - - -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6) - -template -MethodFunctor6 -Bind(FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6) { - return MethodFunctor6( - method, object, p1, p2, p3, p4, p5, p6); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6) const - -template -MethodFunctor6 -Bind(FP_T(method), const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6) { - return MethodFunctor6( - method, object, p1, p2, p3, p4, p5, p6); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6) - -template -MethodFunctor6 -Bind(FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6) { - return MethodFunctor6( - method, object.get(), p1, p2, p3, p4, p5, p6); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6) - -template -Functor6 -Bind(FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6) { - return Functor6( - function, p1, p2, p3, p4, p5, p6); -} - -#undef FP_T - -template -class MethodFunctor7 { - public: - MethodFunctor7(MethodT method, - ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7) - : method_(method), - object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7) {} - R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_); + // Use sequence_generator (see template_util.h) to expand an + // UnretainedMethodFunctor with 2 arguments to (std::get<0>(args_), + // std::get<1>(args_)), for instance. + template + R CallMethod(sequence) const { + return (object_->*method_)(std::get(args_)...); } - private: MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; + ObjectT* object_; + typename std::tuple::type...> args_; }; -template -class Functor7 { +template +class Functor { public: - Functor7(const FunctorT& functor, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7) {} - R operator()() const { return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_); } - - private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; -}; - -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) - -template -MethodFunctor7 Bind( - FP_T(method), - ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7) { - return MethodFunctor7( - method, object, p1, p2, p3, p4, p5, p6, p7); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) const - -template -MethodFunctor7 Bind( - FP_T(method), - const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7) { - return MethodFunctor7(method, object, p1, p2, p3, p4, p5, p6, p7); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7) - -template -MethodFunctor7 Bind( - FP_T(method), - const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7) { - return MethodFunctor7( - method, object.get(), p1, p2, p3, p4, p5, p6, p7); -} - -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7) - -template -Functor7 Bind( - FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7) { - return Functor7( - function, p1, p2, p3, p4, p5, p6, p7); -} - -#undef FP_T - -template -class MethodFunctor8 { - public: - MethodFunctor8(MethodT method, - ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7, - P8 p8) - : method_(method), - object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7), - p8_(p8) {} + Functor(const FunctorT& functor, Args... args) + : functor_(functor), args_(args...) {} R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_); + return CallFunction(typename sequence_generator::type()); } private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; - typename rtc::remove_reference::type p8_; -}; - -template -class Functor8 { - public: - Functor8(const FunctorT& functor, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7, - P8 p8) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7), - p8_(p8) {} - R operator()() const { - return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_); + // Use sequence_generator (see template_util.h) to expand a Functor + // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for + // instance. + template + R CallFunction(sequence) const { + return functor_(std::get(args_)...); } - private: FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; - typename rtc::remove_reference::type p8_; + typename std::tuple::type...> args_; }; -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) +#define FP_T(x) R (ObjectT::*x)(Args...) -template -MethodFunctor8 Bind( +template +MethodFunctor Bind( FP_T(method), ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8) { - return MethodFunctor8(method, object, p1, p2, p3, p4, p5, p6, p7, p8); + typename detail::identity::type... args) { + return MethodFunctor(method, object, + args...); } -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) const - -template -MethodFunctor8 -Bind(FP_T(method), - const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8) { - return MethodFunctor8(method, object, p1, p2, p3, p4, p5, p6, p7, p8); -} - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8) - -template -MethodFunctor8 Bind( +template +MethodFunctor Bind( FP_T(method), const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8) { - return MethodFunctor8(method, object.get(), p1, p2, p3, p4, p5, p6, p7, - p8); + typename detail::identity::type... args) { + return MethodFunctor(method, object.get(), + args...); } -#undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8) - -template -Functor8 Bind( - FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8) { - return Functor8( - function, p1, p2, p3, p4, p5, p6, p7, p8); -} - -#undef FP_T - -template -class MethodFunctor9 { - public: - MethodFunctor9(MethodT method, - ObjectT* object, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7, - P8 p8, - P9 p9) - : method_(method), - object_(object), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7), - p8_(p8), - p9_(p9) {} - R operator()() const { - return (object_->*method_)(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_); - } - - private: - MethodT method_; - typename detail::PointerType::type object_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; - typename rtc::remove_reference::type p8_; - typename rtc::remove_reference::type p9_; -}; - -template -class Functor9 { - public: - Functor9(const FunctorT& functor, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7, - P8 p8, - P9 p9) - : functor_(functor), - p1_(p1), - p2_(p2), - p3_(p3), - p4_(p4), - p5_(p5), - p6_(p6), - p7_(p7), - p8_(p8), - p9_(p9) {} - R operator()() const { - return functor_(p1_, p2_, p3_, p4_, p5_, p6_, p7_, p8_, p9_); - } - - private: - FunctorT functor_; - typename rtc::remove_reference::type p1_; - typename rtc::remove_reference::type p2_; - typename rtc::remove_reference::type p3_; - typename rtc::remove_reference::type p4_; - typename rtc::remove_reference::type p5_; - typename rtc::remove_reference::type p6_; - typename rtc::remove_reference::type p7_; - typename rtc::remove_reference::type p8_; - typename rtc::remove_reference::type p9_; -}; - -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) - -template -MethodFunctor9 -Bind(FP_T(method), - ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8, - typename detail::identity::type p9) { - return MethodFunctor9(method, object, p1, p2, p3, p4, p5, p6, p7, p8, - p9); +template +UnretainedMethodFunctor Bind( + FP_T(method), + detail::UnretainedWrapper object, + typename detail::identity::type... args) { + return UnretainedMethodFunctor( + method, object, args...); } #undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) const +#define FP_T(x) R (ObjectT::*x)(Args...) const -template -MethodFunctor9 -Bind(FP_T(method), - const ObjectT* object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8, - typename detail::identity::type p9) { - return MethodFunctor9(method, object, p1, p2, p3, p4, p5, p6, p7, - p8, p9); +template +MethodFunctor Bind( + FP_T(method), + const ObjectT* object, + typename detail::identity::type... args) { + return MethodFunctor(method, object, + args...); } - -#undef FP_T -#define FP_T(x) R (ObjectT::*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) - -template -MethodFunctor9 -Bind(FP_T(method), - const scoped_refptr& object, - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8, - typename detail::identity::type p9) { - return MethodFunctor9(method, object.get(), p1, p2, p3, p4, p5, p6, - p7, p8, p9); +template +UnretainedMethodFunctor Bind( + FP_T(method), + detail::UnretainedWrapper object, + typename detail::identity::type... args) { + return UnretainedMethodFunctor( + method, object, args...); } #undef FP_T -#define FP_T(x) R (*x)(P1, P2, P3, P4, P5, P6, P7, P8, P9) +#define FP_T(x) R (*x)(Args...) -template -Functor9 Bind( +template +Functor Bind( FP_T(function), - typename detail::identity::type p1, - typename detail::identity::type p2, - typename detail::identity::type p3, - typename detail::identity::type p4, - typename detail::identity::type p5, - typename detail::identity::type p6, - typename detail::identity::type p7, - typename detail::identity::type p8, - typename detail::identity::type p9) { - return Functor9( - function, p1, p2, p3, p4, p5, p6, p7, p8, p9); + typename detail::identity::type... args) { + return Functor(function, args...); } #undef FP_T diff --git a/include/webrtc/base/bitbuffer.h b/include/webrtc/base/bitbuffer.h index 8ea044e..b2baaa9 100644 --- a/include/webrtc/base/bitbuffer.h +++ b/include/webrtc/base/bitbuffer.h @@ -109,6 +109,10 @@ class BitBufferWriter : public BitBuffer { // Writes the exponential golomb encoded version of the supplied value. // Returns false if there isn't enough room left for the value. bool WriteExponentialGolomb(uint32_t val); + // Writes the signed exponential golomb version of the supplied value. + // Signed exponential golomb values are just the unsigned values mapped to the + // sequence 0, 1, -1, 2, -2, etc. in order. + bool WriteSignedExponentialGolomb(int32_t val); private: // The buffer, as a writable array. diff --git a/include/webrtc/base/buffer.h b/include/webrtc/base/buffer.h index b8b8fc0..44f941e 100644 --- a/include/webrtc/base/buffer.h +++ b/include/webrtc/base/buffer.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_BASE_BUFFER_H_ #define WEBRTC_BASE_BUFFER_H_ +#include #include #include #include @@ -18,6 +19,7 @@ #include "webrtc/base/array_view.h" #include "webrtc/base/checks.h" +#include "webrtc/base/type_traits.h" namespace rtc { @@ -123,6 +125,11 @@ class BufferT { return reinterpret_cast(data_.get()); } + bool empty() const { + RTC_DCHECK(IsConsistent()); + return size_ == 0; + } + size_t size() const { RTC_DCHECK(IsConsistent()); return size_; @@ -191,7 +198,12 @@ class BufferT { SetData(array, N); } - void SetData(const BufferT& buf) { SetData(buf.data(), buf.size()); } + template ::value>::type* = nullptr> + void SetData(const W& w) { + SetData(w.data(), w.size()); + } // Replace the data in the buffer with at most |max_elements| of data, using // the function |setter|, which should have the following signature: @@ -218,7 +230,7 @@ class BufferT { void AppendData(const U* data, size_t size) { RTC_DCHECK(IsConsistent()); const size_t new_size = size_ + size; - EnsureCapacity(new_size); + EnsureCapacityWithHeadroom(new_size, true); static_assert(sizeof(T) == sizeof(U), ""); std::memcpy(data_.get() + size_, data, size * sizeof(U)); size_ = new_size; @@ -233,7 +245,19 @@ class BufferT { AppendData(array, N); } - void AppendData(const BufferT& buf) { AppendData(buf.data(), buf.size()); } + template ::value>::type* = nullptr> + void AppendData(const W& w) { + AppendData(w.data(), w.size()); + } + + template ::value>::type* = nullptr> + void AppendData(const U& item) { + AppendData(&item, 1); + } // Append at most |max_elements| to the end of the buffer, using the function // |setter|, which should have the following signature: @@ -264,7 +288,7 @@ class BufferT { // the existing contents will be kept and the new space will be // uninitialized. void SetSize(size_t size) { - EnsureCapacity(size); + EnsureCapacityWithHeadroom(size, true); size_ = size; } @@ -272,14 +296,9 @@ class BufferT { // further reallocation. (Of course, this operation might need to reallocate // the buffer.) void EnsureCapacity(size_t capacity) { - RTC_DCHECK(IsConsistent()); - if (capacity <= capacity_) - return; - std::unique_ptr new_data(new T[capacity]); - std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T)); - data_ = std::move(new_data); - capacity_ = capacity; - RTC_DCHECK(IsConsistent()); + // Don't allocate extra headroom, since the user is asking for a specific + // capacity. + EnsureCapacityWithHeadroom(capacity, false); } // Resets the buffer to zero size without altering capacity. Works even if the @@ -298,6 +317,27 @@ class BufferT { } private: + void EnsureCapacityWithHeadroom(size_t capacity, bool extra_headroom) { + RTC_DCHECK(IsConsistent()); + if (capacity <= capacity_) + return; + + // If the caller asks for extra headroom, ensure that the new capacity is + // >= 1.5 times the old capacity. Any constant > 1 is sufficient to prevent + // quadratic behavior; as to why we pick 1.5 in particular, see + // https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md and + // http://www.gahcep.com/cpp-internals-stl-vector-part-1/. + const size_t new_capacity = + extra_headroom ? std::max(capacity, capacity_ + capacity_ / 2) + : capacity; + + std::unique_ptr new_data(new T[new_capacity]); + std::memcpy(new_data.get(), data_.get(), size_ * sizeof(T)); + data_ = std::move(new_data); + capacity_ = new_capacity; + RTC_DCHECK(IsConsistent()); + } + // Precondition for all methods except Clear and the destructor. // Postcondition for all methods except move construction and move // assignment, which leave the moved-from object in a possibly inconsistent @@ -309,7 +349,7 @@ class BufferT { // Called when *this has been moved from. Conceptually it's a no-op, but we // can mutate the state slightly to help subsequent sanity checks catch bugs. void OnMovedFrom() { -#ifdef NDEBUG +#if RTC_DCHECK_IS_ON // Make *this consistent and empty. Shouldn't be necessary, but better safe // than sorry. size_ = 0; diff --git a/include/webrtc/base/bytebuffer.h b/include/webrtc/base/bytebuffer.h index cd7b2c6..546c447 100644 --- a/include/webrtc/base/bytebuffer.h +++ b/include/webrtc/base/bytebuffer.h @@ -46,9 +46,9 @@ class ByteBufferWriter : public ByteBuffer { ~ByteBufferWriter(); - const char* Data() const { return bytes_ + start_; } - size_t Length() const { return end_ - start_; } - size_t Capacity() const { return size_ - start_; } + const char* Data() const { return bytes_; } + size_t Length() const { return end_; } + size_t Capacity() const { return size_; } // Write value to the buffer. Resizes the buffer when it is // neccessary. @@ -77,7 +77,6 @@ class ByteBufferWriter : public ByteBuffer { char* bytes_; size_t size_; - size_t start_; size_t end_; // There are sensible ways to define these, but they aren't needed in our code diff --git a/include/webrtc/base/checks.h b/include/webrtc/base/checks.h index 681361a..c15a08c 100644 --- a/include/webrtc/base/checks.h +++ b/include/webrtc/base/checks.h @@ -11,10 +11,32 @@ #ifndef WEBRTC_BASE_CHECKS_H_ #define WEBRTC_BASE_CHECKS_H_ +#include "webrtc/typedefs.h" + +// If you for some reson need to know if DCHECKs are on, test the value of +// RTC_DCHECK_IS_ON. (Test its value, not if it's defined; it'll always be +// defined, to either a true or a false value.) +#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON) +#define RTC_DCHECK_IS_ON 1 +#else +#define RTC_DCHECK_IS_ON 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif +NO_RETURN void rtc_FatalMessage(const char* file, int line, const char* msg); +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +// C++ version. + #include #include -#include "webrtc/typedefs.h" +#include "webrtc/base/safe_compare.h" // The macros here print a message to stderr and abort under various // conditions. All will accept additional stream messages. For example: @@ -63,19 +85,25 @@ namespace rtc { #define RTC_LAZY_STREAM(stream, condition) \ !(condition) ? static_cast(0) : rtc::FatalMessageVoidify() & (stream) -// The actual stream used isn't important. We reference condition in the code +// The actual stream used isn't important. We reference |ignored| in the code // but don't evaluate it; this is to avoid "unused variable" warnings (we do so // in a particularly convoluted way with an extra ?: because that appears to be // the simplest construct that keeps Visual Studio from complaining about // condition being unused). -#define RTC_EAT_STREAM_PARAMETERS(condition) \ - (true ? true : !(condition)) \ - ? static_cast(0) \ +#define RTC_EAT_STREAM_PARAMETERS(ignored) \ + (true ? true : ((void)(ignored), true)) \ + ? static_cast(0) \ : rtc::FatalMessageVoidify() & rtc::FatalMessage("", 0).stream() -// RTC_CHECK dies with a fatal error if condition is not true. It is *not* -// controlled by NDEBUG, so the check will be executed regardless of -// compilation mode. +// Call RTC_EAT_STREAM_PARAMETERS with an argument that fails to compile if +// values of the same types as |a| and |b| can't be compared with the given +// operation, and that would evaluate |a| and |b| if evaluated. +#define RTC_EAT_STREAM_PARAMETERS_OP(op, a, b) \ + RTC_EAT_STREAM_PARAMETERS(((void)rtc::safe_cmp::op(a, b))) + +// RTC_CHECK dies with a fatal error if condition is not true. It is *not* +// controlled by NDEBUG or anything else, so the check will be executed +// regardless of compilation mode. // // We make sure RTC_CHECK et al. always evaluates their arguments, as // doing RTC_CHECK(FunctionWithSideEffect()) is a common idiom. @@ -130,41 +158,40 @@ std::string* MakeCheckOpString( // The (int, int) specialization works around the issue that the compiler // will not instantiate the template version of the function on values of // unnamed enum type - see comment below. -#define DEFINE_RTC_CHECK_OP_IMPL(name, op) \ +#define DEFINE_RTC_CHECK_OP_IMPL(name) \ template \ inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ const char* names) { \ - if (v1 op v2) \ - return NULL; \ + if (rtc::safe_cmp::name(v1, v2)) \ + return nullptr; \ else \ return rtc::MakeCheckOpString(v1, v2, names); \ } \ inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ - if (v1 op v2) \ - return NULL; \ + if (rtc::safe_cmp::name(v1, v2)) \ + return nullptr; \ else \ return rtc::MakeCheckOpString(v1, v2, names); \ } -DEFINE_RTC_CHECK_OP_IMPL(EQ, ==) -DEFINE_RTC_CHECK_OP_IMPL(NE, !=) -DEFINE_RTC_CHECK_OP_IMPL(LE, <=) -DEFINE_RTC_CHECK_OP_IMPL(LT, < ) -DEFINE_RTC_CHECK_OP_IMPL(GE, >=) -DEFINE_RTC_CHECK_OP_IMPL(GT, > ) +DEFINE_RTC_CHECK_OP_IMPL(Eq) +DEFINE_RTC_CHECK_OP_IMPL(Ne) +DEFINE_RTC_CHECK_OP_IMPL(Le) +DEFINE_RTC_CHECK_OP_IMPL(Lt) +DEFINE_RTC_CHECK_OP_IMPL(Ge) +DEFINE_RTC_CHECK_OP_IMPL(Gt) #undef DEFINE_RTC_CHECK_OP_IMPL -#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(EQ, ==, val1, val2) -#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(NE, !=, val1, val2) -#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(LE, <=, val1, val2) -#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(LT, < , val1, val2) -#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(GE, >=, val1, val2) -#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(GT, > , val1, val2) +#define RTC_CHECK_EQ(val1, val2) RTC_CHECK_OP(Eq, ==, val1, val2) +#define RTC_CHECK_NE(val1, val2) RTC_CHECK_OP(Ne, !=, val1, val2) +#define RTC_CHECK_LE(val1, val2) RTC_CHECK_OP(Le, <=, val1, val2) +#define RTC_CHECK_LT(val1, val2) RTC_CHECK_OP(Lt, <, val1, val2) +#define RTC_CHECK_GE(val1, val2) RTC_CHECK_OP(Ge, >=, val1, val2) +#define RTC_CHECK_GT(val1, val2) RTC_CHECK_OP(Gt, >, val1, val2) // The RTC_DCHECK macro is equivalent to RTC_CHECK except that it only generates // code in debug builds. It does reference the condition parameter in all cases, // though, so callers won't risk getting warnings about unused variables. -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define RTC_DCHECK_IS_ON 1 +#if RTC_DCHECK_IS_ON #define RTC_DCHECK(condition) RTC_CHECK(condition) #define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2) #define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2) @@ -173,14 +200,13 @@ DEFINE_RTC_CHECK_OP_IMPL(GT, > ) #define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2) #define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2) #else -#define RTC_DCHECK_IS_ON 0 #define RTC_DCHECK(condition) RTC_EAT_STREAM_PARAMETERS(condition) -#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) == (v2)) -#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) != (v2)) -#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) <= (v2)) -#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) < (v2)) -#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) >= (v2)) -#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS((v1) > (v2)) +#define RTC_DCHECK_EQ(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Eq, v1, v2) +#define RTC_DCHECK_NE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ne, v1, v2) +#define RTC_DCHECK_LE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Le, v1, v2) +#define RTC_DCHECK_LT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Lt, v1, v2) +#define RTC_DCHECK_GE(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Ge, v1, v2) +#define RTC_DCHECK_GT(v1, v2) RTC_EAT_STREAM_PARAMETERS_OP(Gt, v1, v2) #endif // This is identical to LogMessageVoidify but in name. @@ -220,10 +246,44 @@ class FatalMessage { // remainder is zero. template inline T CheckedDivExact(T a, T b) { - RTC_CHECK_EQ(a % b, static_cast(0)); + RTC_CHECK_EQ(a % b, 0) << a << " is not evenly divisible by " << b; return a / b; } } // namespace rtc +#else // __cplusplus not defined +// C version. Lacks many features compared to the C++ version, but usage +// guidelines are the same. + +#define RTC_CHECK(condition) \ + do { \ + if (!(condition)) { \ + rtc_FatalMessage(__FILE__, __LINE__, "CHECK failed: " #condition); \ + } \ + } while (0) + +#define RTC_CHECK_EQ(a, b) RTC_CHECK((a) == (b)) +#define RTC_CHECK_NE(a, b) RTC_CHECK((a) != (b)) +#define RTC_CHECK_LE(a, b) RTC_CHECK((a) <= (b)) +#define RTC_CHECK_LT(a, b) RTC_CHECK((a) < (b)) +#define RTC_CHECK_GE(a, b) RTC_CHECK((a) >= (b)) +#define RTC_CHECK_GT(a, b) RTC_CHECK((a) > (b)) + +#define RTC_DCHECK(condition) \ + do { \ + if (RTC_DCHECK_IS_ON && !(condition)) { \ + rtc_FatalMessage(__FILE__, __LINE__, "DCHECK failed: " #condition); \ + } \ + } while (0) + +#define RTC_DCHECK_EQ(a, b) RTC_DCHECK((a) == (b)) +#define RTC_DCHECK_NE(a, b) RTC_DCHECK((a) != (b)) +#define RTC_DCHECK_LE(a, b) RTC_DCHECK((a) <= (b)) +#define RTC_DCHECK_LT(a, b) RTC_DCHECK((a) < (b)) +#define RTC_DCHECK_GE(a, b) RTC_DCHECK((a) >= (b)) +#define RTC_DCHECK_GT(a, b) RTC_DCHECK((a) > (b)) + +#endif // __cplusplus + #endif // WEBRTC_BASE_CHECKS_H_ diff --git a/include/webrtc/base/common.h b/include/webrtc/base/common.h deleted file mode 100644 index 1b1dac6..0000000 --- a/include/webrtc/base/common.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_COMMON_H_ // NOLINT -#define WEBRTC_BASE_COMMON_H_ - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" - -#if defined(_MSC_VER) -// warning C4355: 'this' : used in base member initializer list -#pragma warning(disable:4355) -#endif - -////////////////////////////////////////////////////////////////////// -// General Utilities -////////////////////////////////////////////////////////////////////// - -#ifndef RTC_UNUSED -#define RTC_UNUSED(x) RtcUnused(static_cast(&x)) -#define RTC_UNUSED2(x, y) RtcUnused(static_cast(&x)); \ - RtcUnused(static_cast(&y)) -#define RTC_UNUSED3(x, y, z) RtcUnused(static_cast(&x)); \ - RtcUnused(static_cast(&y)); \ - RtcUnused(static_cast(&z)) -#define RTC_UNUSED4(x, y, z, a) RtcUnused(static_cast(&x)); \ - RtcUnused(static_cast(&y)); \ - RtcUnused(static_cast(&z)); \ - RtcUnused(static_cast(&a)) -#define RTC_UNUSED5(x, y, z, a, b) RtcUnused(static_cast(&x)); \ - RtcUnused(static_cast(&y)); \ - RtcUnused(static_cast(&z)); \ - RtcUnused(static_cast(&a)); \ - RtcUnused(static_cast(&b)) -inline void RtcUnused(const void*) {} -#endif // RTC_UNUSED - -#if !defined(WEBRTC_WIN) - -#ifndef strnicmp -#define strnicmp(x, y, n) strncasecmp(x, y, n) -#endif - -#ifndef stricmp -#define stricmp(x, y) strcasecmp(x, y) -#endif - -#endif // !defined(WEBRTC_WIN) - -///////////////////////////////////////////////////////////////////////////// -// Assertions -///////////////////////////////////////////////////////////////////////////// - -#ifndef ENABLE_DEBUG -#if !defined(NDEBUG) -#define ENABLE_DEBUG 1 -#else -#define ENABLE_DEBUG 0 -#endif -#endif // !defined(ENABLE_DEBUG) - -// Even for release builds, allow for the override of LogAssert. Though no -// macro is provided, this can still be used for explicit runtime asserts -// and allow applications to override the assert behavior. - -namespace rtc { - - -// If a debugger is attached, triggers a debugger breakpoint. If a debugger is -// not attached, forces program termination. -void Break(); - -// LogAssert writes information about an assertion to the log. It's called by -// Assert (and from the ASSERT macro in debug mode) before any other action -// is taken (e.g. breaking the debugger, abort()ing, etc.). -void LogAssert(const char* function, const char* file, int line, - const char* expression); - -typedef void (*AssertLogger)(const char* function, - const char* file, - int line, - const char* expression); - -// Sets a custom assert logger to be used instead of the default LogAssert -// behavior. To clear the custom assert logger, pass NULL for |logger| and the -// default behavior will be restored. Only one custom assert logger can be set -// at a time, so this should generally be set during application startup and -// only by one component. -void SetCustomAssertLogger(AssertLogger logger); - -bool IsOdd(int n); - -bool IsEven(int n); - -} // namespace rtc - -#if ENABLE_DEBUG - -namespace rtc { - -inline bool Assert(bool result, const char* function, const char* file, - int line, const char* expression) { - if (!result) { - LogAssert(function, file, line, expression); - Break(); - } - return result; -} - -// Same as Assert above, but does not call Break(). Used in assert macros -// that implement their own breaking. -inline bool AssertNoBreak(bool result, const char* function, const char* file, - int line, const char* expression) { - if (!result) - LogAssert(function, file, line, expression); - return result; -} - -} // namespace rtc - -#if defined(_MSC_VER) && _MSC_VER < 1300 -#define __FUNCTION__ "" -#endif - -#ifndef ASSERT -#if defined(WIN32) -// Using debugbreak() inline on Windows directly in the ASSERT macro, has the -// benefit of breaking exactly where the failing expression is and not two -// calls up the stack. -#define ASSERT(x) \ - (rtc::AssertNoBreak((x), __FUNCTION__, __FILE__, __LINE__, #x) ? \ - (void)(1) : __debugbreak()) -#else -#define ASSERT(x) \ - (void)rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x) -#endif -#endif - -#ifndef VERIFY -#if defined(WIN32) -#define VERIFY(x) \ - (rtc::AssertNoBreak((x), __FUNCTION__, __FILE__, __LINE__, #x) ? \ - true : (__debugbreak(), false)) -#else -#define VERIFY(x) rtc::Assert((x), __FUNCTION__, __FILE__, __LINE__, #x) -#endif -#endif - -#else // !ENABLE_DEBUG - -namespace rtc { - -inline bool ImplicitCastToBool(bool result) { return result; } - -} // namespace rtc - -#ifndef ASSERT -#define ASSERT(x) (void)0 -#endif - -#ifndef VERIFY -#define VERIFY(x) rtc::ImplicitCastToBool(x) -#endif - -#endif // !ENABLE_DEBUG - -#define COMPILE_TIME_ASSERT(expr) char CTA_UNIQUE_NAME[expr] -#define CTA_UNIQUE_NAME CTA_MAKE_NAME(__LINE__) -#define CTA_MAKE_NAME(line) CTA_MAKE_NAME2(line) -#define CTA_MAKE_NAME2(line) constraint_ ## line - -// Forces compiler to inline, even against its better judgement. Use wisely. -#if defined(__GNUC__) -#define FORCE_INLINE __attribute__ ((__always_inline__)) -#elif defined(WEBRTC_WIN) -#define FORCE_INLINE __forceinline -#else -#define FORCE_INLINE -#endif - -// Annotate a function indicating the caller must examine the return value. -// Use like: -// int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in . -// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and -// libjingle are merged. -#if !defined(WARN_UNUSED_RESULT) -#if defined(__GNUC__) || defined(__clang__) -#define WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) -#else -#define WARN_UNUSED_RESULT -#endif -#endif // WARN_UNUSED_RESULT - -#endif // WEBRTC_BASE_COMMON_H_ // NOLINT diff --git a/include/webrtc/base/copyonwritebuffer.h b/include/webrtc/base/copyonwritebuffer.h index a7e52be..fe3f561 100644 --- a/include/webrtc/base/copyonwritebuffer.h +++ b/include/webrtc/base/copyonwritebuffer.h @@ -89,7 +89,7 @@ class CopyOnWriteBuffer { template ::value>::type* = nullptr> - T* cdata() const { + const T* cdata() const { RTC_DCHECK(IsConsistent()); if (!buffer_) { return nullptr; @@ -119,20 +119,11 @@ class CopyOnWriteBuffer { CopyOnWriteBuffer& operator=(CopyOnWriteBuffer&& buf) { RTC_DCHECK(IsConsistent()); RTC_DCHECK(buf.IsConsistent()); - // TODO(jbauch): use std::move once scoped_refptr supports it (issue 5556) - buffer_.swap(buf.buffer_); - buf.buffer_ = nullptr; + buffer_ = std::move(buf.buffer_); return *this; } - bool operator==(const CopyOnWriteBuffer& buf) const { - // Must either use the same buffer internally or have the same contents. - RTC_DCHECK(IsConsistent()); - RTC_DCHECK(buf.IsConsistent()); - return buffer_.get() == buf.buffer_.get() || - (buffer_.get() && buf.buffer_.get() && - *buffer_.get() == *buf.buffer_.get()); - } + bool operator==(const CopyOnWriteBuffer& buf) const; bool operator!=(const CopyOnWriteBuffer& buf) const { return !(*this == buf); @@ -155,9 +146,10 @@ class CopyOnWriteBuffer { internal::BufferCompat::value>::type* = nullptr> void SetData(const T* data, size_t size) { RTC_DCHECK(IsConsistent()); - if (!buffer_ || !buffer_->HasOneRef()) { - buffer_ = size > 0 ? new RefCountedObject(data, size) - : nullptr; + if (!buffer_) { + buffer_ = size > 0 ? new RefCountedObject(data, size) : nullptr; + } else if (!buffer_->HasOneRef()) { + buffer_ = new RefCountedObject(data, size, buffer_->capacity()); } else { buffer_->SetData(data, size); } @@ -214,51 +206,16 @@ class CopyOnWriteBuffer { // buffer contents will be kept but truncated; if the new size is greater, // the existing contents will be kept and the new space will be // uninitialized. - void SetSize(size_t size) { - RTC_DCHECK(IsConsistent()); - if (!buffer_) { - if (size > 0) { - buffer_ = new RefCountedObject(size); - } - RTC_DCHECK(IsConsistent()); - return; - } - - CloneDataIfReferenced(std::max(buffer_->capacity(), size)); - buffer_->SetSize(size); - RTC_DCHECK(IsConsistent()); - } + void SetSize(size_t size); // Ensure that the buffer size can be increased to at least capacity without // further reallocation. (Of course, this operation might need to reallocate // the buffer.) - void EnsureCapacity(size_t capacity) { - RTC_DCHECK(IsConsistent()); - if (!buffer_) { - if (capacity > 0) { - buffer_ = new RefCountedObject(0, capacity); - } - RTC_DCHECK(IsConsistent()); - return; - } else if (capacity <= buffer_->capacity()) { - return; - } + void EnsureCapacity(size_t capacity); - CloneDataIfReferenced(std::max(buffer_->capacity(), capacity)); - buffer_->EnsureCapacity(capacity); - RTC_DCHECK(IsConsistent()); - } - - // Resets the buffer to zero size and capacity. - void Clear() { - RTC_DCHECK(IsConsistent()); - if (!buffer_ || !buffer_->HasOneRef()) { - buffer_ = nullptr; - } else { - buffer_->Clear(); - } - RTC_DCHECK(IsConsistent()); - } + // Resets the buffer to zero size without altering capacity. Works even if the + // buffer has been moved from. + void Clear(); // Swaps two buffers. friend void swap(CopyOnWriteBuffer& a, CopyOnWriteBuffer& b) { @@ -268,15 +225,7 @@ class CopyOnWriteBuffer { private: // Create a copy of the underlying data if it is referenced from other Buffer // objects. - void CloneDataIfReferenced(size_t new_capacity) { - if (buffer_->HasOneRef()) { - return; - } - - buffer_ = new RefCountedObject(buffer_->data(), buffer_->size(), - new_capacity); - RTC_DCHECK(IsConsistent()); - } + void CloneDataIfReferenced(size_t new_capacity); // Pre- and postcondition of all methods. bool IsConsistent() const { diff --git a/include/webrtc/base/cpu_time.h b/include/webrtc/base/cpu_time.h new file mode 100644 index 0000000..87e9418 --- /dev/null +++ b/include/webrtc/base/cpu_time.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_CPU_TIME_H_ +#define WEBRTC_BASE_CPU_TIME_H_ + +#include + +namespace rtc { + +// Returns total CPU time of a current process in nanoseconds. +// Time base is unknown, therefore use only to calculate deltas. +int64_t GetProcessCpuTimeNanos(); + +// Returns total CPU time of a current thread in nanoseconds. +// Time base is unknown, therefore use only to calculate deltas. +int64_t GetThreadCpuTimeNanos(); + +} // namespace rtc + +#endif // WEBRTC_BASE_CPU_TIME_H_ diff --git a/include/webrtc/base/criticalsection.h b/include/webrtc/base/criticalsection.h index 49c97a0..a0f9a6b 100644 --- a/include/webrtc/base/criticalsection.h +++ b/include/webrtc/base/criticalsection.h @@ -12,6 +12,7 @@ #define WEBRTC_BASE_CRITICALSECTION_H_ #include "webrtc/base/atomicops.h" +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/base/platform_thread_types.h" @@ -37,9 +38,7 @@ #include #endif -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define CS_DEBUG_CHECKS 1 -#endif +#define CS_DEBUG_CHECKS RTC_DCHECK_IS_ON #if CS_DEBUG_CHECKS #define CS_DEBUG_CODE(x) x @@ -61,12 +60,10 @@ class LOCKABLE CriticalSection { bool TryEnter() const EXCLUSIVE_TRYLOCK_FUNCTION(true); void Leave() const UNLOCK_FUNCTION(); + private: // Use only for RTC_DCHECKing. bool CurrentThreadIsOwner() const; - // Use only for RTC_DCHECKing. - bool IsLocked() const; - private: #if defined(WEBRTC_WIN) mutable CRITICAL_SECTION crit_; #elif defined(WEBRTC_POSIX) diff --git a/include/webrtc/base/cryptstring.h b/include/webrtc/base/cryptstring.h index adaac2f..e1ee309 100644 --- a/include/webrtc/base/cryptstring.h +++ b/include/webrtc/base/cryptstring.h @@ -17,8 +17,6 @@ #include #include -#include "webrtc/base/linked_ptr.h" - namespace rtc { class CryptStringImpl { diff --git a/include/webrtc/base/dbus.h b/include/webrtc/base/dbus.h deleted file mode 100644 index fb90638..0000000 --- a/include/webrtc/base/dbus.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_DBUS_H_ -#define WEBRTC_BASE_DBUS_H_ - -#ifdef HAVE_DBUS_GLIB - -#include - -#include -#include - -#include "webrtc/base/libdbusglibsymboltable.h" -#include "webrtc/base/messagehandler.h" -#include "webrtc/base/thread.h" - -namespace rtc { - -#define DBUS_TYPE "type" -#define DBUS_SIGNAL "signal" -#define DBUS_PATH "path" -#define DBUS_INTERFACE "interface" -#define DBUS_MEMBER "member" - -#ifdef CHROMEOS -#define CROS_PM_PATH "/" -#define CROS_PM_INTERFACE "org.chromium.PowerManager" -#define CROS_SIG_POWERCHANGED "PowerStateChanged" -#define CROS_VALUE_SLEEP "mem" -#define CROS_VALUE_RESUME "on" -#else -#define UP_PATH "/org/freedesktop/UPower" -#define UP_INTERFACE "org.freedesktop.UPower" -#define UP_SIG_SLEEPING "Sleeping" -#define UP_SIG_RESUMING "Resuming" -#endif // CHROMEOS - -// Wraps a DBus messages. -class DBusSigMessageData : public TypedMessageData { - public: - explicit DBusSigMessageData(DBusMessage *message); - ~DBusSigMessageData(); -}; - -// DBusSigFilter is an abstract class that defines the interface of DBus -// signal handling. -// The subclasses implement ProcessSignal() for various purposes. -// When a DBus signal comes, a DSM_SIGNAL message is posted to the caller thread -// which will then invokes ProcessSignal(). -class DBusSigFilter : protected MessageHandler { - public: - enum DBusSigMessage { DSM_SIGNAL }; - - // This filter string should ususally come from BuildFilterString() - explicit DBusSigFilter(const std::string &filter) - : caller_thread_(Thread::Current()), filter_(filter) { - } - - // Builds a DBus monitor filter string from given DBus path, interface, and - // member. - // See http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html - static std::string BuildFilterString(const std::string &path, - const std::string &interface, - const std::string &member); - - // Handles callback on DBus messages by DBus system. - static DBusHandlerResult DBusCallback(DBusConnection *dbus_conn, - DBusMessage *message, - void *instance); - - // Handles callback on DBus messages to each DBusSigFilter instance. - DBusHandlerResult Callback(DBusMessage *message); - - // From MessageHandler. - virtual void OnMessage(Message *message); - - // Returns the DBus monitor filter string. - const std::string &filter() const { return filter_; } - - private: - // On caller thread. - virtual void ProcessSignal(DBusMessage *message) = 0; - - Thread *caller_thread_; - const std::string filter_; -}; - -// DBusMonitor is a class for DBus signal monitoring. -// -// The caller-thread calls AddFilter() first to add the signals that it wants to -// monitor and then calls StartMonitoring() to start the monitoring. -// This will create a worker-thread which listens on DBus connection and sends -// DBus signals back through the callback. -// The worker-thread will be running forever until either StopMonitoring() is -// called from the caller-thread or the worker-thread hit some error. -// -// Programming model: -// 1. Caller-thread: Creates an object of DBusMonitor. -// 2. Caller-thread: Calls DBusMonitor::AddFilter() one or several times. -// 3. Caller-thread: StartMonitoring(). -// ... -// 4. Worker-thread: DBus signal recieved. Post a message to caller-thread. -// 5. Caller-thread: DBusFilterBase::ProcessSignal() is invoked. -// ... -// 6. Caller-thread: StopMonitoring(). -// -// Assumption: -// AddFilter(), StartMonitoring(), and StopMonitoring() methods are called by -// a single thread. Hence, there is no need to make them thread safe. -class DBusMonitor { - public: - // Status of DBus monitoring. - enum DBusMonitorStatus { - DMS_NOT_INITIALIZED, // Not initialized. - DMS_INITIALIZING, // Initializing the monitoring thread. - DMS_RUNNING, // Monitoring. - DMS_STOPPED, // Not monitoring. Stopped normally. - DMS_FAILED, // Not monitoring. Failed. - }; - - // Returns the DBus-Glib symbol table. - // We should only use this function to access DBus-Glib symbols. - static LibDBusGlibSymbolTable *GetDBusGlibSymbolTable(); - - // Creates an instance of DBusMonitor. - static DBusMonitor *Create(DBusBusType type); - ~DBusMonitor(); - - // Adds a filter to DBusMonitor. - bool AddFilter(DBusSigFilter *filter); - - // Starts DBus message monitoring. - bool StartMonitoring(); - - // Stops DBus message monitoring. - bool StopMonitoring(); - - // Gets the status of DBus monitoring. - DBusMonitorStatus GetStatus(); - - private: - // Forward declaration. Defined in the .cc file. - class DBusMonitoringThread; - - explicit DBusMonitor(DBusBusType type); - - // Updates status_ when monitoring status has changed. - void OnMonitoringStatusChanged(DBusMonitorStatus status); - - DBusBusType type_; - DBusMonitorStatus status_; - DBusMonitoringThread *monitoring_thread_; - std::vector filter_list_; -}; - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB - -#endif // WEBRTC_BASE_DBUS_H_ diff --git a/include/webrtc/base/diskcache.h b/include/webrtc/base/diskcache.h deleted file mode 100644 index 4ac1be1..0000000 --- a/include/webrtc/base/diskcache.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_DISKCACHE_H__ -#define WEBRTC_BASE_DISKCACHE_H__ - -#include -#include - -#if defined(WEBRTC_WIN) -#undef UnlockResource -#endif // WEBRTC_WIN - -namespace rtc { - -class StreamInterface; - -/////////////////////////////////////////////////////////////////////////////// -// DiskCache - An LRU cache of streams, stored on disk. -// -// Streams are identified by a unique resource id. Multiple streams can be -// associated with each resource id, distinguished by an index. When old -// resources are flushed from the cache, all streams associated with those -// resources are removed together. -// DiskCache is designed to persist across executions of the program. It is -// safe for use from an arbitrary number of users on a single thread, but not -// from multiple threads or other processes. -/////////////////////////////////////////////////////////////////////////////// - -class DiskCache { -public: - DiskCache(); - virtual ~DiskCache(); - - bool Initialize(const std::string& folder, size_t size); - bool Purge(); - - bool LockResource(const std::string& id); - StreamInterface* WriteResource(const std::string& id, size_t index); - bool UnlockResource(const std::string& id); - - StreamInterface* ReadResource(const std::string& id, size_t index) const; - - bool HasResource(const std::string& id) const; - bool HasResourceStream(const std::string& id, size_t index) const; - bool DeleteResource(const std::string& id); - - protected: - virtual bool InitializeEntries() = 0; - virtual bool PurgeFiles() = 0; - - virtual bool FileExists(const std::string& filename) const = 0; - virtual bool DeleteFile(const std::string& filename) const = 0; - - enum LockState { LS_UNLOCKED, LS_LOCKED, LS_UNLOCKING }; - struct Entry { - LockState lock_state; - mutable size_t accessors; - size_t size; - size_t streams; - time_t last_modified; - }; - typedef std::map EntryMap; - friend class DiskCacheAdapter; - - bool CheckLimit(); - - std::string IdToFilename(const std::string& id, size_t index) const; - bool FilenameToId(const std::string& filename, std::string* id, - size_t* index) const; - - const Entry* GetEntry(const std::string& id) const { - return const_cast(this)->GetOrCreateEntry(id, false); - } - Entry* GetOrCreateEntry(const std::string& id, bool create); - - void ReleaseResource(const std::string& id, size_t index) const; - - std::string folder_; - size_t max_cache_, total_size_; - EntryMap map_; - mutable size_t total_accessors_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// CacheLock - Automatically manage locking and unlocking, with optional -// rollback semantics -/////////////////////////////////////////////////////////////////////////////// - -class CacheLock { -public: - CacheLock(DiskCache* cache, const std::string& id, bool rollback = false) - : cache_(cache), id_(id), rollback_(rollback) - { - locked_ = cache_->LockResource(id_); - } - ~CacheLock() { - if (locked_) { - cache_->UnlockResource(id_); - if (rollback_) { - cache_->DeleteResource(id_); - } - } - } - bool IsLocked() const { return locked_; } - void Commit() { rollback_ = false; } - -private: - DiskCache* cache_; - std::string id_; - bool rollback_, locked_; -}; - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_DISKCACHE_H__ diff --git a/include/webrtc/base/diskcache_win32.h b/include/webrtc/base/diskcache_win32.h deleted file mode 100644 index 42cb9b0..0000000 --- a/include/webrtc/base/diskcache_win32.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2006 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_DISKCACHEWIN32_H__ -#define WEBRTC_BASE_DISKCACHEWIN32_H__ - -#include "webrtc/base/diskcache.h" - -namespace rtc { - -class DiskCacheWin32 : public DiskCache { - protected: - virtual bool InitializeEntries(); - virtual bool PurgeFiles(); - - virtual bool FileExists(const std::string& filename) const; - virtual bool DeleteFile(const std::string& filename) const; -}; - -} - -#endif // WEBRTC_BASE_DISKCACHEWIN32_H__ diff --git a/include/webrtc/base/event.h b/include/webrtc/base/event.h index 5237151..d4b5872 100644 --- a/include/webrtc/base/event.h +++ b/include/webrtc/base/event.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_BASE_EVENT_H__ #define WEBRTC_BASE_EVENT_H__ +#include "webrtc/base/constructormagic.h" #if defined(WEBRTC_WIN) #include "webrtc/base/win32.h" // NOLINT: consider this a system header. #elif defined(WEBRTC_POSIX) @@ -19,8 +20,6 @@ #error "Must define either WEBRTC_WIN or WEBRTC_POSIX." #endif -#include "webrtc/base/basictypes.h" - namespace rtc { class Event { @@ -46,6 +45,8 @@ class Event { const bool is_manual_reset_; bool event_status_; #endif + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Event); }; } // namespace rtc diff --git a/include/webrtc/base/fakeclock.h b/include/webrtc/base/fakeclock.h new file mode 100644 index 0000000..fcdfc0b --- /dev/null +++ b/include/webrtc/base/fakeclock.h @@ -0,0 +1,71 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_FAKECLOCK_H_ +#define WEBRTC_BASE_FAKECLOCK_H_ + +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/timedelta.h" +#include "webrtc/base/timeutils.h" + +namespace rtc { + +// Fake clock for use with unit tests, which does not tick on its own. +// Starts at time 0. +// +// TODO(deadbeef): Unify with webrtc::SimulatedClock. +class FakeClock : public ClockInterface { + public: + ~FakeClock() override {} + + // ClockInterface implementation. + int64_t TimeNanos() const override; + + // Methods that can be used by the test to control the time. + + // Should only be used to set a time in the future. + void SetTimeNanos(int64_t nanos); + void SetTimeMicros(int64_t micros) { + SetTimeNanos(kNumNanosecsPerMicrosec * micros); + } + + void AdvanceTime(TimeDelta delta); + void AdvanceTimeMicros(int64_t micros) { + AdvanceTime(rtc::TimeDelta::FromMicroseconds(micros)); + } + private: + CriticalSection lock_; + int64_t time_ GUARDED_BY(lock_) = 0; +}; + +// Helper class that sets itself as the global clock in its constructor and +// unsets it in its destructor. +class ScopedFakeClock : public FakeClock { + public: + ScopedFakeClock(); + ~ScopedFakeClock() override; + + private: + ClockInterface* prev_clock_; +}; + +// Helper class to "undo" the fake clock temporarily. +class ScopedRealClock { + public: + ScopedRealClock(); + ~ScopedRealClock(); + + private: + ClockInterface* prev_clock_; +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_FAKECLOCK_H_ diff --git a/include/webrtc/base/fakenetwork.h b/include/webrtc/base/fakenetwork.h index 2dd2137..108e738 100644 --- a/include/webrtc/base/fakenetwork.h +++ b/include/webrtc/base/fakenetwork.h @@ -31,7 +31,7 @@ const int kFakeIPv6NetworkPrefixLength = 64; class FakeNetworkManager : public NetworkManagerBase, public MessageHandler { public: - FakeNetworkManager() : thread_(Thread::Current()) {} + FakeNetworkManager() {} typedef std::vector> IfaceList; @@ -68,7 +68,7 @@ class FakeNetworkManager : public NetworkManagerBase, ++start_count_; if (start_count_ == 1) { sent_first_update_ = false; - thread_->Post(this); + rtc::Thread::Current()->Post(RTC_FROM_HERE, this); } else { if (sent_first_update_) { SignalNetworksChanged(); @@ -115,7 +115,6 @@ class FakeNetworkManager : public NetworkManagerBase, } } - Thread* thread_; IfaceList ifaces_; int next_index_ = 0; int start_count_ = 0; diff --git a/include/webrtc/base/fakesslidentity.h b/include/webrtc/base/fakesslidentity.h index 3b0df29..7065fc0 100644 --- a/include/webrtc/base/fakesslidentity.h +++ b/include/webrtc/base/fakesslidentity.h @@ -15,7 +15,7 @@ #include #include -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/messagedigest.h" #include "webrtc/base/sslidentity.h" @@ -45,7 +45,7 @@ class FakeSSLCertificate : public rtc::SSLCertificate { } void ToDER(Buffer* der_buffer) const override { std::string der_string; - VERIFY(SSLIdentity::PemToDer(kPemTypeCertificate, data_, &der_string)); + RTC_CHECK(SSLIdentity::PemToDer(kPemTypeCertificate, data_, &der_string)); der_buffer->SetData(der_string.c_str(), der_string.size()); } int64_t CertificateExpirationTime() const override { diff --git a/include/webrtc/base/faketaskrunner.h b/include/webrtc/base/faketaskrunner.h deleted file mode 100644 index 88e4826..0000000 --- a/include/webrtc/base/faketaskrunner.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2011 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// A fake TaskRunner for use in unit tests. - -#ifndef WEBRTC_BASE_FAKETASKRUNNER_H_ -#define WEBRTC_BASE_FAKETASKRUNNER_H_ - -#include "webrtc/base/taskparent.h" -#include "webrtc/base/taskrunner.h" - -namespace rtc { - -class FakeTaskRunner : public TaskRunner { - public: - FakeTaskRunner() : current_time_(0) {} - virtual ~FakeTaskRunner() {} - - virtual void WakeTasks() { RunTasks(); } - - virtual int64_t CurrentTime() { - // Implement if needed. - return current_time_++; - } - - int64_t current_time_; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_FAKETASKRUNNER_H_ diff --git a/include/webrtc/base/file.h b/include/webrtc/base/file.h new file mode 100644 index 0000000..f4806d1 --- /dev/null +++ b/include/webrtc/base/file.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_FILE_H_ +#define WEBRTC_BASE_FILE_H_ + +#include + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/pathutils.h" +#include "webrtc/base/platform_file.h" + +namespace rtc { + +// This class wraps the platform specific APIs for simple file interactions. +// +// The various read and write methods are best effort, i.e. if an underlying +// call does not manage to read/write all the data more calls will be performed, +// until an error is detected or all data is read/written. +class File { + public: + // Wraps the given PlatformFile. This class is then responsible for closing + // the file, which will be done in the destructor if Close is never called. + explicit File(PlatformFile); + // The default constructor produces a closed file. + File(); + ~File(); + + File(File&& other); + File& operator=(File&& other); + + // Open and Create give files with both reading and writing enabled. + static File Open(const std::string& path); + static File Open(Pathname&& path); + static File Open(const Pathname& path); + // If the file already exists it will be overwritten. + static File Create(const std::string& path); + static File Create(Pathname&& path); + static File Create(const Pathname& path); + + // Remove a file in the file system. + static bool Remove(const std::string& path); + static bool Remove(Pathname&& path); + static bool Remove(const Pathname& path); + + size_t Write(const uint8_t* data, size_t length); + size_t Read(uint8_t* buffer, size_t length); + + // The current position in the file after a call to these methods is platform + // dependent (MSVC gives position offset+length, most other + // compilers/platforms do not alter the position), i.e. do not depend on it, + // do a Seek before any subsequent Read/Write. + size_t WriteAt(const uint8_t* data, size_t length, size_t offset); + size_t ReadAt(uint8_t* buffer, size_t length, size_t offset); + + // Attempt to position the file at the given offset from the start. + // Returns true if successful, false otherwise. + bool Seek(size_t offset); + + // Attempt to close the file. Returns true if successful, false otherwise, + // most notably when the file is already closed. + bool Close(); + + bool IsOpen(); + + private: + PlatformFile file_; + RTC_DISALLOW_COPY_AND_ASSIGN(File); +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_FILE_H_ diff --git a/include/webrtc/base/fileutils.h b/include/webrtc/base/fileutils.h index 23d36b1..8f6ec52 100644 --- a/include/webrtc/base/fileutils.h +++ b/include/webrtc/base/fileutils.h @@ -21,8 +21,7 @@ #include #endif -#include "webrtc/base/basictypes.h" -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/platform_file.h" @@ -63,18 +62,6 @@ class DirectoryIterator { // returns the name of the file currently pointed to virtual std::string Name() const; - // returns the size of the file currently pointed to - virtual size_t FileSize() const; - - // returns true if the file is older than seconds - virtual bool OlderThan(int seconds) const; - - // checks whether current file is a special directory file "." or ".." - bool IsDots() const { - std::string filename(Name()); - return (filename.compare(".") == 0) || (filename.compare("..") == 0); - } - private: std::string directory_; #if defined(WEBRTC_WIN) @@ -98,28 +85,19 @@ class FilesystemInterface { virtual DirectoryIterator* IterateDirectory(); // Opens a file. Returns an open StreamInterface if function succeeds. - // Otherwise, returns NULL. + // Otherwise, returns null. // TODO: Add an error param to indicate failure reason, similar to // FileStream::Open virtual FileStream *OpenFile(const Pathname &filename, const std::string &mode) = 0; - // Atomically creates an empty file accessible only to the current user if one - // does not already exist at the given path, otherwise fails. This is the only - // secure way to create a file in a shared temp directory (e.g., C:\Temp on - // Windows or /tmp on Linux). - // Note that if it is essential that a file be successfully created then the - // app must generate random names and retry on failure, or else it will be - // vulnerable to a trivial DoS. - virtual bool CreatePrivateFile(const Pathname &filename) = 0; - // This will attempt to delete the path located at filename. - // It ASSERTS and returns false if the path points to a folder or a + // It DCHECKs and returns false if the path points to a folder or a // non-existent file. virtual bool DeleteFile(const Pathname &filename) = 0; // This will attempt to delete the empty folder located at 'folder' - // It ASSERTS and returns false if the path points to a file or a non-existent + // It DCHECKs and returns false if the path points to a file or a non-existent // folder. It fails normally if the folder is not empty or can otherwise // not be deleted. virtual bool DeleteEmptyFolder(const Pathname &folder) = 0; @@ -133,60 +111,22 @@ class FilesystemInterface { // the folder itself. virtual bool DeleteFolderAndContents(const Pathname& folder); - // This will delete whatever is located at path, be it a file or a folder. - // If it is a folder, it will delete it recursively by calling - // DeleteFolderAndContents - bool DeleteFileOrFolder(const Pathname &path) { - if (IsFolder(path)) - return DeleteFolderAndContents(path); - else - return DeleteFile(path); - } - // Creates a directory. This will call itself recursively to create /foo/bar // even if /foo does not exist. Returns true if the function succeeds. virtual bool CreateFolder(const Pathname &pathname) = 0; // This moves a file from old_path to new_path, where "old_path" is a - // plain file. This ASSERTs and returns false if old_path points to a + // plain file. This DCHECKs and returns false if old_path points to a // directory, and returns true if the function succeeds. // If the new path is on a different volume than the old path, this function // will attempt to copy and, if that succeeds, delete the old path. - virtual bool MoveFolder(const Pathname &old_path, - const Pathname &new_path) = 0; - - // This moves a directory from old_path to new_path, where "old_path" is a - // directory. This ASSERTs and returns false if old_path points to a plain - // file, and returns true if the function succeeds. - // If the new path is on a different volume, this function will attempt to - // copy and if that succeeds, delete the old path. virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0; - // This attempts to move whatever is located at old_path to new_path, - // be it a file or folder. - bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) { - if (IsFile(old_path)) { - return MoveFile(old_path, new_path); - } else { - return MoveFolder(old_path, new_path); - } - } - - // This copies a file from old_path to new_path. This method ASSERTs and + // This copies a file from old_path to new_path. This method DCHECKs and // returns false if old_path is a folder, and returns true if the copy // succeeds. virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0; - // This copies a folder from old_path to new_path. - bool CopyFolder(const Pathname &old_path, const Pathname &new_path); - - bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) { - if (IsFile(old_path)) - return CopyFile(old_path, new_path); - else - return CopyFolder(old_path, new_path); - } - // Returns true if pathname refers to a directory virtual bool IsFolder(const Pathname& pathname) = 0; @@ -215,44 +155,26 @@ class FilesystemInterface { virtual bool GetFileTime(const Pathname& path, FileTimeType which, time_t* time) = 0; - // Returns the path to the running application. - // Note: This is not guaranteed to work on all platforms. Be aware of the - // limitations before using it, and robustly handle failure. - virtual bool GetAppPathname(Pathname* path) = 0; - - // Get a folder that is unique to the current application, which is suitable - // for sharing data between executions of the app. If the per_user arg is - // true, the folder is also specific to the current user. - virtual bool GetAppDataFolder(Pathname* path, bool per_user) = 0; - // Get a temporary folder that is unique to the current user and application. // TODO: Re-evaluate the goals of this function. We probably just need any // directory that won't collide with another existing directory, and which // will be cleaned up when the program exits. virtual bool GetAppTempFolder(Pathname* path) = 0; - // Delete the contents of the folder returned by GetAppTempFolder - bool CleanAppTempFolder(); - - virtual bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) = 0; - - // Returns the absolute path of the current directory. - virtual Pathname GetCurrentDirectory() = 0; - // Note: These might go into some shared config section later, but they're // used by some methods in this interface, so we're leaving them here for now. void SetOrganizationName(const std::string& organization) { organization_name_ = organization; } void GetOrganizationName(std::string* organization) { - ASSERT(NULL != organization); + RTC_DCHECK(organization); *organization = organization_name_; } void SetApplicationName(const std::string& application) { application_name_ = application; } void GetApplicationName(std::string* application) { - ASSERT(NULL != application); + RTC_DCHECK(application); *application = application_name_; } @@ -264,7 +186,7 @@ class FilesystemInterface { class Filesystem { public: static FilesystemInterface *default_filesystem() { - ASSERT(default_filesystem_ != NULL); + RTC_DCHECK(default_filesystem_); return default_filesystem_; } @@ -292,18 +214,10 @@ class Filesystem { return EnsureDefaultFilesystem()->OpenFile(filename, mode); } - static bool CreatePrivateFile(const Pathname &filename) { - return EnsureDefaultFilesystem()->CreatePrivateFile(filename); - } - static bool DeleteFile(const Pathname &filename) { return EnsureDefaultFilesystem()->DeleteFile(filename); } - static bool DeleteEmptyFolder(const Pathname &folder) { - return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder); - } - static bool DeleteFolderContents(const Pathname &folder) { return EnsureDefaultFilesystem()->DeleteFolderContents(folder); } @@ -312,18 +226,10 @@ class Filesystem { return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder); } - static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) { - return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path); - } - static bool MoveFile(const Pathname &old_path, const Pathname &new_path) { return EnsureDefaultFilesystem()->MoveFile(old_path, new_path); } - static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) { - return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path); - } - static bool CopyFile(const Pathname &old_path, const Pathname &new_path) { return EnsureDefaultFilesystem()->CopyFile(old_path, new_path); } @@ -363,30 +269,10 @@ class Filesystem { return EnsureDefaultFilesystem()->GetFileTime(path, which, time); } - static bool GetAppPathname(Pathname* path) { - return EnsureDefaultFilesystem()->GetAppPathname(path); - } - - static bool GetAppDataFolder(Pathname* path, bool per_user) { - return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user); - } - static bool GetAppTempFolder(Pathname* path) { return EnsureDefaultFilesystem()->GetAppTempFolder(path); } - static bool CleanAppTempFolder() { - return EnsureDefaultFilesystem()->CleanAppTempFolder(); - } - - static bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) { - return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes); - } - - // Definition has to be in the .cc file due to returning forward-declared - // Pathname by value. - static Pathname GetCurrentDirectory(); - static void SetOrganizationName(const std::string& organization) { EnsureDefaultFilesystem()->SetOrganizationName(organization); } @@ -410,27 +296,6 @@ class Filesystem { RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Filesystem); }; -class FilesystemScope{ - public: - explicit FilesystemScope(FilesystemInterface *new_fs) { - old_fs_ = Filesystem::swap_default_filesystem(new_fs); - } - ~FilesystemScope() { - Filesystem::set_default_filesystem(old_fs_); - } - private: - FilesystemInterface* old_fs_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope); -}; - -// Generates a unique filename based on the input path. If no path component -// is specified, it uses the temporary directory. If a filename is provided, -// up to 100 variations of form basename-N.extension are tried. When -// create_empty is true, an empty file of this name is created (which -// decreases the chance of a temporary filename collision with another -// process). -bool CreateUniqueFile(Pathname& path, bool create_empty); - } // namespace rtc #endif // WEBRTC_BASE_FILEUTILS_H_ diff --git a/include/webrtc/base/fileutils_mock.h b/include/webrtc/base/fileutils_mock.h deleted file mode 100644 index 428d444..0000000 --- a/include/webrtc/base/fileutils_mock.h +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_FILEUTILS_MOCK_H_ -#define WEBRTC_BASE_FILEUTILS_MOCK_H_ - -#include -#include -#include - -#include "webrtc/base/fileutils.h" -#include "webrtc/base/gunit.h" -#include "webrtc/base/pathutils.h" -#include "webrtc/base/stream.h" - -namespace rtc { - -class FakeFileStream : public FileStream { - public: - explicit FakeFileStream(const std::string & contents) : - string_stream_(contents) - {} - - virtual StreamResult Read(void* buffer, size_t buffer_len, - size_t* read, int* error) { - return string_stream_.Read(buffer, buffer_len, read, error); - } - - virtual void Close() { - return string_stream_.Close(); - } - virtual bool GetSize(size_t* size) const { - return string_stream_.GetSize(size); - } - - private: - StringStream string_stream_; -}; - -class FakeDirectoryIterator : public DirectoryIterator { - public: - typedef std::pair File; - - /* - * files should be sorted by directory - * put '/' at the end of file if you want it to be a directory - * - * Sample list: - * /var/dir/file1 - * /var/dir/file2 - * /var/dir/subdir1/ - * /var/dir/subdir2/ - * /var/dir2/file2 - * /var/dir3/ - * - * you can call Iterate for any path: /var, /var/dir, /var/dir2 - * unrelated files will be ignored - */ - explicit FakeDirectoryIterator(const std::vector& all_files) : - all_files_(all_files) {} - - virtual bool Iterate(const Pathname& path) { - path_iterator_ = all_files_.begin(); - path_ = path.pathname(); - - // make sure path ends end with '/' - if (path_.rfind(Pathname::DefaultFolderDelimiter()) != path_.size() - 1) - path_ += Pathname::DefaultFolderDelimiter(); - - return FakeDirectoryIterator::Search(std::string("")); - } - - virtual bool Next() { - std::string current_name = Name(); - path_iterator_++; - return FakeDirectoryIterator::Search(current_name); - } - - bool Search(const std::string& current_name) { - for (; path_iterator_ != all_files_.end(); path_iterator_++) { - if (path_iterator_->first.find(path_) == 0 - && Name().compare(current_name) != 0) { - return true; - } - } - - return false; - } - - virtual bool IsDirectory() const { - std::string sub_path = path_iterator_->first; - - return std::string::npos != - sub_path.find(Pathname::DefaultFolderDelimiter(), path_.size()); - } - - virtual std::string Name() const { - std::string sub_path = path_iterator_->first; - - // path - top level path (ex. /var/lib) - // sub_path - subpath under top level path (ex. /var/lib/dir/dir/file ) - // find shortest non-trivial common path. (ex. /var/lib/dir) - size_t start = path_.size(); - size_t end = sub_path.find(Pathname::DefaultFolderDelimiter(), start); - - if (end != std::string::npos) { - return sub_path.substr(start, end - start); - } else { - return sub_path.substr(start); - } - } - - private: - const std::vector all_files_; - - std::string path_; - std::vector::const_iterator path_iterator_; -}; - -class FakeFileSystem : public FilesystemInterface { - public: - typedef std::pair File; - - explicit FakeFileSystem(const std::vector& all_files) : - all_files_(all_files) {} - - virtual DirectoryIterator *IterateDirectory() { - return new FakeDirectoryIterator(all_files_); - } - - virtual FileStream * OpenFile( - const Pathname &filename, - const std::string &mode) { - std::vector::const_iterator i_files = all_files_.begin(); - std::string path = filename.pathname(); - - for (; i_files != all_files_.end(); i_files++) { - if (i_files->first.compare(path) == 0) { - return new FakeFileStream(i_files->second); - } - } - - return NULL; - } - - bool CreatePrivateFile(const Pathname &filename) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool DeleteFile(const Pathname &filename) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool DeleteEmptyFolder(const Pathname &folder) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool DeleteFolderContents(const Pathname &folder) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool DeleteFolderAndContents(const Pathname &folder) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool CreateFolder(const Pathname &pathname) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool MoveFolder(const Pathname &old_path, const Pathname &new_path) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool MoveFile(const Pathname &old_path, const Pathname &new_path) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool CopyFile(const Pathname &old_path, const Pathname &new_path) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool IsFolder(const Pathname &pathname) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool IsFile(const Pathname &pathname) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool IsAbsent(const Pathname &pathname) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool IsTemporaryPath(const Pathname &pathname) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool GetTemporaryFolder(Pathname &path, bool create, - const std::string *append) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - std::string TempFilename(const Pathname &dir, const std::string &prefix) { - EXPECT_TRUE(false) << "Unsupported operation"; - return std::string(); - } - bool GetFileSize(const Pathname &path, size_t *size) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool GetFileTime(const Pathname &path, FileTimeType which, - time_t* time) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool GetAppPathname(Pathname *path) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool GetAppDataFolder(Pathname *path, bool per_user) { - EXPECT_TRUE(per_user) << "Unsupported operation"; -#if defined(WEBRTC_WIN) - path->SetPathname("c:\\Users\\test_user", ""); -#else - path->SetPathname("/home/user/test_user", ""); -#endif - return true; - } - bool GetAppTempFolder(Pathname *path) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) { - EXPECT_TRUE(false) << "Unsupported operation"; - return false; - } - Pathname GetCurrentDirectory() { - return Pathname(); - } - - private: - const std::vector all_files_; -}; -} // namespace rtc - -#endif // WEBRTC_BASE_FILEUTILS_MOCK_H_ diff --git a/include/webrtc/base/firewallsocketserver.h b/include/webrtc/base/firewallsocketserver.h index 26fc75e..95ff039 100644 --- a/include/webrtc/base/firewallsocketserver.h +++ b/include/webrtc/base/firewallsocketserver.h @@ -26,8 +26,8 @@ enum FirewallDirection { FD_IN, FD_OUT, FD_ANY }; class FirewallSocketServer : public SocketServer { public: - FirewallSocketServer(SocketServer * server, - FirewallManager * manager = NULL, + FirewallSocketServer(SocketServer* server, + FirewallManager* manager = nullptr, bool should_delete_server = false); ~FirewallSocketServer() override; @@ -35,7 +35,7 @@ class FirewallSocketServer : public SocketServer { void set_socketserver(SocketServer* server) { if (server_ && should_delete_server_) { delete server_; - server_ = NULL; + server_ = nullptr; should_delete_server_ = false; } server_ = server; diff --git a/include/webrtc/base/flags.h b/include/webrtc/base/flags.h index d16f12b..d6a871e 100644 --- a/include/webrtc/base/flags.h +++ b/include/webrtc/base/flags.h @@ -23,10 +23,7 @@ #ifndef WEBRTC_BASE_FLAGS_H__ #define WEBRTC_BASE_FLAGS_H__ -#include - #include "webrtc/base/checks.h" -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" namespace rtc { @@ -88,43 +85,43 @@ class Flag { // Flag variables bool* bool_variable() const { - assert(type_ == BOOL); + RTC_DCHECK_EQ(BOOL, type_); return &variable_->b; } int* int_variable() const { - assert(type_ == INT); + RTC_DCHECK_EQ(INT, type_); return &variable_->i; } double* float_variable() const { - assert(type_ == FLOAT); + RTC_DCHECK_EQ(FLOAT, type_); return &variable_->f; } const char** string_variable() const { - assert(type_ == STRING); + RTC_DCHECK_EQ(STRING, type_); return &variable_->s; } // Default values bool bool_default() const { - assert(type_ == BOOL); + RTC_DCHECK_EQ(BOOL, type_); return default_.b; } int int_default() const { - assert(type_ == INT); + RTC_DCHECK_EQ(INT, type_); return default_.i; } double float_default() const { - assert(type_ == FLOAT); + RTC_DCHECK_EQ(FLOAT, type_); return default_.f; } const char* string_default() const { - assert(type_ == STRING); + RTC_DCHECK_EQ(STRING, type_); return default_.s; } @@ -192,19 +189,19 @@ class FlagList { public: FlagList(); - // The NULL-terminated list of all flags. Traverse with Flag::next(). + // The null-terminated list of all flags. Traverse with Flag::next(). static Flag* list() { return list_; } - // If file != NULL, prints information for all flags defined in file; - // otherwise prints information for all flags in all files. The current - // flag value is only printed if print_current_value is set. + // If file != nullptr, prints information for all flags defined in file; + // otherwise prints information for all flags in all files. The current flag + // value is only printed if print_current_value is set. static void Print(const char* file, bool print_current_value); - // Lookup a flag by name. Returns the matching flag or NULL. + // Lookup a flag by name. Returns the matching flag or null. static Flag* Lookup(const char* name); // Helper function to parse flags: Takes an argument arg and splits it into - // a flag name and flag value (or NULL if they are missing). is_bool is set + // a flag name and flag value (or null if they are missing). is_bool is set // if the arg started with "-no" or "--no". The buffer may be used to NUL- // terminate the name, it must be large enough to hold any possible name. static void SplitArgument(const char* arg, diff --git a/include/webrtc/base/function_view.h b/include/webrtc/base/function_view.h new file mode 100644 index 0000000..861bccf --- /dev/null +++ b/include/webrtc/base/function_view.h @@ -0,0 +1,130 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_FUNCTION_VIEW_H_ +#define WEBRTC_BASE_FUNCTION_VIEW_H_ + +#include +#include + +#include "webrtc/base/checks.h" + +// Just like std::function, FunctionView will wrap any callable and hide its +// actual type, exposing only its signature. But unlike std::function, +// FunctionView doesn't own its callable---it just points to it. Thus, it's a +// good choice mainly as a function argument when the callable argument will +// not be called again once the function has returned. +// +// Its constructors are implicit, so that callers won't have to convert lambdas +// and other callables to FunctionView explicitly. This is +// safe because FunctionView is only a reference to the real callable. +// +// Example use: +// +// void SomeFunction(rtc::FunctionView index_transform); +// ... +// SomeFunction([](int i) { return 2 * i + 1; }); +// +// Note: FunctionView is tiny (essentially just two pointers) and trivially +// copyable, so it's probably cheaper to pass it by value than by const +// reference. + +namespace rtc { + +template +class FunctionView; // Undefined. + +template +class FunctionView final { + public: + // Constructor for lambdas and other callables; it accepts every type of + // argument except those noted in its enable_if call. + template < + typename F, + typename std::enable_if< + // Not for function pointers; we have another constructor for that + // below. + !std::is_function::type>::type>::value && + + // Not for nullptr; we have another constructor for that below. + !std::is_same::type>::value && + + // Not for FunctionView objects; we have another constructor for that + // (the implicitly declared copy constructor). + !std::is_same::type>::type>::value>::type* = nullptr> + FunctionView(F&& f) + : call_(CallVoidPtr::type>) { + f_.void_ptr = &f; + } + + // Constructor that accepts function pointers. If the argument is null, the + // result is an empty FunctionView. + template < + typename F, + typename std::enable_if::type>::type>::value>::type* = + nullptr> + FunctionView(F&& f) + : call_(f ? CallFunPtr::type> : nullptr) { + f_.fun_ptr = reinterpret_cast(f); + } + + // Constructor that accepts nullptr. It creates an empty FunctionView. + template ::type>::value>::type* = nullptr> + FunctionView(F&& f) : call_(nullptr) {} + + // Default constructor. Creates an empty FunctionView. + FunctionView() : call_(nullptr) {} + + RetT operator()(ArgT... args) const { + RTC_DCHECK(call_); + return call_(f_, std::forward(args)...); + } + + // Returns true if we have a function, false if we don't (i.e., we're null). + explicit operator bool() const { return !!call_; } + + private: + union VoidUnion { + void* void_ptr; + void (*fun_ptr)(); + }; + + template + static RetT CallVoidPtr(VoidUnion vu, ArgT... args) { + return (*static_cast(vu.void_ptr))(std::forward(args)...); + } + template + static RetT CallFunPtr(VoidUnion vu, ArgT... args) { + return (reinterpret_cast::type>(vu.fun_ptr))( + std::forward(args)...); + } + + // A pointer to the callable thing, with type information erased. It's a + // union because we have to use separate types depending on if the callable + // thing is a function pointer or something else. + VoidUnion f_; + + // Pointer to a dispatch function that knows the type of the callable thing + // that's stored in f_, and how to call it. A FunctionView object is empty + // (null) iff call_ is null. + RetT (*call_)(VoidUnion, ArgT...); +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_FUNCTION_VIEW_H_ diff --git a/include/webrtc/base/gunit.h b/include/webrtc/base/gunit.h index e705322..10258c7 100644 --- a/include/webrtc/base/gunit.h +++ b/include/webrtc/base/gunit.h @@ -11,31 +11,35 @@ #ifndef WEBRTC_BASE_GUNIT_H_ #define WEBRTC_BASE_GUNIT_H_ +#include "webrtc/base/fakeclock.h" #include "webrtc/base/logging.h" #include "webrtc/base/thread.h" #if defined(GTEST_RELATIVE_PATH) -#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/test/gtest.h" #else #include "testing/base/public/gunit.h" #endif // Wait until "ex" is true, or "timeout" expires. -#define WAIT(ex, timeout) \ - for (int64_t start = rtc::TimeMillis(); \ - !(ex) && rtc::TimeMillis() < start + timeout;) \ - rtc::Thread::Current()->ProcessMessages(1); +#define WAIT(ex, timeout) \ + for (int64_t start = rtc::SystemTimeMillis(); \ + !(ex) && rtc::SystemTimeMillis() < start + (timeout);) { \ + rtc::Thread::Current()->ProcessMessages(0); \ + rtc::Thread::Current()->SleepMs(1); \ + } // This returns the result of the test in res, so that we don't re-evaluate // the expression in the XXXX_WAIT macros below, since that causes problems // when the expression is only true the first time you check it. -#define WAIT_(ex, timeout, res) \ - do { \ - int64_t start = rtc::TimeMillis(); \ - res = (ex); \ - while (!res && rtc::TimeMillis() < start + timeout) { \ - rtc::Thread::Current()->ProcessMessages(1); \ - res = (ex); \ - } \ +#define WAIT_(ex, timeout, res) \ + do { \ + int64_t start = rtc::SystemTimeMillis(); \ + res = (ex); \ + while (!res && rtc::SystemTimeMillis() < start + (timeout)) { \ + rtc::Thread::Current()->ProcessMessages(0); \ + rtc::Thread::Current()->SleepMs(1); \ + res = (ex); \ + } \ } while (0) // The typical EXPECT_XXXX and ASSERT_XXXXs, but done until true or a timeout. @@ -70,19 +74,77 @@ // Version with a "soft" timeout and a margin. This logs if the timeout is // exceeded, but it only fails if the expression still isn't true after the // margin time passes. -#define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \ - do { \ - bool res; \ - WAIT_(ex, timeout, res); \ - if (res) { \ - break; \ - } \ - LOG(LS_WARNING) << "Expression " << #ex << " still not true after " << \ - timeout << "ms; waiting an additional " << margin << "ms"; \ - WAIT_(ex, margin, res); \ - if (!res) { \ - EXPECT_TRUE(ex); \ - } \ +#define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \ + do { \ + bool res; \ + WAIT_(ex, timeout, res); \ + if (res) { \ + break; \ + } \ + LOG(LS_WARNING) << "Expression " << #ex << " still not true after " \ + << (timeout) << "ms; waiting an additional " << margin \ + << "ms"; \ + WAIT_(ex, margin, res); \ + if (!res) { \ + EXPECT_TRUE(ex); \ + } \ + } while (0) + +// Wait until "ex" is true, or "timeout" expires, using fake clock where +// messages are processed every millisecond. +// TODO(pthatcher): Allow tests to control how many milliseconds to advance. +#define SIMULATED_WAIT(ex, timeout, clock) \ + for (int64_t start = rtc::TimeMillis(); \ + !(ex) && rtc::TimeMillis() < start + (timeout);) { \ + (clock).AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ + } + +// This returns the result of the test in res, so that we don't re-evaluate +// the expression in the XXXX_WAIT macros below, since that causes problems +// when the expression is only true the first time you check it. +#define SIMULATED_WAIT_(ex, timeout, res, clock) \ + do { \ + int64_t start = rtc::TimeMillis(); \ + res = (ex); \ + while (!res && rtc::TimeMillis() < start + (timeout)) { \ + (clock).AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ + res = (ex); \ + } \ + } while (0) + +// The typical EXPECT_XXXX, but done until true or a timeout with a fake clock. +#define EXPECT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(ex, timeout, res, clock); \ + if (!res) { \ + EXPECT_TRUE(ex); \ + } \ + } while (0) + +#define EXPECT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(v1 == v2, timeout, res, clock); \ + if (!res) { \ + EXPECT_EQ(v1, v2); \ + } \ + } while (0) + +#define ASSERT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(ex, timeout, res, clock); \ + if (!res) \ + ASSERT_TRUE(ex); \ + } while (0) + +#define ASSERT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \ + do { \ + bool res; \ + SIMULATED_WAIT_(v1 == v2, timeout, res, clock); \ + if (!res) \ + ASSERT_EQ(v1, v2); \ } while (0) #endif // WEBRTC_BASE_GUNIT_H_ diff --git a/include/webrtc/base/helpers.h b/include/webrtc/base/helpers.h index 0e79373..fcf77af 100644 --- a/include/webrtc/base/helpers.h +++ b/include/webrtc/base/helpers.h @@ -25,7 +25,6 @@ bool InitRandom(const char* seed, size_t len); // Generates a (cryptographically) random string of the given length. // We generate base64 values so that they will be printable. -// WARNING: could silently fail. Use the version below instead. std::string CreateRandomString(size_t length); // Generates a (cryptographically) random string of the given length. @@ -36,9 +35,15 @@ bool CreateRandomString(size_t length, std::string* str); // Generates a (cryptographically) random string of the given length, // with characters from the given table. Return false if the random // number generator failed. +// For ease of implementation, the function requires that the table +// size evenly divide 256; otherwise, it returns false. bool CreateRandomString(size_t length, const std::string& table, std::string* str); +// Generates (cryptographically) random data of the given length. +// Return false if the random number generator failed. +bool CreateRandomData(size_t length, std::string* data); + // Generates a (cryptographically) random UUID version 4 string. std::string CreateRandomUuid(); diff --git a/include/webrtc/base/httpbase.h b/include/webrtc/base/httpbase.h index 7f368f8..4b834a4 100644 --- a/include/webrtc/base/httpbase.h +++ b/include/webrtc/base/httpbase.h @@ -113,7 +113,7 @@ class HttpBase // Obtaining this stream puts HttpBase into stream mode until the stream // is closed. HttpBase can only expose one open stream interface at a time. - // Further calls will return NULL. + // Further calls will return null. StreamInterface* GetDocumentStream(); protected: diff --git a/include/webrtc/base/httpclient.h b/include/webrtc/base/httpclient.h deleted file mode 100644 index 0c19d2e..0000000 --- a/include/webrtc/base/httpclient.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_HTTPCLIENT_H__ -#define WEBRTC_BASE_HTTPCLIENT_H__ - -#include - -#include "webrtc/base/common.h" -#include "webrtc/base/httpbase.h" -#include "webrtc/base/nethelpers.h" -#include "webrtc/base/proxyinfo.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/base/socketaddress.h" -#include "webrtc/base/socketpool.h" - -namespace rtc { - -////////////////////////////////////////////////////////////////////// -// Client-specific http utilities -////////////////////////////////////////////////////////////////////// - -// Write cache-relevant response headers to output stream. If size is non-null, -// it contains the length of the output in bytes. output may be null if only -// the length is desired. -bool HttpWriteCacheHeaders(const HttpResponseData* response, - StreamInterface* output, size_t* size); -// Read cached headers from a stream, and them merge them into the response -// object using the specified combine operation. -bool HttpReadCacheHeaders(StreamInterface* input, - HttpResponseData* response, - HttpData::HeaderCombine combine); - -////////////////////////////////////////////////////////////////////// -// HttpClient -// Implements an HTTP 1.1 client. -////////////////////////////////////////////////////////////////////// - -class DiskCache; -class HttpClient; -class IPNetPool; - -class SignalThread; -// What to do: Define STRICT_HTTP_ERROR=1 in your makefile. Use HttpError in -// your code (HttpErrorType should only be used for code that is shared -// with groups which have not yet migrated). -#if STRICT_HTTP_ERROR -typedef HttpError HttpErrorType; -#else // !STRICT_HTTP_ERROR -typedef int HttpErrorType; -#endif // !STRICT_HTTP_ERROR - -class HttpClient : private IHttpNotify, public sigslot::has_slots<> { -public: - // If HttpRequestData and HttpResponseData objects are provided, they must - // be freed by the caller. Otherwise, an internal object is allocated. - HttpClient(const std::string& agent, StreamPool* pool, - HttpTransaction* transaction = NULL); - ~HttpClient() override; - - void set_pool(StreamPool* pool) { pool_ = pool; } - - void set_agent(const std::string& agent) { agent_ = agent; } - const std::string& agent() const { return agent_; } - - void set_proxy(const ProxyInfo& proxy) { proxy_ = proxy; } - const ProxyInfo& proxy() const { return proxy_; } - - // Request retries occur when the connection closes before the beginning of - // an http response is received. In these cases, the http server may have - // timed out the keepalive connection before it received our request. Note - // that if a request document cannot be rewound, no retry is made. The - // default is 1. - void set_request_retries(size_t retries) { retries_ = retries; } - size_t request_retries() const { return retries_; } - - enum RedirectAction { REDIRECT_DEFAULT, REDIRECT_ALWAYS, REDIRECT_NEVER }; - void set_redirect_action(RedirectAction action) { redirect_action_ = action; } - RedirectAction redirect_action() const { return redirect_action_; } - - enum UriForm { URI_DEFAULT, URI_ABSOLUTE, URI_RELATIVE }; - void set_uri_form(UriForm form) { uri_form_ = form; } - UriForm uri_form() const { return uri_form_; } - - void set_cache(DiskCache* cache) { ASSERT(!IsCacheActive()); cache_ = cache; } - bool cache_enabled() const { return (NULL != cache_); } - - // reset clears the server, request, and response structures. It will also - // abort an active request. - void reset(); - - void set_server(const SocketAddress& address); - const SocketAddress& server() const { return server_; } - - // Note: in order for HttpClient to retry a POST in response to - // an authentication challenge, a redirect response, or socket disconnection, - // the request document must support 'replaying' by calling Rewind() on it. - HttpTransaction* transaction() { return transaction_; } - const HttpTransaction* transaction() const { return transaction_; } - HttpRequestData& request() { return transaction_->request; } - const HttpRequestData& request() const { return transaction_->request; } - HttpResponseData& response() { return transaction_->response; } - const HttpResponseData& response() const { return transaction_->response; } - - // convenience methods - void prepare_get(const std::string& url); - void prepare_post(const std::string& url, const std::string& content_type, - StreamInterface* request_doc); - - // Convert HttpClient to a pull-based I/O model. - StreamInterface* GetDocumentStream(); - - // After you finish setting up your request, call start. - void start(); - - // Signalled when the header has finished downloading, before the document - // content is processed. You may change the response document in response - // to this signal. The second parameter indicates whether this is an - // intermediate (false) or final (true) header. An intermediate header is - // one that generates another request, such as a redirect or authentication - // challenge. The third parameter indicates the length of the response - // document, or else SIZE_UNKNOWN. Note: Do NOT abort the request in response - // to this signal. - sigslot::signal3 SignalHeaderAvailable; - // Signalled when the current request finishes. On success, err is 0. - sigslot::signal2 SignalHttpClientComplete; - -protected: - void connect(); - void release(); - - bool ShouldRedirect(std::string* location) const; - - bool BeginCacheFile(); - HttpError WriteCacheHeaders(const std::string& id); - void CompleteCacheFile(); - - bool CheckCache(); - HttpError ReadCacheHeaders(const std::string& id, bool override); - HttpError ReadCacheBody(const std::string& id); - - bool PrepareValidate(); - HttpError CompleteValidate(); - - HttpError OnHeaderAvailable(bool ignore_data, bool chunked, size_t data_size); - - void StartDNSLookup(); - void OnResolveResult(AsyncResolverInterface* resolver); - - // IHttpNotify Interface - HttpError onHttpHeaderComplete(bool chunked, size_t& data_size) override; - void onHttpComplete(HttpMode mode, HttpError err) override; - void onHttpClosed(HttpError err) override; - -private: - enum CacheState { CS_READY, CS_WRITING, CS_READING, CS_VALIDATING }; - bool IsCacheActive() const { return (cache_state_ > CS_READY); } - - std::string agent_; - StreamPool* pool_; - HttpBase base_; - SocketAddress server_; - ProxyInfo proxy_; - HttpTransaction* transaction_; - bool free_transaction_; - size_t retries_, attempt_, redirects_; - RedirectAction redirect_action_; - UriForm uri_form_; - std::unique_ptr context_; - DiskCache* cache_; - CacheState cache_state_; - AsyncResolverInterface* resolver_; -}; - -////////////////////////////////////////////////////////////////////// -// HttpClientDefault - Default implementation of HttpClient -////////////////////////////////////////////////////////////////////// - -class HttpClientDefault : public ReuseSocketPool, public HttpClient { -public: - HttpClientDefault(SocketFactory* factory, const std::string& agent, - HttpTransaction* transaction = NULL); -}; - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_HTTPCLIENT_H__ diff --git a/include/webrtc/base/httpcommon-inl.h b/include/webrtc/base/httpcommon-inl.h index 188d9e6..f29f075 100644 --- a/include/webrtc/base/httpcommon-inl.h +++ b/include/webrtc/base/httpcommon-inl.h @@ -12,7 +12,7 @@ #define WEBRTC_BASE_HTTPCOMMON_INL_H__ #include "webrtc/base/arraysize.h" -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/httpcommon.h" namespace rtc { @@ -53,7 +53,7 @@ void Url::do_set_address(const CTYPE* val, size_t len) { host_.assign(val, colon - val); // Note: In every case, we're guaranteed that colon is followed by a null, // or non-numeric character. - port_ = static_cast(::strtoul(colon + 1, NULL, 10)); + port_ = static_cast(::strtoul(colon + 1, nullptr, 10)); // TODO: Consider checking for invalid data following port number. } else { host_.assign(val, len); @@ -72,7 +72,7 @@ void Url::do_set_full_path(const CTYPE* val, size_t len) { // TODO: consider failing in this case. path_.assign(1, static_cast('/')); } else { - ASSERT(val[0] == static_cast('/')); + RTC_DCHECK(val[0] == static_cast('/')); path_.assign(val, path_length); } query_.assign(query, len - path_length); diff --git a/include/webrtc/base/httpcommon.h b/include/webrtc/base/httpcommon.h index 3450b58..7182aa2 100644 --- a/include/webrtc/base/httpcommon.h +++ b/include/webrtc/base/httpcommon.h @@ -16,7 +16,7 @@ #include #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/stringutils.h" #include "webrtc/base/stream.h" @@ -254,14 +254,14 @@ class Url { if (val.empty()) { path_.assign(1, static_cast('/')); } else { - ASSERT(val[0] == static_cast('/')); + RTC_DCHECK(val[0] == static_cast('/')); path_ = val; } } const string& path() const { return path_; } void set_query(const string& val) { - ASSERT(val.empty() || (val[0] == static_cast('?'))); + RTC_DCHECK(val.empty() || (val[0] == static_cast('?'))); query_ = val; } const string& query() const { return query_; } diff --git a/include/webrtc/base/httprequest.h b/include/webrtc/base/httprequest.h deleted file mode 100644 index fa2ffdb..0000000 --- a/include/webrtc/base/httprequest.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2006 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef _HTTPREQUEST_H_ -#define _HTTPREQUEST_H_ - -#include "webrtc/base/httpclient.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/proxyinfo.h" -#include "webrtc/base/socketserver.h" -#include "webrtc/base/thread.h" -#include "webrtc/base/sslsocketfactory.h" // Deprecated include - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// HttpRequest -/////////////////////////////////////////////////////////////////////////////// - -class FirewallManager; -class MemoryStream; - -class HttpRequest { -public: - HttpRequest(const std::string &user_agent); - ~HttpRequest(); - - void Send(); - - void set_proxy(const ProxyInfo& proxy) { - proxy_ = proxy; - } - void set_firewall(FirewallManager * firewall) { - firewall_ = firewall; - } - - // The DNS name of the host to connect to. - const std::string& host() { return host_; } - void set_host(const std::string& host) { host_ = host; } - - // The port to connect to on the target host. - int port() { return port_; } - void set_port(int port) { port_ = port; } - - // Whether the request should use SSL. - bool secure() { return secure_; } - void set_secure(bool secure) { secure_ = secure; } - - // Returns the redirect when redirection occurs - const std::string& response_redirect() { return response_redirect_; } - - // Time to wait on the download, in ms. Default is 5000 (5s) - int timeout() { return timeout_; } - void set_timeout(int timeout) { timeout_ = timeout; } - - // Fail redirects to allow analysis of redirect urls, etc. - bool fail_redirect() const { return fail_redirect_; } - void set_fail_redirect(bool fail_redirect) { fail_redirect_ = fail_redirect; } - - HttpRequestData& request() { return client_.request(); } - HttpResponseData& response() { return client_.response(); } - HttpErrorType error() { return error_; } - -protected: - void set_error(HttpErrorType error) { error_ = error; } - -private: - ProxyInfo proxy_; - FirewallManager * firewall_; - std::string host_; - int port_; - bool secure_; - int timeout_; - bool fail_redirect_; - HttpClient client_; - HttpErrorType error_; - std::string response_redirect_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// HttpMonitor -/////////////////////////////////////////////////////////////////////////////// - -class HttpMonitor : public sigslot::has_slots<> { -public: - HttpMonitor(SocketServer *ss); - - void reset() { - complete_ = false; - error_ = HE_DEFAULT; - } - - bool done() const { return complete_; } - HttpErrorType error() const { return error_; } - - void Connect(HttpClient* http); - void OnHttpClientComplete(HttpClient * http, HttpErrorType error); - -private: - bool complete_; - HttpErrorType error_; - SocketServer *ss_; -}; - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc_ - -#endif // _HTTPREQUEST_H_ diff --git a/include/webrtc/base/httpserver.h b/include/webrtc/base/httpserver.h index c322e81..cbee734 100644 --- a/include/webrtc/base/httpserver.h +++ b/include/webrtc/base/httpserver.h @@ -51,8 +51,8 @@ class HttpServer { // the request document is a MemoryStream. By handling this signal, the // document can be overridden, in which case the third signal argument should // be set to true. In the case where the request body should be ignored, - // the document can be set to NULL. Note that the transaction object is still - // owened by the HttpServer at this point. + // the document can be set to null. Note that the transaction object is still + // owened by the HttpServer at this point. sigslot::signal3 SignalHttpRequestHeader; diff --git a/include/webrtc/base/ignore_wundef.h b/include/webrtc/base/ignore_wundef.h new file mode 100644 index 0000000..b5bf7f7 --- /dev/null +++ b/include/webrtc/base/ignore_wundef.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_IGNORE_WUNDEF_H_ +#define WEBRTC_BASE_IGNORE_WUNDEF_H_ + +// If a header file uses #if on possibly undefined macros (and it's for some +// reason not possible to just fix the header file), include it like this: +// +// RTC_PUSH_IGNORING_WUNDEF() +// #include "misbehaving_header.h" +// RTC_POP_IGNORING_WUNDEF() +// +// This will cause the compiler to not emit -Wundef warnings for that file. + +#ifdef __clang__ +#define RTC_PUSH_IGNORING_WUNDEF() \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wundef\"") +#define RTC_POP_IGNORING_WUNDEF() _Pragma("clang diagnostic pop") +#else +#define RTC_PUSH_IGNORING_WUNDEF() +#define RTC_POP_IGNORING_WUNDEF() +#endif // __clang__ + +#endif // WEBRTC_BASE_IGNORE_WUNDEF_H_ diff --git a/include/webrtc/base/latebindingsymboltable.h b/include/webrtc/base/latebindingsymboltable.h deleted file mode 100644 index 794a4ab..0000000 --- a/include/webrtc/base/latebindingsymboltable.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LATEBINDINGSYMBOLTABLE_H_ -#define WEBRTC_BASE_LATEBINDINGSYMBOLTABLE_H_ - -#include - -#include "webrtc/base/common.h" -#include "webrtc/base/constructormagic.h" - -namespace rtc { - -#if defined(WEBRTC_POSIX) -typedef void *DllHandle; -#else -#error Not implemented for this platform -#endif - -// This is the base class for "symbol table" classes to simplify the dynamic -// loading of symbols from DLLs. Currently the implementation only supports -// Linux and OS X, and pure C symbols (or extern "C" symbols that wrap C++ -// functions). Sub-classes for specific DLLs are generated via the "supermacro" -// files latebindingsymboltable.h.def and latebindingsymboltable.cc.def. See -// talk/sound/pulseaudiosymboltable.(h|cc) for an example. -class LateBindingSymbolTable { - public: - struct TableInfo { - const char *dll_name; - int num_symbols; - // Array of size num_symbols. - const char *const *symbol_names; - }; - - LateBindingSymbolTable(const TableInfo *info, void **table); - ~LateBindingSymbolTable(); - - bool IsLoaded() const; - // Loads the DLL and the symbol table. Returns true iff the DLL and symbol - // table loaded successfully. - bool Load(); - // Like load, but allows overriding the dll path for when the dll path is - // dynamic. - bool LoadFromPath(const char *dll_path); - void Unload(); - - // Gets the raw OS handle to the DLL. Be careful what you do with it. - DllHandle GetDllHandle() const { return handle_; } - - private: - void ClearSymbols(); - - const TableInfo *info_; - void **table_; - DllHandle handle_; - bool undefined_symbols_; - - RTC_DISALLOW_COPY_AND_ASSIGN(LateBindingSymbolTable); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_LATEBINDINGSYMBOLTABLE_H_ diff --git a/include/webrtc/base/libdbusglibsymboltable.h b/include/webrtc/base/libdbusglibsymboltable.h deleted file mode 100644 index b87b4c1..0000000 --- a/include/webrtc/base/libdbusglibsymboltable.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ -#define WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ - -#ifdef HAVE_DBUS_GLIB - -#include -#include - -#include "webrtc/base/latebindingsymboltable.h" - -namespace rtc { - -#define LIBDBUS_GLIB_CLASS_NAME LibDBusGlibSymbolTable -// The libdbus-glib symbols we need, as an X-Macro list. -// This list must contain precisely every libdbus-glib function that is used in -// dbus.cc. -#define LIBDBUS_GLIB_SYMBOLS_LIST \ - X(dbus_bus_add_match) \ - X(dbus_connection_add_filter) \ - X(dbus_connection_close) \ - X(dbus_connection_remove_filter) \ - X(dbus_connection_set_exit_on_disconnect) \ - X(dbus_g_bus_get) \ - X(dbus_g_bus_get_private) \ - X(dbus_g_connection_get_connection) \ - X(dbus_g_connection_unref) \ - X(dbus_g_thread_init) \ - X(dbus_message_get_interface) \ - X(dbus_message_get_member) \ - X(dbus_message_get_path) \ - X(dbus_message_get_type) \ - X(dbus_message_iter_get_arg_type) \ - X(dbus_message_iter_get_basic) \ - X(dbus_message_iter_init) \ - X(dbus_message_ref) \ - X(dbus_message_unref) - -#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME -#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST -#include "webrtc/base/latebindingsymboltable.h.def" - -} // namespace rtc - -#endif // HAVE_DBUS_GLIB - -#endif // WEBRTC_BASE_LIBDBUSGLIBSYMBOLTABLE_H_ diff --git a/include/webrtc/base/linked_ptr.h b/include/webrtc/base/linked_ptr.h deleted file mode 100644 index 65e5a00..0000000 --- a/include/webrtc/base/linked_ptr.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -/* - * linked_ptr - simple reference linked pointer - * (like reference counting, just using a linked list of the references - * instead of their count.) - * - * The implementation stores three pointers for every linked_ptr, but - * does not allocate anything on the free store. - */ - -#ifndef WEBRTC_BASE_LINKED_PTR_H__ -#define WEBRTC_BASE_LINKED_PTR_H__ - -namespace rtc { - -/* For ANSI-challenged compilers, you may want to #define - * NO_MEMBER_TEMPLATES, explicit or mutable */ -#define NO_MEMBER_TEMPLATES - -template class linked_ptr -{ -public: - -#ifndef NO_MEMBER_TEMPLATES -# define TEMPLATE_FUNCTION template - TEMPLATE_FUNCTION friend class linked_ptr; -#else -# define TEMPLATE_FUNCTION - typedef X Y; -#endif - - typedef X element_type; - - explicit linked_ptr(X* p = 0) throw() - : itsPtr(p) {itsPrev = itsNext = this;} - ~linked_ptr() - {release();} - linked_ptr(const linked_ptr& r) throw() - {acquire(r);} - linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; - } - -#ifndef NO_MEMBER_TEMPLATES - template friend class linked_ptr; - template linked_ptr(const linked_ptr& r) throw() - {acquire(r);} - template linked_ptr& operator=(const linked_ptr& r) - { - if (this != &r) { - release(); - acquire(r); - } - return *this; - } -#endif // NO_MEMBER_TEMPLATES - - X& operator*() const throw() {return *itsPtr;} - X* operator->() const throw() {return itsPtr;} - X* get() const throw() {return itsPtr;} - bool unique() const throw() {return itsPrev ? itsPrev==this : true;} - -private: - X* itsPtr; - mutable const linked_ptr* itsPrev; - mutable const linked_ptr* itsNext; - - void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; -#ifndef mutable - r.itsNext = this; -#else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; -#endif - } - -#ifndef NO_MEMBER_TEMPLATES - template void acquire(const linked_ptr& r) throw() - { // insert this to the list - itsPtr = r.itsPtr; - itsNext = r.itsNext; - itsNext->itsPrev = this; - itsPrev = &r; -#ifndef mutable - r.itsNext = this; -#else // for ANSI-challenged compilers - (const_cast*>(&r))->itsNext = this; -#endif - } -#endif // NO_MEMBER_TEMPLATES - - void release() - { // erase this from the list, delete if unique - if (unique()) delete itsPtr; - else { - itsPrev->itsNext = itsNext; - itsNext->itsPrev = itsPrev; - itsPrev = itsNext = 0; - } - itsPtr = 0; - } -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_LINKED_PTR_H__ - diff --git a/include/webrtc/base/linux.h b/include/webrtc/base/linux.h deleted file mode 100644 index b69de3b..0000000 --- a/include/webrtc/base/linux.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LINUX_H_ -#define WEBRTC_BASE_LINUX_H_ - -#if defined(WEBRTC_LINUX) -#include -#include -#include -#include - -#include "webrtc/base/stream.h" - -namespace rtc { - -////////////////////////////////////////////////////////////////////////////// -// ConfigParser parses a FileStream of an ".ini."-type format into a map. -////////////////////////////////////////////////////////////////////////////// - -// Sample Usage: -// ConfigParser parser; -// ConfigParser::MapVector key_val_pairs; -// if (parser.Open(inifile) && parser.Parse(&key_val_pairs)) { -// for (int section_num=0; i < key_val_pairs.size(); ++section_num) { -// std::string val1 = key_val_pairs[section_num][key1]; -// std::string val2 = key_val_pairs[section_num][key2]; -// // Do something with valn; -// } -// } - -class ConfigParser { - public: - typedef std::map SimpleMap; - typedef std::vector MapVector; - - ConfigParser(); - virtual ~ConfigParser(); - - virtual bool Open(const std::string& filename); - virtual void Attach(StreamInterface* stream); - virtual bool Parse(MapVector* key_val_pairs); - virtual bool ParseSection(SimpleMap* key_val_pair); - virtual bool ParseLine(std::string* key, std::string* value); - - private: - std::unique_ptr instream_; -}; - -////////////////////////////////////////////////////////////////////////////// -// ProcCpuInfo reads CPU info from the /proc subsystem on any *NIX platform. -////////////////////////////////////////////////////////////////////////////// - -// Sample Usage: -// ProcCpuInfo proc_info; -// int no_of_cpu; -// if (proc_info.LoadFromSystem()) { -// std::string out_str; -// proc_info.GetNumCpus(&no_of_cpu); -// proc_info.GetCpuStringValue(0, "vendor_id", &out_str); -// } -// } - -class ProcCpuInfo { - public: - ProcCpuInfo(); - virtual ~ProcCpuInfo(); - - // Reads the proc subsystem's cpu info into memory. If this fails, this - // returns false; if it succeeds, it returns true. - virtual bool LoadFromSystem(); - - // Obtains the number of logical CPU threads and places the value num. - virtual bool GetNumCpus(int* num); - - // Obtains the number of physical CPU cores and places the value num. - virtual bool GetNumPhysicalCpus(int* num); - - // Obtains the CPU family id. - virtual bool GetCpuFamily(int* id); - - // Obtains the number of sections in /proc/cpuinfo, which may be greater - // than the number of CPUs (e.g. on ARM) - virtual bool GetSectionCount(size_t* count); - - // Looks for the CPU proc item with the given name for the given section - // number and places the string value in result. - virtual bool GetSectionStringValue(size_t section_num, const std::string& key, - std::string* result); - - // Looks for the CPU proc item with the given name for the given section - // number and places the int value in result. - virtual bool GetSectionIntValue(size_t section_num, const std::string& key, - int* result); - - private: - ConfigParser::MapVector sections_; -}; - -// Returns the output of "uname". -std::string ReadLinuxUname(); - -// Returns the content (int) of -// /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq -// Returns -1 on error. -int ReadCpuMaxFreq(); - -} // namespace rtc - -#endif // defined(WEBRTC_LINUX) -#endif // WEBRTC_BASE_LINUX_H_ diff --git a/include/webrtc/base/linuxfdwalk.h b/include/webrtc/base/linuxfdwalk.h deleted file mode 100644 index fe5a697..0000000 --- a/include/webrtc/base/linuxfdwalk.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LINUXFDWALK_H_ -#define WEBRTC_BASE_LINUXFDWALK_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// Linux port of SunOS's fdwalk(3) call. It loops over all open file descriptors -// and calls func on each one. Additionally, it is safe to use from the child -// of a fork that hasn't exec'ed yet, so you can use it to close all open file -// descriptors prior to exec'ing a daemon. -// The return value is 0 if successful, or else -1 and errno is set. The -// possible errors include any error that can be returned by opendir(), -// readdir(), or closedir(), plus EBADF if there are problems parsing the -// contents of /proc/self/fd. -// The file descriptors that are enumerated will not include the file descriptor -// used for the enumeration itself. -int fdwalk(void (*func)(void *, int), void *opaque); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // WEBRTC_BASE_LINUXFDWALK_H_ diff --git a/include/webrtc/base/location.h b/include/webrtc/base/location.h new file mode 100644 index 0000000..a541bbe --- /dev/null +++ b/include/webrtc/base/location.h @@ -0,0 +1,57 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_LOCATION_H_ +#define WEBRTC_BASE_LOCATION_H_ + +#include + +#include "webrtc/system_wrappers/include/stringize_macros.h" + +namespace rtc { + +// Location provides basic info where of an object was constructed, or was +// significantly brought to life. +// This is a stripped down version of: +// https://code.google.com/p/chromium/codesearch#chromium/src/base/location.h +class Location { + public: + // Constructor should be called with a long-lived char*, such as __FILE__. + // It assumes the provided value will persist as a global constant, and it + // will not make a copy of it. + // + // TODO(deadbeef): Tracing is currently limited to 2 arguments, which is + // why the file name and line number are combined into one argument. + // + // Once TracingV2 is available, separate the file name and line number. + Location(const char* function_name, const char* file_and_line); + Location(); + Location(const Location& other); + Location& operator=(const Location& other); + + const char* function_name() const { return function_name_; } + const char* file_and_line() const { return file_and_line_; } + + std::string ToString() const; + + private: + const char* function_name_; + const char* file_and_line_; +}; + +// Define a macro to record the current source location. +#define RTC_FROM_HERE RTC_FROM_HERE_WITH_FUNCTION(__FUNCTION__) + +#define RTC_FROM_HERE_WITH_FUNCTION(function_name) \ + ::rtc::Location(function_name, __FILE__ ":" STRINGIZE(__LINE__)) + +} // namespace rtc + +#endif // WEBRTC_BASE_LOCATION_H_ diff --git a/include/webrtc/base/logging.h b/include/webrtc/base/logging.h index 631c638..8f476a0 100644 --- a/include/webrtc/base/logging.h +++ b/include/webrtc/base/logging.h @@ -139,9 +139,12 @@ class LogSink { class LogMessage { public: - LogMessage(const char* file, int line, LoggingSeverity sev, - LogErrorContext err_ctx = ERRCTX_NONE, int err = 0, - const char* module = NULL); + LogMessage(const char* file, + int line, + LoggingSeverity sev, + LogErrorContext err_ctx = ERRCTX_NONE, + int err = 0, + const char* module = nullptr); LogMessage(const char* file, int line, @@ -185,7 +188,7 @@ class LogMessage { // GetLogToStream gets the severity for the specified stream, of if none // is specified, the minimum stream severity. // RemoveLogToStream removes the specified stream, without destroying it. - static int GetLogToStream(LogSink* stream = NULL); + static int GetLogToStream(LogSink* stream = nullptr); static void AddLogToStream(LogSink* stream, LoggingSeverity min_sev); static void RemoveLogToStream(LogSink* stream); @@ -254,7 +257,7 @@ class LogMultilineState { }; // When possible, pass optional state variable to track various data across -// multiple calls to LogMultiline. Otherwise, pass NULL. +// multiple calls to LogMultiline. Otherwise, pass null. void LogMultiline(LoggingSeverity level, const char* label, bool input, const void* data, size_t len, bool hex_mode, LogMultilineState* state); @@ -335,7 +338,7 @@ inline bool LogCheckLevel(LoggingSeverity sev) { LOG_GLE(sev) #define LAST_SYSTEM_ERROR \ (::GetLastError()) -#elif __native_client__ +#elif defined(__native_client__) && __native_client__ #define LOG_ERR_EX(sev, err) \ LOG(sev) #define LOG_ERR(sev) \ @@ -351,9 +354,9 @@ inline bool LogCheckLevel(LoggingSeverity sev) { (errno) #endif // WEBRTC_WIN -#define LOG_TAG(sev, tag) \ +#define LOG_TAG(sev, tag) \ LOG_SEVERITY_PRECONDITION(sev) \ - rtc::LogMessage(NULL, 0, sev, tag).stream() + rtc::LogMessage(nullptr, 0, sev, tag).stream() #define PLOG(sev, err) \ LOG_ERR_EX(sev, err) diff --git a/include/webrtc/base/macasyncsocket.h b/include/webrtc/base/macasyncsocket.h deleted file mode 100644 index c0f57b9..0000000 --- a/include/webrtc/base/macasyncsocket.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -// MacAsyncSocket is a kind of AsyncSocket. It only creates sockets -// of the TCP type, and does not (yet) support listen and accept. It works -// asynchronously, which means that users of this socket should connect to -// the various events declared in asyncsocket.h to receive notifications about -// this socket. - -#ifndef WEBRTC_BASE_MACASYNCSOCKET_H__ -#define WEBRTC_BASE_MACASYNCSOCKET_H__ - -#include - -#include "webrtc/base/asyncsocket.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/nethelpers.h" - -namespace rtc { - -class MacBaseSocketServer; - -class MacAsyncSocket : public AsyncSocket, public sigslot::has_slots<> { - public: - MacAsyncSocket(MacBaseSocketServer* ss, int family); - ~MacAsyncSocket() override; - - bool valid() const { return source_ != NULL; } - - // Socket interface - SocketAddress GetLocalAddress() const override; - SocketAddress GetRemoteAddress() const override; - int Bind(const SocketAddress& addr) override; - int Connect(const SocketAddress& addr) override; - int Send(const void* buffer, size_t length) override; - int SendTo(const void* buffer, - size_t length, - const SocketAddress& addr) override; - int Recv(void* buffer, size_t length) override; - int RecvFrom(void* buffer, size_t length, SocketAddress* out_addr) override; - int Listen(int backlog) override; - MacAsyncSocket* Accept(SocketAddress* out_addr) override; - int Close() override; - int GetError() const override; - void SetError(int error) override; - ConnState GetState() const override; - int EstimateMTU(uint16_t* mtu) override; - int GetOption(Option opt, int* value) override; - int SetOption(Option opt, int value) override; - - // For the MacBaseSocketServer to disable callbacks when process_io is false. - void EnableCallbacks(); - void DisableCallbacks(); - - protected: - void OnResolveResult(SignalThread* thread); - int DoConnect(const SocketAddress& addr); - - private: - // Creates an async socket from an existing bsd socket - MacAsyncSocket(MacBaseSocketServer* ss, int family, int native_socket); - - // Attaches the socket to the CFRunloop and sets the wrapped bsd socket - // to async mode - void Initialize(int family); - - // Translate the SocketAddress into a CFDataRef to pass to CF socket - // functions. Caller must call CFRelease on the result when done. - static CFDataRef CopyCFAddress(const SocketAddress& address); - - // Callback for the underlying CFSocketRef. - static void MacAsyncSocketCallBack(CFSocketRef s, - CFSocketCallBackType callbackType, - CFDataRef address, - const void* data, - void* info); - - MacBaseSocketServer* ss_; - CFSocketRef socket_; - int native_socket_; - CFRunLoopSourceRef source_; - int current_callbacks_; - bool disabled_; - int error_; - ConnState state_; - AsyncResolver* resolver_; - - RTC_DISALLOW_COPY_AND_ASSIGN(MacAsyncSocket); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_MACASYNCSOCKET_H__ diff --git a/include/webrtc/base/maccocoasocketserver.h b/include/webrtc/base/maccocoasocketserver.h deleted file mode 100644 index 3e07a45..0000000 --- a/include/webrtc/base/maccocoasocketserver.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2007 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// A libjingle compatible SocketServer for OSX/iOS/Cocoa. - -#ifndef WEBRTC_BASE_MACCOCOASOCKETSERVER_H_ -#define WEBRTC_BASE_MACCOCOASOCKETSERVER_H_ - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/macsocketserver.h" - -#ifdef __OBJC__ -@class NSTimer, MacCocoaSocketServerHelperRtc; -#else -class NSTimer; -class MacCocoaSocketServerHelperRtc; -#endif - -namespace rtc { - -// A socketserver implementation that wraps the main cocoa -// application loop accessed through [NSApp run]. -class MacCocoaSocketServer : public MacBaseSocketServer { - public: - explicit MacCocoaSocketServer(); - ~MacCocoaSocketServer() override; - - bool Wait(int cms, bool process_io) override; - void WakeUp() override; - - private: - MacCocoaSocketServerHelperRtc* helper_; - NSTimer* timer_; // Weak. - // The count of how many times we're inside the NSApplication main loop. - int run_count_; - - RTC_DISALLOW_COPY_AND_ASSIGN(MacCocoaSocketServer); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_MACCOCOASOCKETSERVER_H_ diff --git a/include/webrtc/base/macconversion.h b/include/webrtc/base/macconversion.h deleted file mode 100644 index 63b27cf..0000000 --- a/include/webrtc/base/macconversion.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_MACCONVERSION_H_ -#define WEBRTC_BASE_MACCONVERSION_H_ - -#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS) - -#include - -#include - -// given a CFStringRef, attempt to convert it to a C++ string. -// returns true if it succeeds, false otherwise. -// We can safely assume, given our context, that the string is -// going to be in ASCII, because it will either be an IP address, -// or a domain name, which is guaranteed to be ASCII-representable. -bool p_convertHostCFStringRefToCPPString(const CFStringRef cfstr, - std::string& cppstr); - -// Convert the CFNumber to an integer, putting the integer in the location -// given, and returhing true, if the conversion succeeds. -// If given a NULL or a non-CFNumber, returns false. -// This is pretty aggresive about trying to convert to int. -bool p_convertCFNumberToInt(CFNumberRef cfn, int* i); - -// given a CFNumberRef, determine if it represents a true value. -bool p_isCFNumberTrue(CFNumberRef cfn); - -#endif // WEBRTC_MAC || WEBRTC_IOS - -#endif // WEBRTC_BASE_MACCONVERSION_H_ diff --git a/include/webrtc/base/macsocketserver.h b/include/webrtc/base/macsocketserver.h deleted file mode 100644 index f85628b..0000000 --- a/include/webrtc/base/macsocketserver.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2007 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#ifndef WEBRTC_BASE_MACSOCKETSERVER_H__ -#define WEBRTC_BASE_MACSOCKETSERVER_H__ - -#include -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) // Invalid on IOS -#include -#endif -#include "webrtc/base/physicalsocketserver.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// MacBaseSocketServer -/////////////////////////////////////////////////////////////////////////////// -class MacAsyncSocket; - -class MacBaseSocketServer : public PhysicalSocketServer { - public: - MacBaseSocketServer(); - ~MacBaseSocketServer() override; - - // SocketServer Interface - Socket* CreateSocket(int type) override; - Socket* CreateSocket(int family, int type) override; - - AsyncSocket* CreateAsyncSocket(int type) override; - AsyncSocket* CreateAsyncSocket(int family, int type) override; - - bool Wait(int cms, bool process_io) override = 0; - void WakeUp() override = 0; - - void RegisterSocket(MacAsyncSocket* socket); - void UnregisterSocket(MacAsyncSocket* socket); - - // PhysicalSocketServer Overrides - bool SetPosixSignalHandler(int signum, void (*handler)(int)) override; - - protected: - void EnableSocketCallbacks(bool enable); - const std::set& sockets() { - return sockets_; - } - - private: - static void FileDescriptorCallback(CFFileDescriptorRef ref, - CFOptionFlags flags, - void* context); - - std::set sockets_; -}; - -// Core Foundation implementation of the socket server. While idle it -// will run the current CF run loop. When the socket server has work -// to do the run loop will be paused. Does not support Carbon or Cocoa -// UI interaction. -class MacCFSocketServer : public MacBaseSocketServer { - public: - MacCFSocketServer(); - ~MacCFSocketServer() override; - - // SocketServer Interface - bool Wait(int cms, bool process_io) override; - void WakeUp() override; - void OnWakeUpCallback(); - - private: - CFRunLoopRef run_loop_; - CFRunLoopSourceRef wake_up_; -}; - -#ifndef CARBON_DEPRECATED - -/////////////////////////////////////////////////////////////////////////////// -// MacCarbonSocketServer -/////////////////////////////////////////////////////////////////////////////// - -// Interacts with the Carbon event queue. While idle it will block, -// waiting for events. When the socket server has work to do, it will -// post a 'wake up' event to the queue, causing the thread to exit the -// event loop until the next call to Wait. Other events are dispatched -// to their target. Supports Carbon and Cocoa UI interaction. -class MacCarbonSocketServer : public MacBaseSocketServer { - public: - MacCarbonSocketServer(); - virtual ~MacCarbonSocketServer(); - - // SocketServer Interface - virtual bool Wait(int cms, bool process_io); - virtual void WakeUp(); - - private: - EventQueueRef event_queue_; - EventRef wake_up_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// MacCarbonAppSocketServer -/////////////////////////////////////////////////////////////////////////////// - -// Runs the Carbon application event loop on the current thread while -// idle. When the socket server has work to do, it will post an event -// to the queue, causing the thread to exit the event loop until the -// next call to Wait. Other events are automatically dispatched to -// their target. -class MacCarbonAppSocketServer : public MacBaseSocketServer { - public: - MacCarbonAppSocketServer(); - virtual ~MacCarbonAppSocketServer(); - - // SocketServer Interface - virtual bool Wait(int cms, bool process_io); - virtual void WakeUp(); - - private: - static OSStatus WakeUpEventHandler(EventHandlerCallRef next, EventRef event, - void *data); - static void TimerHandler(EventLoopTimerRef timer, void *data); - - EventQueueRef event_queue_; - EventHandlerRef event_handler_; - EventLoopTimerRef timer_; -}; - -#endif -} // namespace rtc - -#endif // WEBRTC_BASE_MACSOCKETSERVER_H__ diff --git a/include/webrtc/base/macutils.h b/include/webrtc/base/macutils.h index 35c3d18..fdcb3ee 100644 --- a/include/webrtc/base/macutils.h +++ b/include/webrtc/base/macutils.h @@ -12,9 +12,6 @@ #define WEBRTC_BASE_MACUTILS_H__ #include -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -#include -#endif #include namespace rtc { @@ -43,13 +40,7 @@ enum MacOSVersionName { kMacOSNewer, // 10.10+ }; -bool GetOSVersion(int* major, int* minor, int* bugfix); MacOSVersionName GetOSVersionName(); -bool GetQuickTimeVersion(std::string* version); - -// Runs the given apple script. Only supports scripts that does not -// require user interaction. -bool RunAppleScript(const std::string& script); #endif /////////////////////////////////////////////////////////////////////////////// diff --git a/include/webrtc/base/macwindowpicker.h b/include/webrtc/base/macwindowpicker.h deleted file mode 100644 index 99091a9..0000000 --- a/include/webrtc/base/macwindowpicker.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#ifndef WEBRTC_BASE_MACWINDOWPICKER_H_ -#define WEBRTC_BASE_MACWINDOWPICKER_H_ - -#include "webrtc/base/windowpicker.h" - -namespace rtc { - -class MacWindowPicker : public WindowPicker { - public: - MacWindowPicker(); - ~MacWindowPicker() override; - bool Init() override; - bool IsVisible(const WindowId& id) override; - bool MoveToFront(const WindowId& id) override; - bool GetWindowList(WindowDescriptionList* descriptions) override; - bool GetDesktopList(DesktopDescriptionList* descriptions) override; - bool GetDesktopDimensions(const DesktopId& id, - int* width, - int* height) override; - - private: - void* lib_handle_; - void* get_window_list_; - void* get_window_list_desc_; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_MACWINDOWPICKER_H_ diff --git a/include/webrtc/base/memory_usage.h b/include/webrtc/base/memory_usage.h new file mode 100644 index 0000000..2699082 --- /dev/null +++ b/include/webrtc/base/memory_usage.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_BASE_MEMORY_USAGE_H_ +#define WEBRTC_BASE_MEMORY_USAGE_H_ + +#include + +namespace rtc { + +// Returns current memory used by the process in bytes (working set size on +// Windows and resident set size on other platforms). +// Returns -1 on failure. +int64_t GetProcessResidentSizeBytes(); + +} // namespace rtc + +#endif // WEBRTC_BASE_MEMORY_USAGE_H_ diff --git a/include/webrtc/base/messagehandler.h b/include/webrtc/base/messagehandler.h index 6a3c2ef..72c0dc6 100644 --- a/include/webrtc/base/messagehandler.h +++ b/include/webrtc/base/messagehandler.h @@ -45,23 +45,13 @@ class FunctorMessageHandler : public MessageHandler { } const ReturnT& result() const { return result_; } - private: - FunctorT functor_; - ReturnT result_; -}; - -// Specialization for std::unique_ptr. -template -class FunctorMessageHandler, FunctorT> - : public MessageHandler { - public: - explicit FunctorMessageHandler(const FunctorT& functor) : functor_(functor) {} - virtual void OnMessage(Message* msg) { result_ = std::move(functor_()); } - std::unique_ptr result() { return std::move(result_); } + // Returns moved result. Should not call result() or MoveResult() again + // after this. + ReturnT MoveResult() { return std::move(result_); } private: FunctorT functor_; - std::unique_ptr result_; + ReturnT result_; }; // Specialization for ReturnT of void. @@ -74,6 +64,7 @@ class FunctorMessageHandler : public MessageHandler { functor_(); } void result() const {} + void MoveResult() {} private: FunctorT functor_; diff --git a/include/webrtc/base/messagequeue.h b/include/webrtc/base/messagequeue.h index 4aa96eb..20e2e13 100644 --- a/include/webrtc/base/messagequeue.h +++ b/include/webrtc/base/messagequeue.h @@ -17,11 +17,13 @@ #include #include #include +#include #include #include "webrtc/base/basictypes.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/base/location.h" #include "webrtc/base/messagehandler.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/sharedexclusivelock.h" @@ -49,6 +51,11 @@ class MessageQueueManager { // MessageQueueManager instance when necessary. static bool IsInitialized(); + // Mainly for testing purposes, for use with a simulated clock. + // Ensures that all message queues have processed delayed messages + // up until the current point in time. + static void ProcessAllMessageQueues(); + private: static MessageQueueManager* Instance(); @@ -58,11 +65,15 @@ class MessageQueueManager { void AddInternal(MessageQueue *message_queue); void RemoveInternal(MessageQueue *message_queue); void ClearInternal(MessageHandler *handler); + void ProcessAllMessageQueuesInternal(); static MessageQueueManager* instance_; // This list contains all live MessageQueues. - std::vector message_queues_; + std::vector message_queues_ GUARDED_BY(crit_); + + // Acquire this with DebugNonReentrantCritScope. CriticalSection crit_; + bool locked_ GUARDED_BY(crit_); }; // Derive from this for specialized data @@ -88,10 +99,21 @@ class TypedMessageData : public MessageData { template class ScopedMessageData : public MessageData { public: - explicit ScopedMessageData(T* data) : data_(data) { } + explicit ScopedMessageData(std::unique_ptr data) + : data_(std::move(data)) {} + // Deprecated. + // TODO(deadbeef): Remove this once downstream applications stop using it. + explicit ScopedMessageData(T* data) : data_(data) {} + // Deprecated. + // TODO(deadbeef): Returning a reference to a unique ptr? Why. Get rid of + // this once downstream applications stop using it, then rename inner_data to + // just data. const std::unique_ptr& data() const { return data_; } std::unique_ptr& data() { return data_; } + const T& inner_data() const { return *data_; } + T& inner_data() { return *data_; } + private: std::unique_ptr data_; }; @@ -132,13 +154,13 @@ const uint32_t MQID_DISPOSE = static_cast(-2); // No destructor struct Message { - Message() { - memset(this, 0, sizeof(*this)); - } + Message() + : phandler(nullptr), message_id(0), pdata(nullptr), ts_sensitive(0) {} inline bool Match(MessageHandler* handler, uint32_t id) const { - return (handler == NULL || handler == phandler) - && (id == MQID_ANY || id == message_id); + return (handler == nullptr || handler == phandler) && + (id == MQID_ANY || id == message_id); } + Location posted_from; MessageHandler *phandler; uint32_t message_id; MessageData *pdata; @@ -152,7 +174,10 @@ typedef std::list MessageList; class DelayedMessage { public: - DelayedMessage(int delay, int64_t trigger, uint32_t num, const Message& msg) + DelayedMessage(int64_t delay, + int64_t trigger, + uint32_t num, + const Message& msg) : cmsDelay_(delay), msTrigger_(trigger), num_(num), msg_(msg) {} bool operator< (const DelayedMessage& dmsg) const { @@ -160,7 +185,7 @@ class DelayedMessage { || ((dmsg.msTrigger_ == msTrigger_) && (dmsg.num_ < num_)); } - int cmsDelay_; // for debugging + int64_t cmsDelay_; // for debugging int64_t msTrigger_; uint32_t num_; Message msg_; @@ -196,6 +221,10 @@ class MessageQueue { virtual void Quit(); virtual bool IsQuitting(); virtual void Restart(); + // Not all message queues actually process messages (such as SignalThread). + // In those cases, it's important to know, before posting, that it won't be + // Processed. Normally, this would be true until IsQuitting() is true. + virtual bool IsProcessingMessages(); // Get() will process I/O until: // 1) A message is available (returns true) @@ -204,26 +233,30 @@ class MessageQueue { virtual bool Get(Message *pmsg, int cmsWait = kForever, bool process_io = true); virtual bool Peek(Message *pmsg, int cmsWait = 0); - virtual void Post(MessageHandler* phandler, + virtual void Post(const Location& posted_from, + MessageHandler* phandler, uint32_t id = 0, - MessageData* pdata = NULL, + MessageData* pdata = nullptr, bool time_sensitive = false); - virtual void PostDelayed(int cmsDelay, + virtual void PostDelayed(const Location& posted_from, + int cmsDelay, MessageHandler* phandler, uint32_t id = 0, - MessageData* pdata = NULL); - virtual void PostAt(int64_t tstamp, + MessageData* pdata = nullptr); + virtual void PostAt(const Location& posted_from, + int64_t tstamp, MessageHandler* phandler, uint32_t id = 0, - MessageData* pdata = NULL); + MessageData* pdata = nullptr); // TODO(honghaiz): Remove this when all the dependencies are removed. - virtual void PostAt(uint32_t tstamp, + virtual void PostAt(const Location& posted_from, + uint32_t tstamp, MessageHandler* phandler, uint32_t id = 0, - MessageData* pdata = NULL); + MessageData* pdata = nullptr); virtual void Clear(MessageHandler* phandler, uint32_t id = MQID_ANY, - MessageList* removed = NULL); + MessageList* removed = nullptr); virtual void Dispatch(Message *pmsg); virtual void ReceiveSends(); @@ -239,7 +272,7 @@ class MessageQueue { // Internally posts a message which causes the doomed object to be deleted template void Dispose(T* doomed) { if (doomed) { - Post(NULL, MQID_DISPOSE, new DisposeData(doomed)); + Post(RTC_FROM_HERE, nullptr, MQID_DISPOSE, new DisposeData(doomed)); } } @@ -254,7 +287,8 @@ class MessageQueue { void reheap() { make_heap(c.begin(), c.end(), comp); } }; - void DoDelayPost(int cmsDelay, + void DoDelayPost(const Location& posted_from, + int64_t cmsDelay, int64_t tstamp, MessageHandler* phandler, uint32_t id, @@ -270,7 +304,6 @@ class MessageQueue { void WakeUpSocketServer(); - bool fStop_; bool fPeekKeep_; Message msgPeek_; MessageList msgq_ GUARDED_BY(crit_); @@ -281,6 +314,8 @@ class MessageQueue { bool fDestroyed_; private: + volatile int stop_; + // The SocketServer might not be owned by MessageQueue. SocketServer* ss_ GUARDED_BY(ss_lock_); // Used if SocketServer ownership lies with |this|. diff --git a/include/webrtc/base/mod_ops.h b/include/webrtc/base/mod_ops.h index 74bd905..7ce100e 100644 --- a/include/webrtc/base/mod_ops.h +++ b/include/webrtc/base/mod_ops.h @@ -43,7 +43,7 @@ inline unsigned long Subtract(unsigned long a, unsigned long b) { // NOLINT // uint8_t x = 253; // uint8_t y = 2; // -// ForwardDiff(x, y) == 4 +// ForwardDiff(x, y) == 5 // // 252 253 254 255 0 1 2 3 // ################################################# diff --git a/include/webrtc/base/multipart.h b/include/webrtc/base/multipart.h deleted file mode 100644 index 9ae3ca2..0000000 --- a/include/webrtc/base/multipart.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_MULTIPART_H__ -#define WEBRTC_BASE_MULTIPART_H__ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/base/stream.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// MultipartStream - Implements an RFC2046 multipart stream by concatenating -// the supplied parts together, and adding the correct boundaries. -/////////////////////////////////////////////////////////////////////////////// - -class MultipartStream : public StreamInterface, public sigslot::has_slots<> { - public: - MultipartStream(const std::string& type, const std::string& boundary); - ~MultipartStream() override; - - void GetContentType(std::string* content_type); - - // Note: If content_disposition and/or content_type are the empty string, - // they will be omitted. - bool AddPart(StreamInterface* data_stream, - const std::string& content_disposition, - const std::string& content_type); - bool AddPart(const std::string& data, - const std::string& content_disposition, - const std::string& content_type); - void EndParts(); - - // Calculates the size of a part before actually adding the part. - size_t GetPartSize(const std::string& data, - const std::string& content_disposition, - const std::string& content_type) const; - size_t GetEndPartSize() const; - - // StreamInterface - StreamState GetState() const override; - StreamResult Read(void* buffer, - size_t buffer_len, - size_t* read, - int* error) override; - StreamResult Write(const void* data, - size_t data_len, - size_t* written, - int* error) override; - void Close() override; - bool SetPosition(size_t position) override; - bool GetPosition(size_t* position) const override; - bool GetSize(size_t* size) const override; - bool GetAvailable(size_t* size) const override; - - private: - typedef std::vector PartList; - - // StreamInterface Slots - void OnEvent(StreamInterface* stream, int events, int error); - - std::string type_, boundary_; - PartList parts_; - bool adding_; - size_t current_; // The index into parts_ of the current read position. - size_t position_; // The current read position in bytes. - - RTC_DISALLOW_COPY_AND_ASSIGN(MultipartStream); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_MULTIPART_H__ diff --git a/include/webrtc/base/network.h b/include/webrtc/base/network.h index a41da4a..52d7d35 100644 --- a/include/webrtc/base/network.h +++ b/include/webrtc/base/network.h @@ -11,13 +11,14 @@ #ifndef WEBRTC_BASE_NETWORK_H_ #define WEBRTC_BASE_NETWORK_H_ +#include + #include #include #include #include #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/ipaddress.h" #include "webrtc/base/networkmonitor.h" #include "webrtc/base/messagehandler.h" @@ -37,6 +38,11 @@ class Network; class NetworkMonitorInterface; class Thread; +static const uint16_t kNetworkCostMax = 999; +static const uint16_t kNetworkCostHigh = 900; +static const uint16_t kNetworkCostUnknown = 50; +static const uint16_t kNetworkCostLow = 10; +static const uint16_t kNetworkCostMin = 0; // By default, ignore loopback interfaces on the host. const int kDefaultNetworkIgnoreMask = ADAPTER_TYPE_LOOPBACK; @@ -58,6 +64,13 @@ class DefaultLocalAddressProvider { // Generic network manager interface. It provides list of local // networks. +// +// Every method of NetworkManager (including the destructor) must be called on +// the same thread, except for the constructor which may be called on any +// thread. +// +// This allows constructing a NetworkManager subclass on one thread and +// passing it into an object that uses it on a different thread. class NetworkManager : public DefaultLocalAddressProvider { public: typedef std::vector NetworkList; @@ -80,6 +93,10 @@ class NetworkManager : public DefaultLocalAddressProvider { // Indicates a failure when getting list of network interfaces. sigslot::signal0<> SignalError; + // This should be called on the NetworkManager's thread before the + // NetworkManager is used. Subclasses may override this if necessary. + virtual void Initialize() {} + // Start/Stop monitoring of network interfaces // list. SignalNetworksChanged or SignalError is emitted immediately // after StartUpdating() is called. After that SignalNetworksChanged @@ -124,8 +141,9 @@ class NetworkManagerBase : public NetworkManager { NetworkManagerBase(); ~NetworkManagerBase() override; - void GetNetworks(std::vector* networks) const override; + void GetNetworks(NetworkList* networks) const override; void GetAnyAddressNetworks(NetworkList* networks) override; + // Defaults to true. bool ipv6_enabled() const { return ipv6_enabled_; } void set_ipv6_enabled(bool enabled) { ipv6_enabled_ = enabled; } @@ -249,6 +267,8 @@ class BasicNetworkManager : public NetworkManagerBase, // Only updates the networks; does not reschedule the next update. void UpdateNetworksOnce(); + AdapterType GetAdapterTypeFromName(const char* network_name) const; + Thread* thread_; bool sent_first_update_; int start_count_; @@ -272,7 +292,7 @@ class Network { AdapterType type); ~Network(); - sigslot::signal1 SignalInactive; + sigslot::signal1 SignalTypeChanged; const DefaultLocalAddressProvider* default_local_address_provider() { return default_local_address_provider_; @@ -344,8 +364,28 @@ class Network { void set_ignored(bool ignored) { ignored_ = ignored; } AdapterType type() const { return type_; } - void set_type(AdapterType type) { type_ = type; } + void set_type(AdapterType type) { + if (type_ == type) { + return; + } + type_ = type; + SignalTypeChanged(this); + } + uint16_t GetCost() const { + switch (type_) { + case rtc::ADAPTER_TYPE_ETHERNET: + case rtc::ADAPTER_TYPE_LOOPBACK: + return kNetworkCostMin; + case rtc::ADAPTER_TYPE_WIFI: + case rtc::ADAPTER_TYPE_VPN: + return kNetworkCostLow; + case rtc::ADAPTER_TYPE_CELLULAR: + return kNetworkCostHigh; + default: + return kNetworkCostUnknown; + } + } // A unique id assigned by the network manager, which may be signaled // to the remote side in the candidate. uint16_t id() const { return id_; } @@ -359,12 +399,8 @@ class Network { // it inactive, so that we can detect network changes properly. bool active() const { return active_; } void set_active(bool active) { - if (active_ == active) { - return; - } - active_ = active; - if (!active) { - SignalInactive(this); + if (active_ != active) { + active_ = active; } } diff --git a/include/webrtc/base/networkmonitor.h b/include/webrtc/base/networkmonitor.h index 5459cd6..72b07b4 100644 --- a/include/webrtc/base/networkmonitor.h +++ b/include/webrtc/base/networkmonitor.h @@ -19,13 +19,12 @@ namespace rtc { class IPAddress; -// Error values are negative. -enum NetworkBindingResults { - NETWORK_BIND_SUCCESS = 0, // No error - NETWORK_BIND_FAILURE = -1, // Generic error - NETWORK_BIND_NOT_IMPLEMENTED = -2, - NETWORK_BIND_ADDRESS_NOT_FOUND = -3, - NETWORK_BIND_NETWORK_CHANGED = -4 +enum class NetworkBindingResult { + SUCCESS = 0, // No error + FAILURE = -1, // Generic error + NOT_IMPLEMENTED = -2, + ADDRESS_NOT_FOUND = -3, + NETWORK_CHANGED = -4 }; enum AdapterType { @@ -44,7 +43,9 @@ class NetworkBinderInterface { // packets on the socket |socket_fd| will be sent via that network. // This is needed because some operating systems (like Android) require a // special bind call to put packets on a non-default network interface. - virtual int BindSocketToNetwork(int socket_fd, const IPAddress& address) = 0; + virtual NetworkBindingResult BindSocketToNetwork( + int socket_fd, + const IPAddress& address) = 0; virtual ~NetworkBinderInterface() {} }; diff --git a/include/webrtc/base/networkroute.h b/include/webrtc/base/networkroute.h index 52fa6d6..a34e6d3 100644 --- a/include/webrtc/base/networkroute.h +++ b/include/webrtc/base/networkroute.h @@ -30,10 +30,11 @@ struct NetworkRoute { last_sent_packet_id(-1) {} // The route is connected if the local and remote network ids are provided. - NetworkRoute(uint16_t local_net_id, + NetworkRoute(bool connected, + uint16_t local_net_id, uint16_t remote_net_id, int last_packet_id) - : connected(true), + : connected(connected), local_network_id(local_net_id), remote_network_id(remote_net_id), last_sent_packet_id(last_packet_id) {} diff --git a/include/webrtc/base/exp_filter.h b/include/webrtc/base/numerics/exp_filter.h similarity index 83% rename from include/webrtc/base/exp_filter.h rename to include/webrtc/base/numerics/exp_filter.h index 174159b..2361702 100644 --- a/include/webrtc/base/exp_filter.h +++ b/include/webrtc/base/numerics/exp_filter.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_BASE_EXP_FILTER_H_ -#define WEBRTC_BASE_EXP_FILTER_H_ +#ifndef WEBRTC_BASE_NUMERICS_EXP_FILTER_H_ +#define WEBRTC_BASE_NUMERICS_EXP_FILTER_H_ namespace rtc { @@ -20,8 +20,7 @@ class ExpFilter { public: static const float kValueUndefined; - explicit ExpFilter(float alpha, float max = kValueUndefined) - : max_(max) { + explicit ExpFilter(float alpha, float max = kValueUndefined) : max_(max) { Reset(alpha); } @@ -40,10 +39,10 @@ class ExpFilter { void UpdateBase(float alpha); private: - float alpha_; // Filter factor base. + float alpha_; // Filter factor base. float filtered_; // Current filter output. const float max_; }; } // namespace rtc -#endif // WEBRTC_BASE_EXP_FILTER_H_ +#endif // WEBRTC_BASE_NUMERICS_EXP_FILTER_H_ diff --git a/include/webrtc/base/numerics/percentile_filter.h b/include/webrtc/base/numerics/percentile_filter.h new file mode 100644 index 0000000..638857d --- /dev/null +++ b/include/webrtc/base/numerics/percentile_filter.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_NUMERICS_PERCENTILE_FILTER_H_ +#define WEBRTC_BASE_NUMERICS_PERCENTILE_FILTER_H_ + +#include + +#include +#include + +#include "webrtc/base/checks.h" + +namespace webrtc { + +// Class to efficiently get the percentile value from a group of observations. +// The percentile is the value below which a given percentage of the +// observations fall. +template +class PercentileFilter { + public: + // Construct filter. |percentile| should be between 0 and 1. + explicit PercentileFilter(float percentile); + + // Insert one observation. The complexity of this operation is logarithmic in + // the size of the container. + void Insert(const T& value); + + // Remove one observation or return false if |value| doesn't exist in the + // container. The complexity of this operation is logarithmic in the size of + // the container. + bool Erase(const T& value); + + // Get the percentile value. The complexity of this operation is constant. + T GetPercentileValue() const; + + private: + // Update iterator and index to point at target percentile value. + void UpdatePercentileIterator(); + + const float percentile_; + std::multiset set_; + // Maintain iterator and index of current target percentile value. + typename std::multiset::iterator percentile_it_; + int64_t percentile_index_; +}; + +template +PercentileFilter::PercentileFilter(float percentile) + : percentile_(percentile), + percentile_it_(set_.begin()), + percentile_index_(0) { + RTC_CHECK_GE(percentile, 0.0f); + RTC_CHECK_LE(percentile, 1.0f); +} + +template +void PercentileFilter::Insert(const T& value) { + // Insert element at the upper bound. + set_.insert(value); + if (set_.size() == 1u) { + // First element inserted - initialize percentile iterator and index. + percentile_it_ = set_.begin(); + percentile_index_ = 0; + } else if (value < *percentile_it_) { + // If new element is before us, increment |percentile_index_|. + ++percentile_index_; + } + UpdatePercentileIterator(); +} + +template +bool PercentileFilter::Erase(const T& value) { + typename std::multiset::const_iterator it = set_.lower_bound(value); + // Ignore erase operation if the element is not present in the current set. + if (it == set_.end() || *it != value) + return false; + if (it == percentile_it_) { + // If same iterator, update to the following element. Index is not + // affected. + percentile_it_ = set_.erase(it); + } else { + set_.erase(it); + // If erased element was before us, decrement |percentile_index_|. + if (value <= *percentile_it_) + --percentile_index_; + } + UpdatePercentileIterator(); + return true; +} + +template +void PercentileFilter::UpdatePercentileIterator() { + if (set_.empty()) + return; + const int64_t index = static_cast(percentile_ * (set_.size() - 1)); + std::advance(percentile_it_, index - percentile_index_); + percentile_index_ = index; +} + +template +T PercentileFilter::GetPercentileValue() const { + return set_.empty() ? 0 : *percentile_it_; +} + +} // namespace webrtc + +#endif // WEBRTC_BASE_NUMERICS_PERCENTILE_FILTER_H_ diff --git a/include/webrtc/base/openssladapter.h b/include/webrtc/base/openssladapter.h index cdf45e6..554627f 100644 --- a/include/webrtc/base/openssladapter.h +++ b/include/webrtc/base/openssladapter.h @@ -37,8 +37,11 @@ class OpenSSLAdapter : public SSLAdapter, public MessageHandler { int StartSSL(const char* hostname, bool restartable) override; int Send(const void* pv, size_t cb) override; int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override; - int Recv(void* pv, size_t cb) override; - int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override; + int Recv(void* pv, size_t cb, int64_t* timestamp) override; + int RecvFrom(void* pv, + size_t cb, + SocketAddress* paddr, + int64_t* timestamp) override; int Close() override; // Note that the socket returns ST_CONNECTING while SSL is being negotiated. diff --git a/include/webrtc/base/opensslidentity.h b/include/webrtc/base/opensslidentity.h index 316572c..84716d1 100644 --- a/include/webrtc/base/opensslidentity.h +++ b/include/webrtc/base/opensslidentity.h @@ -17,7 +17,7 @@ #include #include -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/sslidentity.h" @@ -30,7 +30,7 @@ namespace rtc { class OpenSSLKeyPair { public: explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) { - ASSERT(pkey_ != NULL); + RTC_DCHECK(pkey_ != nullptr); } static OpenSSLKeyPair* Generate(const KeyParams& key_params); diff --git a/include/webrtc/base/opensslstreamadapter.h b/include/webrtc/base/opensslstreamadapter.h index 1e90bac..16b62eb 100644 --- a/include/webrtc/base/opensslstreamadapter.h +++ b/include/webrtc/base/opensslstreamadapter.h @@ -27,29 +27,26 @@ typedef struct x509_store_ctx_st X509_STORE_CTX; namespace rtc { // This class was written with OpenSSLAdapter (a socket adapter) as a -// starting point. It has similar structure and functionality, with -// the peer-to-peer mode added. +// starting point. It has similar structure and functionality, but uses a +// "peer-to-peer" mode, verifying the peer's certificate using a digest +// sent over a secure signaling channel. // // Static methods to initialize and deinit the SSL library are in -// OpenSSLAdapter. This class also uses -// OpenSSLAdapter::custom_verify_callback_ (a static field). These -// should probably be moved out to a neutral class. +// OpenSSLAdapter. These should probably be moved out to a neutral class. // -// In a few cases I have factored out some OpenSSLAdapter code into -// static methods so it can be reused from this class. Eventually that -// code should probably be moved to a common support -// class. Unfortunately there remain a few duplicated sections of -// code. I have not done more restructuring because I did not want to -// affect existing code that uses OpenSSLAdapter. +// In a few cases I have factored out some OpenSSLAdapter code into static +// methods so it can be reused from this class. Eventually that code should +// probably be moved to a common support class. Unfortunately there remain a +// few duplicated sections of code. I have not done more restructuring because +// I did not want to affect existing code that uses OpenSSLAdapter. // -// This class does not support the SSL connection restart feature -// present in OpenSSLAdapter. I am not entirely sure how the feature -// is useful and I am not convinced that it works properly. +// This class does not support the SSL connection restart feature present in +// OpenSSLAdapter. I am not entirely sure how the feature is useful and I am +// not convinced that it works properly. // -// This implementation is careful to disallow data exchange after an -// SSL error, and it has an explicit SSL_CLOSED state. It should not -// be possible to send any data in clear after one of the StartSSL -// methods has been called. +// This implementation is careful to disallow data exchange after an SSL error, +// and it has an explicit SSL_CLOSED state. It should not be possible to send +// any data in clear after one of the StartSSL methods has been called. // Look in sslstreamadapter.h for documentation of the methods. @@ -66,16 +63,20 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { // Default argument is for compatibility void SetServerRole(SSLRole role = SSL_SERVER) override; - bool SetPeerCertificateDigest(const std::string& digest_alg, - const unsigned char* digest_val, - size_t digest_len) override; + bool SetPeerCertificateDigest( + const std::string& digest_alg, + const unsigned char* digest_val, + size_t digest_len, + SSLPeerCertificateDigestError* error = nullptr) override; std::unique_ptr GetPeerCertificate() const override; - int StartSSLWithServer(const char* server_name) override; - int StartSSLWithPeer() override; + // Goes from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT, depending + // on whether the underlying stream is already open or not. + int StartSSL() override; void SetMode(SSLMode mode) override; void SetMaxProtocolVersion(SSLProtocolVersion version) override; + void SetInitialRetransmissionTimeout(int timeout_ms) override; StreamResult Read(void* data, size_t data_len, @@ -107,14 +108,18 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { bool SetDtlsSrtpCryptoSuites(const std::vector& crypto_suites) override; bool GetDtlsSrtpCryptoSuite(int* crypto_suite) override; - // Capabilities interfaces - static bool HaveDtls(); - static bool HaveDtlsSrtp(); - static bool HaveExporter(); + bool IsTlsConnected() override; + + // Capabilities interfaces. + static bool IsBoringSsl(); static bool IsAcceptableCipher(int cipher, KeyType key_type); static bool IsAcceptableCipher(const std::string& cipher, KeyType key_type); + // Use our timeutils.h source of timing in BoringSSL, allowing us to test + // using a fake clock. + static void enable_time_callback_for_testing(); + protected: void OnEvent(StreamInterface* stream, int events, int err) override; @@ -137,10 +142,6 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { // on some other error cases, so it can't really be interpreted // unfortunately. - // Go from state SSL_NONE to either SSL_CONNECTING or SSL_WAIT, - // depending on whether the underlying stream is already open or - // not. - int StartSSL(); // Prepare SSL library, state is SSL_CONNECTING. int BeginSSL(); // Perform SSL negotiation steps. @@ -152,8 +153,11 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { // raised on the stream with the specified error. // A 0 error means a graceful close, otherwise there is not really enough // context to interpret the error code. - void Error(const char* context, int err, bool signal); - void Cleanup(); + // |alert| indicates an alert description (one of the SSL_AD constants) to + // send to the remote endpoint when closing the association. If 0, a normal + // shutdown will be performed. + void Error(const char* context, int err, uint8_t alert, bool signal); + void Cleanup(uint8_t alert); // Override MessageHandler void OnMessage(Message* msg) override; @@ -163,16 +167,23 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { // SSL library configuration SSL_CTX* SetupSSLContext(); - // SSL verification check - bool SSLPostConnectionCheck(SSL* ssl, const char* server_name, - const X509* peer_cert, - const std::string& peer_digest); + // Verify the peer certificate matches the signaled digest. + bool VerifyPeerCertificate(); // SSL certification verification error handler, called back from // the openssl library. Returns an int interpreted as a boolean in // the C style: zero means verification failure, non-zero means // passed. static int SSLVerifyCallback(int ok, X509_STORE_CTX* store); + bool waiting_to_verify_peer_certificate() const { + return client_auth_enabled() && !peer_certificate_verified_; + } + + bool has_peer_certificate_digest() const { + return !peer_certificate_digest_algorithm_.empty() && + !peer_certificate_digest_value_.empty(); + } + SSLState state_; SSLRole role_; int ssl_error_code_; // valid when state_ == SSL_ERROR or SSL_CLOSED @@ -184,22 +195,16 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { SSL* ssl_; SSL_CTX* ssl_ctx_; - // Our key and certificate, mostly useful in peer-to-peer mode. + // Our key and certificate. std::unique_ptr identity_; - // in traditional mode, the server name that the server's certificate - // must specify. Empty in peer-to-peer mode. - std::string ssl_server_name_; - // The certificate that the peer must present or did present. Initially - // null in traditional mode, until the connection is established. + // The certificate that the peer presented. Initially null, until the + // connection is established. std::unique_ptr peer_certificate_; - // In peer-to-peer mode, the digest of the certificate that - // the peer must present. + bool peer_certificate_verified_ = false; + // The digest of the certificate that the peer must present. Buffer peer_certificate_digest_value_; std::string peer_certificate_digest_algorithm_; - // OpenSSLAdapter::custom_verify_callback_ result - bool custom_verification_succeeded_; - // The DtlsSrtp ciphers std::string srtp_ciphers_; @@ -208,6 +213,10 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { // Max. allowed protocol version SSLProtocolVersion ssl_max_version_; + + // A 50-ms initial timeout ensures rapid setup on fast connections, but may + // be too aggressive for low bandwidth links. + int dtls_handshake_timeout_ms_ = 50; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/include/webrtc/base/optional.h b/include/webrtc/base/optional.h index 25cfbfe..c8ed069 100644 --- a/include/webrtc/base/optional.h +++ b/include/webrtc/base/optional.h @@ -15,10 +15,41 @@ #include #include +#ifdef UNIT_TEST +#include +#include +#endif // UNIT_TEST + +#include "webrtc/base/array_view.h" #include "webrtc/base/checks.h" +#include "webrtc/base/sanitizer.h" namespace rtc { +namespace optional_internal { + +#if RTC_HAS_ASAN + +// This is a non-inlined function. The optimizer can't see inside it. It +// prevents the compiler from generating optimized code that reads value_ even +// if it is unset. Although safe, this causes memory sanitizers to complain. +void* FunctionThatDoesNothingImpl(void*); + +template +inline T* FunctionThatDoesNothing(T* x) { + return reinterpret_cast( + FunctionThatDoesNothingImpl(reinterpret_cast(x))); +} + +#else + +template +inline T* FunctionThatDoesNothing(T* x) { return x; } + +#endif + +} // namespace optional_internal + // Simple std::optional-wannabe. It either contains a T or not. // // A moved-from Optional may only be destroyed, and assigned to if T allows @@ -53,13 +84,21 @@ namespace rtc { // might make sense, but any larger parse job is probably going to need to // tell the caller what the problem was, not just that there was one. // +// - As a non-mutable function argument. When you want to pass a value of a +// type T that can fail to be there, const T* is almost always both fastest +// and cleanest. (If you're *sure* that the the caller will always already +// have an Optional, const Optional& is slightly faster than const T*, +// but this is a micro-optimization. In general, stick to const T*.) +// // TODO(kwiberg): Get rid of this class when the standard library has // std::optional (and we're allowed to use it). template class Optional final { public: // Construct an empty Optional. - Optional() : has_value_(false) {} + Optional() : has_value_(false), empty_('\0') { + PoisonValue(); + } // Construct an Optional that contains a value. explicit Optional(const T& value) : has_value_(true) { @@ -73,6 +112,8 @@ class Optional final { Optional(const Optional& m) : has_value_(m.has_value_) { if (has_value_) new (&value_) T(m.value_); + else + PoisonValue(); } // Move constructor: if m has a value, moves the value from m, leaving m @@ -82,11 +123,15 @@ class Optional final { Optional(Optional&& m) : has_value_(m.has_value_) { if (has_value_) new (&value_) T(std::move(m.value_)); + else + PoisonValue(); } ~Optional() { if (has_value_) value_.~T(); + else + UnpoisonValue(); } // Copy assignment. Uses T's copy assignment if both sides have a value, T's @@ -96,12 +141,12 @@ class Optional final { if (has_value_) { value_ = m.value_; // T's copy assignment. } else { + UnpoisonValue(); new (&value_) T(m.value_); // T's copy constructor. has_value_ = true; } - } else if (has_value_) { - value_.~T(); - has_value_ = false; + } else { + reset(); } return *this; } @@ -114,12 +159,12 @@ class Optional final { if (has_value_) { value_ = std::move(m.value_); // T's move assignment. } else { + UnpoisonValue(); new (&value_) T(std::move(m.value_)); // T's move constructor. has_value_ = true; } - } else if (has_value_) { - value_.~T(); - has_value_ = false; + } else { + reset(); } return *this; } @@ -134,20 +179,43 @@ class Optional final { swap(m1.value_, m2.value_); } else { // Only m1 has a value: move it to m2. + m2.UnpoisonValue(); new (&m2.value_) T(std::move(m1.value_)); m1.value_.~T(); // Destroy the moved-from value. m1.has_value_ = false; m2.has_value_ = true; + m1.PoisonValue(); } } else if (m2.has_value_) { // Only m2 has a value: move it to m1. + m1.UnpoisonValue(); new (&m1.value_) T(std::move(m2.value_)); m2.value_.~T(); // Destroy the moved-from value. m1.has_value_ = true; m2.has_value_ = false; + m2.PoisonValue(); } } + // Destroy any contained value. Has no effect if we have no value. + void reset() { + if (!has_value_) + return; + value_.~T(); + has_value_ = false; + PoisonValue(); + } + + template + void emplace(Args&&... args) { + if (has_value_) + value_.~T(); + else + UnpoisonValue(); + new (&value_) T(std::forward(args)...); + has_value_ = true; + } + // Conversion to bool to test if we have a value. explicit operator bool() const { return has_value_; } @@ -171,24 +239,61 @@ class Optional final { // Dereference with a default value in case we don't have a value. const T& value_or(const T& default_val) const { - return has_value_ ? value_ : default_val; + // The no-op call prevents the compiler from generating optimized code that + // reads value_ even if !has_value_, but only if FunctionThatDoesNothing is + // not completely inlined; see its declaration.). + return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_) + : default_val; + } + + // Dereference and move value. + T MoveValue() { + RTC_DCHECK(has_value_); + return std::move(value_); } // Equality tests. Two Optionals are equal if they contain equivalent values, - // or - // if they're both empty. + // or if they're both empty. friend bool operator==(const Optional& m1, const Optional& m2) { return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_ : m1.has_value_ == m2.has_value_; } + friend bool operator==(const Optional& opt, const T& value) { + return opt.has_value_ && opt.value_ == value; + } + friend bool operator==(const T& value, const Optional& opt) { + return opt.has_value_ && value == opt.value_; + } + friend bool operator!=(const Optional& m1, const Optional& m2) { return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_ : m1.has_value_ != m2.has_value_; } + friend bool operator!=(const Optional& opt, const T& value) { + return !opt.has_value_ || opt.value_ != value; + } + friend bool operator!=(const T& value, const Optional& opt) { + return !opt.has_value_ || value != opt.value_; + } private: + // Tell sanitizers that value_ shouldn't be touched. + void PoisonValue() { + rtc::AsanPoison(rtc::MakeArrayView(&value_, 1)); + rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1)); + } + + // Tell sanitizers that value_ is OK to touch again. + void UnpoisonValue() { + rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1)); + } + bool has_value_; // True iff value_ contains a live value. union { + // empty_ exists only to make it possible to initialize the union, even when + // it doesn't contain any data. If the union goes uninitialized, it may + // trigger compiler warnings. + char empty_; // By placing value_ in a union, we get to manage its construction and // destruction manually: the Optional constructors won't automatically // construct it, and the Optional destructor won't automatically destroy @@ -198,6 +303,98 @@ class Optional final { }; }; +#ifdef UNIT_TEST +namespace optional_internal { + +// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T. +template +struct HasPrintTo { + private: + struct No {}; + + template + static auto Test(const T2& obj) + -> decltype(PrintTo(obj, std::declval())); + + template + static No Test(...); + + public: + static constexpr bool value = + !std::is_same(std::declval())), No>::value; +}; + +// Checks if there's a valid operator<<(std::ostream&, const T&) call for T. +template +struct HasOstreamOperator { + private: + struct No {}; + + template + static auto Test(const T2& obj) + -> decltype(std::declval() << obj); + + template + static No Test(...); + + public: + static constexpr bool value = + !std::is_same(std::declval())), No>::value; +}; + +// Prefer using PrintTo to print the object. +template +typename std::enable_if::value, void>::type OptionalPrintToHelper( + const T& value, + std::ostream* os) { + PrintTo(value, os); +} + +// Fall back to operator<<(std::ostream&, ...) if it exists. +template +typename std::enable_if::value && !HasPrintTo::value, + void>::type +OptionalPrintToHelper(const T& value, std::ostream* os) { + *os << value; +} + +inline void OptionalPrintObjectBytes(const unsigned char* bytes, + size_t size, + std::ostream* os) { + *os << "(bytes[i]); + } + *os << "]>"; +} + +// As a final back-up, just print the contents of the objcets byte-wise. +template +typename std::enable_if::value && !HasPrintTo::value, + void>::type +OptionalPrintToHelper(const T& value, std::ostream* os) { + OptionalPrintObjectBytes(reinterpret_cast(&value), + sizeof(value), os); +} + +} // namespace optional_internal + +// PrintTo is used by gtest to print out the results of tests. We want to ensure +// the object contained in an Optional can be printed out if it's set, while +// avoiding touching the object's storage if it is undefined. +template +void PrintTo(const rtc::Optional& opt, std::ostream* os) { + if (opt) { + optional_internal::OptionalPrintToHelper(*opt, os); + } else { + *os << ""; + } +} + +#endif // UNIT_TEST + } // namespace rtc #endif // WEBRTC_BASE_OPTIONAL_H_ diff --git a/include/webrtc/base/pathutils.h b/include/webrtc/base/pathutils.h index 2a0efa9..0aebcef 100644 --- a/include/webrtc/base/pathutils.h +++ b/include/webrtc/base/pathutils.h @@ -12,8 +12,8 @@ #define WEBRTC_BASE_PATHUTILS_H__ #include -// Temporary, until deprecated helpers are removed. -#include "webrtc/base/fileutils.h" + +#include "webrtc/base/checks.h" namespace rtc { @@ -66,8 +66,6 @@ class Pathname { // is always false. bool empty() const; - std::string url() const; - // Returns the folder and filename components. If the pathname is empty, // returns a string representing the current directory (as a relative path, // i.e., "."). @@ -108,63 +106,6 @@ class Pathname { char folder_delimiter_; }; -/////////////////////////////////////////////////////////////////////////////// -// Global Helpers (deprecated) -/////////////////////////////////////////////////////////////////////////////// - -inline void SetOrganizationName(const std::string& organization) { - Filesystem::SetOrganizationName(organization); -} -inline void SetApplicationName(const std::string& application) { - Filesystem::SetApplicationName(application); -} -inline void GetOrganizationName(std::string* organization) { - Filesystem::GetOrganizationName(organization); -} -inline void GetApplicationName(std::string* application) { - Filesystem::GetApplicationName(application); -} -inline bool CreateFolder(const Pathname& path) { - return Filesystem::CreateFolder(path); -} -inline bool FinishPath(Pathname& path, bool create, const std::string& append) { - if (!append.empty()) - path.AppendFolder(append); - return !create || CreateFolder(path); -} -// Note: this method uses the convention of / for the temporary -// folder. Filesystem uses /. We will be migrating exclusively -// to // eventually. Since these are temp folders, -// it's probably ok to orphan them during the transition. -inline bool GetTemporaryFolder(Pathname& path, bool create, - const std::string& append) { - std::string application_name; - Filesystem::GetApplicationName(&application_name); - ASSERT(!application_name.empty()); - return Filesystem::GetTemporaryFolder(path, create, &application_name) - && FinishPath(path, create, append); -} -inline bool GetAppDataFolder(Pathname& path, bool create, - const std::string& append) { - ASSERT(!create); // TODO: Support create flag on Filesystem::GetAppDataFolder. - return Filesystem::GetAppDataFolder(&path, true) - && FinishPath(path, create, append); -} -inline bool CleanupTemporaryFolder() { - Pathname path; - if (!GetTemporaryFolder(path, false, "")) - return false; - if (Filesystem::IsAbsent(path)) - return true; - if (!Filesystem::IsTemporaryPath(path)) { - ASSERT(false); - return false; - } - return Filesystem::DeleteFolderContents(path); -} - -/////////////////////////////////////////////////////////////////////////////// - } // namespace rtc #endif // WEBRTC_BASE_PATHUTILS_H__ diff --git a/include/webrtc/base/physicalsocketserver.h b/include/webrtc/base/physicalsocketserver.h index f5867d2..462fab2 100644 --- a/include/webrtc/base/physicalsocketserver.h +++ b/include/webrtc/base/physicalsocketserver.h @@ -14,7 +14,6 @@ #include #include -#include "webrtc/base/asyncfile.h" #include "webrtc/base/nethelpers.h" #include "webrtc/base/socketserver.h" #include "webrtc/base/criticalsection.h" @@ -79,8 +78,6 @@ class PhysicalSocketServer : public SocketServer { void Remove(Dispatcher* dispatcher); #if defined(WEBRTC_POSIX) - AsyncFile* CreateFile(int fd); - // Sets the function to be executed in response to the specified POSIX signal. // The function is executed from inside Wait() using the "self-pipe trick"-- // regardless of which thread receives the signal--and hence can safely @@ -143,8 +140,11 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> { size_t length, const SocketAddress& addr) override; - int Recv(void* buffer, size_t length) override; - int RecvFrom(void* buffer, size_t length, SocketAddress* out_addr) override; + int Recv(void* buffer, size_t length, int64_t* timestamp) override; + int RecvFrom(void* buffer, + size_t length, + SocketAddress* out_addr, + int64_t* timestamp) override; int Listen(int backlog) override; AsyncSocket* Accept(SocketAddress* out_addr) override; diff --git a/include/webrtc/base/platform_file.h b/include/webrtc/base/platform_file.h index 12e08e9..27accf0 100644 --- a/include/webrtc/base/platform_file.h +++ b/include/webrtc/base/platform_file.h @@ -12,9 +12,10 @@ #define WEBRTC_BASE_PLATFORM_FILE_H_ #include +#include #if defined(WEBRTC_WIN) -#include +#include "webrtc/base/win32.h" #endif namespace rtc { @@ -39,6 +40,17 @@ FILE* FdopenPlatformFileForWriting(PlatformFile file); // Use fclose instead. bool ClosePlatformFile(PlatformFile file); +// Removes a file in the filesystem. +bool RemoveFile(const std::string& path); + +// Opens a file for reading and writing. You might want to use base/file.h +// instead. +PlatformFile OpenPlatformFile(const std::string& path); + +// Creates a new file for reading and writing. If the file already exists it +// will be overwritten. You might want to use base/file.h instead. +PlatformFile CreatePlatformFile(const std::string& path); + } // namespace rtc #endif // WEBRTC_BASE_PLATFORM_FILE_H_ diff --git a/include/webrtc/base/platform_thread.h b/include/webrtc/base/platform_thread.h index d74aec2..ed26ca0 100644 --- a/include/webrtc/base/platform_thread.h +++ b/include/webrtc/base/platform_thread.h @@ -32,7 +32,8 @@ void SetCurrentThreadName(const char* name); // Callback function that the spawned thread will enter once spawned. // A return value of false is interpreted as that the function has no // more work to do and that the thread can be released. -typedef bool (*ThreadRunFunction)(void*); +typedef bool (*ThreadRunFunctionDeprecated)(void*); +typedef void (*ThreadRunFunction)(void*); enum ThreadPriority { #ifdef WEBRTC_WIN @@ -55,7 +56,13 @@ enum ThreadPriority { // called from the same thread, including instantiation. class PlatformThread { public: - PlatformThread(ThreadRunFunction func, void* obj, const char* thread_name); + PlatformThread(ThreadRunFunctionDeprecated func, + void* obj, + const char* thread_name); + PlatformThread(ThreadRunFunction func, + void* obj, + const char* thread_name, + ThreadPriority priority = kNormalPriority); virtual ~PlatformThread(); const std::string& name() const { return name_; } @@ -74,6 +81,7 @@ class PlatformThread { void Stop(); // Set the priority of the thread. Must be called when thread is running. + // TODO(tommi): Make private and only allow public support via ctor. bool SetPriority(ThreadPriority priority); protected: @@ -85,24 +93,28 @@ class PlatformThread { private: void Run(); - ThreadRunFunction const run_function_; + ThreadRunFunctionDeprecated const run_function_deprecated_ = nullptr; + ThreadRunFunction const run_function_ = nullptr; + const ThreadPriority priority_ = kNormalPriority; void* const obj_; // TODO(pbos): Make sure call sites use string literals and update to a const // char* instead of a std::string. const std::string name_; rtc::ThreadChecker thread_checker_; + rtc::ThreadChecker spawned_thread_checker_; #if defined(WEBRTC_WIN) static DWORD WINAPI StartThread(void* param); - bool stop_; - HANDLE thread_; - DWORD thread_id_; + bool stop_ = false; + HANDLE thread_ = nullptr; + DWORD thread_id_ = 0; #else static void* StartThread(void* param); - rtc::Event stop_event_; - - pthread_t thread_; + // An atomic flag that we use to stop the thread. Only modified on the + // controlling thread and checked on the worker thread. + volatile int stop_flag_ = 0; + pthread_t thread_ = 0; #endif // defined(WEBRTC_WIN) RTC_DISALLOW_COPY_AND_ASSIGN(PlatformThread); }; diff --git a/include/webrtc/base/posix.h b/include/webrtc/base/posix.h deleted file mode 100644 index 8d1c2b1..0000000 --- a/include/webrtc/base/posix.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_POSIX_H_ -#define WEBRTC_BASE_POSIX_H_ - -namespace rtc { - -// Runs the given executable name as a daemon, so that it executes concurrently -// with this process. Upon completion, the daemon process will automatically be -// reaped by init(8), so an error exit status or a failure to start the -// executable are not reported. Returns true if the daemon process was forked -// successfully, else false. -bool RunAsDaemon(const char *file, const char *const argv[]); - -} // namespace rtc - -#endif // WEBRTC_BASE_POSIX_H_ diff --git a/include/webrtc/base/profiler.h b/include/webrtc/base/profiler.h deleted file mode 100644 index 4dd35f5..0000000 --- a/include/webrtc/base/profiler.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2013 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// A simple wall-clock profiler for instrumented code. -// Example: -// void MyLongFunction() { -// PROFILE_F(); // Time the execution of this function. -// // Do something -// { // Time just what is in this scope. -// PROFILE("My event"); -// // Do something else -// } -// } -// Another example: -// void StartAsyncProcess() { -// PROFILE_START("My async event"); -// DoSomethingAsyncAndThenCall(&Callback); -// } -// void Callback() { -// PROFILE_STOP("My async event"); -// // Handle callback. -// } - -#ifndef WEBRTC_BASE_PROFILER_H_ -#define WEBRTC_BASE_PROFILER_H_ - -#include -#include - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/common.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/logging.h" -#include "webrtc/base/sharedexclusivelock.h" - -// Profiling could be switched via a build flag, but for now, it's always on. -#ifndef ENABLE_PROFILING -#define ENABLE_PROFILING -#endif - -#ifdef ENABLE_PROFILING - -#define UV_HELPER2(x) _uv_ ## x -#define UV_HELPER(x) UV_HELPER2(x) -#define UNIQUE_VAR UV_HELPER(__LINE__) - -// Profiles the current scope. -#define PROFILE(msg) rtc::ProfilerScope UNIQUE_VAR(msg) -// When placed at the start of a function, profiles the current function. -#define PROFILE_F() PROFILE(__FUNCTION__) -// Reports current timings to the log at severity |sev|. -#define PROFILE_DUMP_ALL(sev) \ - rtc::Profiler::Instance()->ReportAllToLog(__FILE__, __LINE__, sev) -// Reports current timings for all events whose names are prefixed by |prefix| -// to the log at severity |sev|. Using a unique event name as |prefix| will -// report only that event. -#define PROFILE_DUMP(sev, prefix) \ - rtc::Profiler::Instance()->ReportToLog(__FILE__, __LINE__, sev, prefix) -// Starts and stops a profile event. Useful when an event is not easily -// captured within a scope (eg, an async call with a callback when done). -#define PROFILE_START(msg) rtc::Profiler::Instance()->StartEvent(msg) -#define PROFILE_STOP(msg) rtc::Profiler::Instance()->StopEvent(msg) -// TODO(ryanpetrie): Consider adding PROFILE_DUMP_EVERY(sev, iterations) - -#undef UV_HELPER2 -#undef UV_HELPER -#undef UNIQUE_VAR - -#else // ENABLE_PROFILING - -#define PROFILE(msg) (void)0 -#define PROFILE_F() (void)0 -#define PROFILE_DUMP_ALL(sev) (void)0 -#define PROFILE_DUMP(sev, prefix) (void)0 -#define PROFILE_START(msg) (void)0 -#define PROFILE_STOP(msg) (void)0 - -#endif // ENABLE_PROFILING - -namespace rtc { - -// Tracks information for one profiler event. -class ProfilerEvent { - public: - ProfilerEvent(); - void Start(); - void Stop(); - void Stop(uint64_t stop_time); - double standard_deviation() const; - double total_time() const { return total_time_; } - double mean() const { return mean_; } - double minimum() const { return minimum_; } - double maximum() const { return maximum_; } - int event_count() const { return event_count_; } - bool is_started() const { return start_count_ > 0; } - - private: - uint64_t current_start_time_; - double total_time_; - double mean_; - double sum_of_squared_differences_; - double minimum_; - double maximum_; - int start_count_; - int event_count_; -}; - -// Singleton that owns ProfilerEvents and reports results. Prefer to use -// macros, defined above, rather than directly calling Profiler methods. -class Profiler { - public: - ~Profiler(); - void StartEvent(const std::string& event_name); - void StopEvent(const std::string& event_name); - void ReportToLog(const char* file, int line, LoggingSeverity severity_to_use, - const std::string& event_prefix); - void ReportAllToLog(const char* file, int line, - LoggingSeverity severity_to_use); - const ProfilerEvent* GetEvent(const std::string& event_name) const; - // Clears all _stopped_ events. Returns true if _all_ events were cleared. - bool Clear(); - - static Profiler* Instance(); - private: - Profiler(); - - typedef std::map EventMap; - EventMap events_; - mutable SharedExclusiveLock lock_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Profiler); -}; - -// Starts an event on construction and stops it on destruction. -// Used by PROFILE macro. -class ProfilerScope { - public: - explicit ProfilerScope(const std::string& event_name) - : event_name_(event_name) { - Profiler::Instance()->StartEvent(event_name_); - } - ~ProfilerScope() { - Profiler::Instance()->StopEvent(event_name_); - } - private: - std::string event_name_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ProfilerScope); -}; - -std::ostream& operator<<(std::ostream& stream, - const ProfilerEvent& profiler_event); - -} // namespace rtc - -#endif // WEBRTC_BASE_PROFILER_H_ diff --git a/include/webrtc/base/proxydetect.h b/include/webrtc/base/proxydetect.h deleted file mode 100644 index 708c332..0000000 --- a/include/webrtc/base/proxydetect.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2007 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef _PROXYDETECT_H_ -#define _PROXYDETECT_H_ - -#include "webrtc/base/proxyinfo.h" - -namespace rtc { -// Auto-detect the proxy server. Returns true if a proxy is configured, -// although hostname may be empty if the proxy is not required for -// the given URL. - -bool GetProxySettingsForUrl(const char* agent, const char* url, - rtc::ProxyInfo* proxy, - bool long_operation = false); - -} // namespace rtc - -#endif // _PROXYDETECT_H_ diff --git a/include/webrtc/base/race_checker.h b/include/webrtc/base/race_checker.h new file mode 100644 index 0000000..a6ba771 --- /dev/null +++ b/include/webrtc/base/race_checker.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_RACE_CHECKER_H_ +#define WEBRTC_BASE_RACE_CHECKER_H_ + +#include "webrtc/base/checks.h" +#include "webrtc/base/platform_thread.h" +#include "webrtc/base/thread_annotations.h" + +namespace rtc { + +namespace internal { +class RaceCheckerScope; +} // namespace internal + +// Best-effort race-checking implementation. This primitive uses no +// synchronization at all to be as-fast-as-possible in the non-racy case. +class LOCKABLE RaceChecker { + public: + friend class internal::RaceCheckerScope; + RaceChecker(); + + private: + bool Acquire() const EXCLUSIVE_LOCK_FUNCTION(); + void Release() const UNLOCK_FUNCTION(); + + // Volatile to prevent code being optimized away in Acquire()/Release(). + mutable volatile int access_count_ = 0; + mutable volatile PlatformThreadRef accessing_thread_; +}; + +namespace internal { +class SCOPED_LOCKABLE RaceCheckerScope { + public: + explicit RaceCheckerScope(const RaceChecker* race_checker) + EXCLUSIVE_LOCK_FUNCTION(race_checker); + + bool RaceDetected() const; + ~RaceCheckerScope() UNLOCK_FUNCTION(); + + private: + const RaceChecker* const race_checker_; + const bool race_check_ok_; +}; + +class SCOPED_LOCKABLE RaceCheckerScopeDoNothing { + public: + explicit RaceCheckerScopeDoNothing(const RaceChecker* race_checker) + EXCLUSIVE_LOCK_FUNCTION(race_checker) {} + + ~RaceCheckerScopeDoNothing() UNLOCK_FUNCTION() {} +}; + +} // namespace internal +} // namespace rtc + +#define RTC_CHECK_RUNS_SERIALIZED(x) \ + rtc::internal::RaceCheckerScope race_checker(x); \ + RTC_CHECK(!race_checker.RaceDetected()) + +#if RTC_DCHECK_IS_ON +#define RTC_DCHECK_RUNS_SERIALIZED(x) \ + rtc::internal::RaceCheckerScope race_checker(x); \ + RTC_DCHECK(!race_checker.RaceDetected()) +#else +#define RTC_DCHECK_RUNS_SERIALIZED(x) \ + rtc::internal::RaceCheckerScopeDoNothing race_checker(x) +#endif + +#endif // WEBRTC_BASE_RACE_CHECKER_H_ diff --git a/include/webrtc/base/rate_limiter.h b/include/webrtc/base/rate_limiter.h new file mode 100644 index 0000000..5809fc1 --- /dev/null +++ b/include/webrtc/base/rate_limiter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_RATE_LIMITER_H_ +#define WEBRTC_BASE_RATE_LIMITER_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/rate_statistics.h" + +namespace webrtc { + +class Clock; + +// Class used to limit a bitrate, making sure the average does not exceed a +// maximum as measured over a sliding window. This class is thread safe; all +// methods will acquire (the same) lock befeore executing. +class RateLimiter { + public: + RateLimiter(Clock* clock, int64_t max_window_ms); + ~RateLimiter(); + + // Try to use rate to send bytes. Returns true on success and if so updates + // current rate. + bool TryUseRate(size_t packet_size_bytes); + + // Set the maximum bitrate, in bps, that this limiter allows to send. + void SetMaxRate(uint32_t max_rate_bps); + + // Set the window size over which to measure the current bitrate. + // For example, irt retransmissions, this is typically the RTT. + // Returns true on success and false if window_size_ms is out of range. + bool SetWindowSize(int64_t window_size_ms); + + private: + Clock* const clock_; + rtc::CriticalSection lock_; + RateStatistics current_rate_ GUARDED_BY(lock_); + int64_t window_size_ms_ GUARDED_BY(lock_); + uint32_t max_rate_bps_ GUARDED_BY(lock_); + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RateLimiter); +}; + +} // namespace webrtc + +#endif // WEBRTC_BASE_RATE_LIMITER_H_ diff --git a/include/webrtc/base/rate_statistics.h b/include/webrtc/base/rate_statistics.h index aea8d79..8a90a46 100644 --- a/include/webrtc/base/rate_statistics.h +++ b/include/webrtc/base/rate_statistics.h @@ -13,41 +13,71 @@ #include +#include "webrtc/base/optional.h" #include "webrtc/typedefs.h" namespace webrtc { class RateStatistics { public: - // window_size = window size in ms for the rate estimation - // scale = coefficient to convert counts/ms to desired units, - // ex: if counts represents bytes, use 8*1000 to go to bits/s - RateStatistics(uint32_t window_size_ms, float scale); + static constexpr float kBpsScale = 8000.0f; + + // max_window_size_ms = Maximum window size in ms for the rate estimation. + // Initial window size is set to this, but may be changed + // to something lower by calling SetWindowSize(). + // scale = coefficient to convert counts/ms to desired unit + // ex: kBpsScale (8000) for bits/s if count represents bytes. + RateStatistics(int64_t max_window_size_ms, float scale); ~RateStatistics(); + // Reset instance to original state. void Reset(); + + // Update rate with a new data point, moving averaging window as needed. void Update(size_t count, int64_t now_ms); - uint32_t Rate(int64_t now_ms); + + // Note that despite this being a const method, it still updates the internal + // state (moves averaging window), but it doesn't make any alterations that + // are observable from the other methods, as long as supplied timestamps are + // from a monotonic clock. Ie, it doesn't matter if this call moves the + // window, since any subsequent call to Update or Rate would still have moved + // the window as much or more. + rtc::Optional Rate(int64_t now_ms) const; + + // Update the size of the averaging window. The maximum allowed value for + // window_size_ms is max_window_size_ms as supplied in the constructor. + bool SetWindowSize(int64_t window_size_ms, int64_t now_ms); private: void EraseOld(int64_t now_ms); + bool IsInitialized() const; // Counters are kept in buckets (circular buffer), with one bucket // per millisecond. - const int num_buckets_; - std::unique_ptr buckets_; + struct Bucket { + size_t sum; // Sum of all samples in this bucket. + size_t samples; // Number of samples in this bucket. + }; + std::unique_ptr buckets_; // Total count recorded in buckets. size_t accumulated_count_; + // The total number of samples in the buckets. + size_t num_samples_; + // Oldest time recorded in buckets. int64_t oldest_time_; // Bucket index of oldest counter recorded in buckets. - int oldest_index_; + uint32_t oldest_index_; // To convert counts/ms to desired units const float scale_; + + // The window sizes, in ms, over which the rate is calculated. + const int64_t max_window_size_ms_; + int64_t current_window_size_ms_; }; } // namespace webrtc diff --git a/include/webrtc/base/ratelimiter.h b/include/webrtc/base/ratelimiter.h index cf5d6b0..1423e99 100644 --- a/include/webrtc/base/ratelimiter.h +++ b/include/webrtc/base/ratelimiter.h @@ -11,8 +11,7 @@ #ifndef WEBRTC_BASE_RATELIMITER_H_ #define WEBRTC_BASE_RATELIMITER_H_ -#include -#include "webrtc/base/basictypes.h" +#include namespace rtc { diff --git a/include/webrtc/base/refcount.h b/include/webrtc/base/refcount.h index 55ce23a..565ae49 100644 --- a/include/webrtc/base/refcount.h +++ b/include/webrtc/base/refcount.h @@ -7,13 +7,10 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ - #ifndef WEBRTC_BASE_REFCOUNT_H_ #define WEBRTC_BASE_REFCOUNT_H_ -#include - -#include "webrtc/base/atomicops.h" +#include "webrtc/base/refcountedobject.h" namespace rtc { @@ -22,106 +19,9 @@ class RefCountInterface { public: virtual int AddRef() const = 0; virtual int Release() const = 0; - protected: - virtual ~RefCountInterface() {} -}; - -template -class RefCountedObject : public T { - public: - RefCountedObject() : ref_count_(0) { - } - - template - explicit RefCountedObject(P p) : T(p), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2) : T(p1, p2), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3) : T(p1, p2, p3), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4) - : T(p1, p2, p3, p4), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) - : T(p1, p2, p3, p4, p5), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) - : T(p1, p2, p3, p4, p5, p6), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) - : T(p1, p2, p3, p4, p5, p6, p7), ref_count_(0) { - } - - template - RefCountedObject(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) - : T(p1, p2, p3, p4, p5, p6, p7, p8), ref_count_(0) { - } - - template - RefCountedObject( - P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) - : T(p1, p2, p3, p4, p5, p6, p7, p8, p9), ref_count_(0) { - } - - template - RefCountedObject( - P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) - : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), ref_count_(0) { - } - - template - RefCountedObject( - P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, - P11 p11) - : T(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), ref_count_(0) { - } - - virtual int AddRef() const { - return AtomicOps::Increment(&ref_count_); - } - - virtual int Release() const { - int count = AtomicOps::Decrement(&ref_count_); - if (!count) { - delete this; - } - return count; - } - - // Return whether the reference count is one. If the reference count is used - // in the conventional way, a reference count of 1 implies that the current - // thread owns the reference and no other thread shares it. This call - // performs the test for a reference count of one, and performs the memory - // barrier needed for the owning thread to act on the object, knowing that it - // has exclusive access to the object. - virtual bool HasOneRef() const { - return AtomicOps::AcquireLoad(&ref_count_) == 1; - } protected: - virtual ~RefCountedObject() { - } - - mutable volatile int ref_count_; + virtual ~RefCountInterface() {} }; } // namespace rtc diff --git a/include/webrtc/base/refcountedobject.h b/include/webrtc/base/refcountedobject.h new file mode 100644 index 0000000..285ed36 --- /dev/null +++ b/include/webrtc/base/refcountedobject.h @@ -0,0 +1,61 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_BASE_REFCOUNTEDOBJECT_H_ +#define WEBRTC_BASE_REFCOUNTEDOBJECT_H_ + +#include + +#include "webrtc/base/atomicops.h" + +namespace rtc { + +template +class RefCountedObject : public T { + public: + RefCountedObject() {} + + template + explicit RefCountedObject(P0&& p0) : T(std::forward(p0)) {} + + template + RefCountedObject(P0&& p0, P1&& p1, Args&&... args) + : T(std::forward(p0), + std::forward(p1), + std::forward(args)...) {} + + virtual int AddRef() const { return AtomicOps::Increment(&ref_count_); } + + virtual int Release() const { + int count = AtomicOps::Decrement(&ref_count_); + if (!count) { + delete this; + } + return count; + } + + // Return whether the reference count is one. If the reference count is used + // in the conventional way, a reference count of 1 implies that the current + // thread owns the reference and no other thread shares it. This call + // performs the test for a reference count of one, and performs the memory + // barrier needed for the owning thread to act on the object, knowing that it + // has exclusive access to the object. + virtual bool HasOneRef() const { + return AtomicOps::AcquireLoad(&ref_count_) == 1; + } + + protected: + virtual ~RefCountedObject() {} + + mutable volatile int ref_count_ = 0; +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_REFCOUNTEDOBJECT_H_ diff --git a/include/webrtc/base/referencecountedsingletonfactory.h b/include/webrtc/base/referencecountedsingletonfactory.h deleted file mode 100644 index 500150f..0000000 --- a/include/webrtc/base/referencecountedsingletonfactory.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ -#define WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ - -#include - -#include "webrtc/base/common.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/logging.h" - -namespace rtc { - -template class rcsf_ptr; - -// A ReferenceCountedSingletonFactory is an object which owns another object, -// and doles out the owned object to consumers in a reference-counted manner. -// Thus, the factory owns at most one object of the desired kind, and -// hands consumers a special pointer to it, through which they can access it. -// When the consumers delete the pointer, the reference count goes down, -// and if the reference count hits zero, the factory can throw the object -// away. If a consumer requests the pointer and the factory has none, -// it can create one on the fly and pass it back. -template -class ReferenceCountedSingletonFactory { - friend class rcsf_ptr; - public: - ReferenceCountedSingletonFactory() : ref_count_(0) {} - - virtual ~ReferenceCountedSingletonFactory() { - ASSERT(ref_count_ == 0); - } - - protected: - // Must be implemented in a sub-class. The sub-class may choose whether or not - // to cache the instance across lifetimes by either reset()'ing or not - // reset()'ing the unique_ptr in CleanupInstance(). - virtual bool SetupInstance() = 0; - virtual void CleanupInstance() = 0; - - std::unique_ptr instance_; - - private: - Interface* GetInstance() { - rtc::CritScope cs(&crit_); - if (ref_count_ == 0) { - if (!SetupInstance()) { - LOG(LS_VERBOSE) << "Failed to setup instance"; - return NULL; - } - ASSERT(instance_.get() != NULL); - } - ++ref_count_; - - LOG(LS_VERBOSE) << "Number of references: " << ref_count_; - return instance_.get(); - } - - void ReleaseInstance() { - rtc::CritScope cs(&crit_); - ASSERT(ref_count_ > 0); - ASSERT(instance_.get() != NULL); - --ref_count_; - LOG(LS_VERBOSE) << "Number of references: " << ref_count_; - if (ref_count_ == 0) { - CleanupInstance(); - } - } - - CriticalSection crit_; - int ref_count_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedSingletonFactory); -}; - -template -class rcsf_ptr { - public: - // Create a pointer that uses the factory to get the instance. - // This is lazy - it won't generate the instance until it is requested. - explicit rcsf_ptr(ReferenceCountedSingletonFactory* factory) - : instance_(NULL), - factory_(factory) { - } - - ~rcsf_ptr() { - release(); - } - - Interface& operator*() { - EnsureAcquired(); - return *instance_; - } - - Interface* operator->() { - EnsureAcquired(); - return instance_; - } - - // Gets the pointer, creating the singleton if necessary. May return NULL if - // creation failed. - Interface* get() { - Acquire(); - return instance_; - } - - // Set instance to NULL and tell the factory we aren't using the instance - // anymore. - void release() { - if (instance_) { - instance_ = NULL; - factory_->ReleaseInstance(); - } - } - - // Lets us know whether instance is valid or not right now. - // Even though attempts to use the instance will automatically create it, it - // is advisable to check this because creation can fail. - bool valid() const { - return instance_ != NULL; - } - - // Returns the factory that this pointer is using. - ReferenceCountedSingletonFactory* factory() const { - return factory_; - } - - private: - void EnsureAcquired() { - Acquire(); - ASSERT(instance_ != NULL); - } - - void Acquire() { - // Since we're getting a singleton back, acquire is a noop if instance is - // already populated. - if (!instance_) { - instance_ = factory_->GetInstance(); - } - } - - Interface* instance_; - ReferenceCountedSingletonFactory* factory_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(rcsf_ptr); -}; - -}; // namespace rtc - -#endif // WEBRTC_BASE_REFERENCECOUNTEDSINGLETONFACTORY_H_ diff --git a/include/webrtc/base/rollingaccumulator.h b/include/webrtc/base/rollingaccumulator.h index 72415ad..6627375 100644 --- a/include/webrtc/base/rollingaccumulator.h +++ b/include/webrtc/base/rollingaccumulator.h @@ -14,7 +14,7 @@ #include #include -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" namespace rtc { @@ -97,8 +97,8 @@ class RollingAccumulator { T ComputeMax() const { if (max_stale_) { - ASSERT(count_ > 0 && - "It shouldn't be possible for max_stale_ && count_ == 0"); + RTC_DCHECK(count_ > 0) << + "It shouldn't be possible for max_stale_ && count_ == 0"; max_ = samples_[next_index_]; for (size_t i = 1u; i < count_; i++) { max_ = std::max(max_, samples_[(next_index_ + i) % max_count()]); @@ -110,8 +110,8 @@ class RollingAccumulator { T ComputeMin() const { if (min_stale_) { - ASSERT(count_ > 0 && - "It shouldn't be possible for min_stale_ && count_ == 0"); + RTC_DCHECK(count_ > 0) << + "It shouldn't be possible for min_stale_ && count_ == 0"; min_ = samples_[next_index_]; for (size_t i = 1u; i < count_; i++) { min_ = std::min(min_, samples_[(next_index_ + i) % max_count()]); diff --git a/include/webrtc/base/rtccertificate.h b/include/webrtc/base/rtccertificate.h index 46d6fd4..dfc7680 100644 --- a/include/webrtc/base/rtccertificate.h +++ b/include/webrtc/base/rtccertificate.h @@ -11,9 +11,10 @@ #ifndef WEBRTC_BASE_RTCCERTIFICATE_H_ #define WEBRTC_BASE_RTCCERTIFICATE_H_ +#include + #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/sslidentity.h" @@ -66,6 +67,7 @@ class RTCCertificate : public RefCountInterface { // To/from PEM, a text representation of the RTCCertificate. RTCCertificatePEM ToPEM() const; + // Can return nullptr if the certificate is invalid. static scoped_refptr FromPEM(const RTCCertificatePEM& pem); bool operator==(const RTCCertificate& certificate) const; bool operator!=(const RTCCertificate& certificate) const; diff --git a/include/webrtc/base/rtccertificategenerator.h b/include/webrtc/base/rtccertificategenerator.h index 08fe671..c131d69 100644 --- a/include/webrtc/base/rtccertificategenerator.h +++ b/include/webrtc/base/rtccertificategenerator.h @@ -20,6 +20,7 @@ namespace rtc { +// See |RTCCertificateGeneratorInterface::GenerateCertificateAsync|. class RTCCertificateGeneratorCallback : public RefCountInterface { public: virtual void OnSuccess( @@ -31,10 +32,27 @@ class RTCCertificateGeneratorCallback : public RefCountInterface { }; // Generates |RTCCertificate|s. +// See |RTCCertificateGenerator| for the WebRTC repo's implementation. +class RTCCertificateGeneratorInterface { + public: + virtual ~RTCCertificateGeneratorInterface() {} + + // Generates a certificate asynchronously on the worker thread. + // Must be called on the signaling thread. The |callback| is invoked with the + // result on the signaling thread. |exipres_ms| optionally specifies for how + // long we want the certificate to be valid, but the implementation may choose + // its own restrictions on the expiration time. + virtual void GenerateCertificateAsync( + const KeyParams& key_params, + const Optional& expires_ms, + const scoped_refptr& callback) = 0; +}; + +// Standard implementation of |RTCCertificateGeneratorInterface|. // The static function |GenerateCertificate| generates a certificate on the // current thread. The |RTCCertificateGenerator| instance generates certificates // asynchronously on the worker thread with |GenerateCertificateAsync|. -class RTCCertificateGenerator { +class RTCCertificateGenerator : public RTCCertificateGeneratorInterface { public: // Generates a certificate on the current thread. Returns null on failure. // If |expires_ms| is specified, the certificate will expire in approximately @@ -46,18 +64,17 @@ class RTCCertificateGenerator { const Optional& expires_ms); RTCCertificateGenerator(Thread* signaling_thread, Thread* worker_thread); + ~RTCCertificateGenerator() override {} - // Generates a certificate asynchronously on the worker thread. - // Must be called on the signaling thread. The |callback| is invoked with the - // result on the signaling thread. If |expires_ms| is specified, the - // certificate will expire in approximately that many milliseconds from now. - // |expires_ms| is limited to a year, a larger value than that is clamped down - // to a year. If |expires_ms| is not specified, a default expiration time is - // used. + // |RTCCertificateGeneratorInterface| overrides. + // If |expires_ms| is specified, the certificate will expire in approximately + // that many milliseconds from now. |expires_ms| is limited to a year, a + // larger value than that is clamped down to a year. If |expires_ms| is not + // specified, a default expiration time is used. void GenerateCertificateAsync( const KeyParams& key_params, const Optional& expires_ms, - const scoped_refptr& callback); + const scoped_refptr& callback) override; private: Thread* const signaling_thread_; diff --git a/include/webrtc/base/safe_compare.h b/include/webrtc/base/safe_compare.h new file mode 100644 index 0000000..39fb917 --- /dev/null +++ b/include/webrtc/base/safe_compare.h @@ -0,0 +1,235 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file defines six functions: +// +// rtc::safe_cmp::Eq // == +// rtc::safe_cmp::Ne // != +// rtc::safe_cmp::Lt // < +// rtc::safe_cmp::Le // <= +// rtc::safe_cmp::Gt // > +// rtc::safe_cmp::Ge // >= +// +// They each accept two arguments of arbitrary types, and in almost all cases, +// they simply call the appropriate comparison operator. However, if both +// arguments are integers, they don't compare them using C++'s quirky rules, +// but instead adhere to the true mathematical definitions. It is as if the +// arguments were first converted to infinite-range signed integers, and then +// compared, although of course nothing expensive like that actually takes +// place. In practice, for signed/signed and unsigned/unsigned comparisons and +// some mixed-signed comparisons with a compile-time constant, the overhead is +// zero; in the remaining cases, it is just a few machine instructions (no +// branches). + +#ifndef WEBRTC_BASE_SAFE_COMPARE_H_ +#define WEBRTC_BASE_SAFE_COMPARE_H_ + +#include +#include + +#include +#include + +namespace rtc { +namespace safe_cmp { + +namespace safe_cmp_impl { + +template +struct LargerIntImpl : std::false_type {}; +template <> +struct LargerIntImpl : std::true_type { + using type = int16_t; +}; +template <> +struct LargerIntImpl : std::true_type { + using type = int32_t; +}; +template <> +struct LargerIntImpl : std::true_type { + using type = int64_t; +}; + +// LargerInt::value is true iff there's a signed type that's larger +// than T1 (and no larger than the larger of T2 and int*, for performance +// reasons); and if there is such a type, LargerInt::type is an alias +// for it. +template +struct LargerInt + : LargerIntImpl {}; + +template +inline typename std::make_unsigned::type MakeUnsigned(T a) { + return static_cast::type>(a); +} + +// Overload for when both T1 and T2 have the same signedness. +template ::value == + std::is_signed::value>::type* = nullptr> +inline bool Cmp(T1 a, T2 b) { + return Op::Op(a, b); +} + +// Overload for signed - unsigned comparison that can be promoted to a bigger +// signed type. +template ::value && + std::is_unsigned::value && + LargerInt::value>::type* = nullptr> +inline bool Cmp(T1 a, T2 b) { + return Op::Op(a, static_cast::type>(b)); +} + +// Overload for unsigned - signed comparison that can be promoted to a bigger +// signed type. +template ::value && + std::is_signed::value && + LargerInt::value>::type* = nullptr> +inline bool Cmp(T1 a, T2 b) { + return Op::Op(static_cast::type>(a), b); +} + +// Overload for signed - unsigned comparison that can't be promoted to a bigger +// signed type. +template ::value && + std::is_unsigned::value && + !LargerInt::value>::type* = nullptr> +inline bool Cmp(T1 a, T2 b) { + return a < 0 ? Op::Op(-1, 0) : Op::Op(safe_cmp_impl::MakeUnsigned(a), b); +} + +// Overload for unsigned - signed comparison that can't be promoted to a bigger +// signed type. +template ::value && + std::is_signed::value && + !LargerInt::value>::type* = nullptr> +inline bool Cmp(T1 a, T2 b) { + return b < 0 ? Op::Op(0, -1) : Op::Op(a, safe_cmp_impl::MakeUnsigned(b)); +} + +#define RTC_SAFECMP_MAKE_OP(name, op) \ + struct name { \ + template \ + static constexpr bool Op(T1 a, T2 b) { \ + return a op b; \ + } \ + }; +RTC_SAFECMP_MAKE_OP(EqOp, ==) +RTC_SAFECMP_MAKE_OP(NeOp, !=) +RTC_SAFECMP_MAKE_OP(LtOp, <) +RTC_SAFECMP_MAKE_OP(LeOp, <=) +RTC_SAFECMP_MAKE_OP(GtOp, >) +RTC_SAFECMP_MAKE_OP(GeOp, >=) +#undef RTC_SAFECMP_MAKE_OP + +// Determines if the given type is an enum that converts implicitly to +// an integral type. +template +struct IsIntEnum { + private: + // This overload is used if the type is an enum, and unary plus + // compiles and turns it into an integral type. + template ::value && + std::is_integral())>::value>::type* = + nullptr> + static int Test(int); + + // Otherwise, this overload is used. + template + static char Test(...); + + public: + static constexpr bool value = + std::is_same::type>(0)), + int>::value; +}; + +// Determines if the given type is integral, or an enum that +// converts implicitly to an integral type. +template +struct IsIntlike { + private: + using X = typename std::remove_reference::type; + + public: + static constexpr bool value = + std::is_integral::value || IsIntEnum::value; +}; + +namespace test_enum_intlike { + +enum E1 { e1 }; +enum { e2 }; +enum class E3 { e3 }; +struct S {}; + +static_assert(IsIntEnum::value, ""); +static_assert(IsIntEnum::value, ""); +static_assert(!IsIntEnum::value, ""); +static_assert(!IsIntEnum::value, ""); +static_assert(!IsIntEnum::value, ""); +static_assert(!IsIntEnum::value, ""); + +static_assert(IsIntlike::value, ""); +static_assert(IsIntlike::value, ""); +static_assert(!IsIntlike::value, ""); +static_assert(IsIntlike::value, ""); +static_assert(!IsIntlike::value, ""); +static_assert(!IsIntlike::value, ""); + +} // test_enum_intlike +} // namespace safe_cmp_impl + +#define RTC_SAFECMP_MAKE_FUN(name) \ + template ::value && \ + safe_cmp_impl::IsIntlike::value>::type* = nullptr> \ + inline bool name(T1 a, T2 b) { \ + /* Unary plus here turns enums into real integral types. */ \ + return safe_cmp_impl::Cmp(+a, +b); \ + } \ + template ::value || \ + !safe_cmp_impl::IsIntlike::value>::type* = nullptr> \ + inline bool name(T1&& a, T2&& b) { \ + return safe_cmp_impl::name##Op::Op(a, b); \ + } +RTC_SAFECMP_MAKE_FUN(Eq) +RTC_SAFECMP_MAKE_FUN(Ne) +RTC_SAFECMP_MAKE_FUN(Lt) +RTC_SAFECMP_MAKE_FUN(Le) +RTC_SAFECMP_MAKE_FUN(Gt) +RTC_SAFECMP_MAKE_FUN(Ge) +#undef RTC_SAFECMP_MAKE_FUN + +} // namespace safe_cmp +} // namespace rtc + +#endif // WEBRTC_BASE_SAFE_COMPARE_H_ diff --git a/include/webrtc/base/sanitizer.h b/include/webrtc/base/sanitizer.h new file mode 100644 index 0000000..e27a692 --- /dev/null +++ b/include/webrtc/base/sanitizer.h @@ -0,0 +1,116 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_SANITIZER_H_ +#define WEBRTC_BASE_SANITIZER_H_ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define RTC_HAS_ASAN 1 +#endif +#if __has_feature(memory_sanitizer) +#define RTC_HAS_MSAN 1 +#endif +#endif +#ifndef RTC_HAS_ASAN +#define RTC_HAS_ASAN 0 +#endif +#ifndef RTC_HAS_MSAN +#define RTC_HAS_MSAN 0 +#endif + +#if RTC_HAS_ASAN +#include +#endif +#if RTC_HAS_MSAN +#include +#endif + +#ifdef __has_attribute +#if __has_attribute(no_sanitize) +#define RTC_NO_SANITIZE(what) __attribute__((no_sanitize(what))) +#endif +#endif +#ifndef RTC_NO_SANITIZE +#define RTC_NO_SANITIZE(what) +#endif + +// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements) +// as being unaddressable, so that reads and writes are not allowed. ASan may +// narrow the range to the nearest alignment boundaries. +static inline void rtc_AsanPoison(const volatile void* ptr, + size_t element_size, + size_t num_elements) { +#if RTC_HAS_ASAN + ASAN_POISON_MEMORY_REGION(ptr, element_size * num_elements); +#endif +} + +// Ask ASan to mark the memory range [ptr, ptr + element_size * num_elements) +// as being addressable, so that reads and writes are allowed. ASan may widen +// the range to the nearest alignment boundaries. +static inline void rtc_AsanUnpoison(const volatile void* ptr, + size_t element_size, + size_t num_elements) { +#if RTC_HAS_ASAN + ASAN_UNPOISON_MEMORY_REGION(ptr, element_size * num_elements); +#endif +} + +// Ask MSan to mark the memory range [ptr, ptr + element_size * num_elements) +// as being uninitialized. +static inline void rtc_MsanMarkUninitialized(const volatile void* ptr, + size_t element_size, + size_t num_elements) { +#if RTC_HAS_MSAN + __msan_poison(ptr, element_size * num_elements); +#endif +} + +// Force an MSan check (if any bits in the memory range [ptr, ptr + +// element_size * num_elements) are uninitialized the call will crash with an +// MSan report). +static inline void rtc_MsanCheckInitialized(const volatile void* ptr, + size_t element_size, + size_t num_elements) { +#if RTC_HAS_MSAN + __msan_check_mem_is_initialized(ptr, element_size * num_elements); +#endif +} + +#ifdef __cplusplus + +namespace rtc { + +template +inline void AsanPoison(const T& mem) { + rtc_AsanPoison(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +inline void AsanUnpoison(const T& mem) { + rtc_AsanUnpoison(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +inline void MsanMarkUninitialized(const T& mem) { + rtc_MsanMarkUninitialized(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +template +inline void MsanCheckInitialized(const T& mem) { + rtc_MsanCheckInitialized(mem.data(), sizeof(mem.data()[0]), mem.size()); +} + +} // namespace rtc + +#endif // __cplusplus + +#endif // WEBRTC_BASE_SANITIZER_H_ diff --git a/include/webrtc/base/scoped_autorelease_pool.h b/include/webrtc/base/scoped_autorelease_pool.h index 808231b..2e0a204 100644 --- a/include/webrtc/base/scoped_autorelease_pool.h +++ b/include/webrtc/base/scoped_autorelease_pool.h @@ -22,7 +22,6 @@ #if defined(WEBRTC_MAC) -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" // This header may be included from Obj-C files or C++ files. @@ -44,9 +43,9 @@ class ScopedAutoreleasePool { // as a stack object" discipline. // // Note: new is declared as "throw()" to get around a gcc warning about new - // returning NULL, but this method will never get called and therefore will + // returning null, but this method will never get called and therefore will // never actually throw any exception. - void* operator new(size_t size) throw() { return NULL; } + void* operator new(size_t size) throw() { return nullptr; } void operator delete (void* ptr) {} NSAutoreleasePool* pool_; diff --git a/include/webrtc/base/scoped_ref_ptr.h b/include/webrtc/base/scoped_ref_ptr.h index a71c20a..26aff03 100644 --- a/include/webrtc/base/scoped_ref_ptr.h +++ b/include/webrtc/base/scoped_ref_ptr.h @@ -30,7 +30,7 @@ // void some_other_function() { // scoped_refptr foo = new MyFoo(); // ... -// foo = NULL; // explicitly releases |foo| +// foo = nullptr; // explicitly releases |foo| // ... // if (foo) // foo->Method(param); @@ -45,7 +45,7 @@ // scoped_refptr b; // // b.swap(a); -// // now, |b| references the MyFoo object, and |a| references NULL. +// // now, |b| references the MyFoo object, and |a| references null. // } // // To make both |a| and |b| in the above example reference the same MyFoo @@ -63,15 +63,14 @@ #ifndef WEBRTC_BASE_SCOPED_REF_PTR_H_ #define WEBRTC_BASE_SCOPED_REF_PTR_H_ -#include +#include namespace rtc { template class scoped_refptr { public: - scoped_refptr() : ptr_(NULL) { - } + scoped_refptr() : ptr_(nullptr) {} scoped_refptr(T* p) : ptr_(p) { if (ptr_) @@ -89,6 +88,12 @@ class scoped_refptr { ptr_->AddRef(); } + // Move constructors. + scoped_refptr(scoped_refptr&& r) : ptr_(r.release()) {} + + template + scoped_refptr(scoped_refptr&& r) : ptr_(r.release()) {} + ~scoped_refptr() { if (ptr_) ptr_->Release(); @@ -100,12 +105,12 @@ class scoped_refptr { // Release a pointer. // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, + // If this object holds a null pointer, the return value is null. + // After this operation, this object will hold a null pointer, // and will not own the object any more. T* release() { T* retVal = ptr_; - ptr_ = NULL; + ptr_ = nullptr; return retVal; } @@ -128,6 +133,17 @@ class scoped_refptr { return *this = r.get(); } + scoped_refptr& operator=(scoped_refptr&& r) { + scoped_refptr(std::move(r)).swap(*this); + return *this; + } + + template + scoped_refptr& operator=(scoped_refptr&& r) { + scoped_refptr(std::move(r)).swap(*this); + return *this; + } + void swap(T** pp) { T* p = ptr_; ptr_ = *pp; diff --git a/include/webrtc/base/scopedptrcollection.h b/include/webrtc/base/scopedptrcollection.h index cfdb6f9..a4be035 100644 --- a/include/webrtc/base/scopedptrcollection.h +++ b/include/webrtc/base/scopedptrcollection.h @@ -14,10 +14,11 @@ #ifndef WEBRTC_BASE_SCOPEDPTRCOLLECTION_H_ #define WEBRTC_BASE_SCOPEDPTRCOLLECTION_H_ +#include + #include #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/constructormagic.h" namespace rtc { diff --git a/include/webrtc/base/sec_buffer.h b/include/webrtc/base/sec_buffer.h deleted file mode 100644 index e6ffea4..0000000 --- a/include/webrtc/base/sec_buffer.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// @file Contains utility classes that make it easier to use SecBuffers - -#ifndef WEBRTC_BASE_SEC_BUFFER_H__ -#define WEBRTC_BASE_SEC_BUFFER_H__ - -namespace rtc { - -// A base class for CSecBuffer. Contains -// all implementation that does not require -// template arguments. -class CSecBufferBase : public SecBuffer { - public: - CSecBufferBase() { - Clear(); - } - - // Uses the SSPI to free a pointer, must be - // used for buffers returned from SSPI APIs. - static void FreeSSPI(void *ptr) { - if ( ptr ) { - SECURITY_STATUS status; - status = ::FreeContextBuffer(ptr); - ASSERT(SEC_E_OK == status); // "Freeing context buffer" - } - } - - // Deletes a buffer with operator delete - static void FreeDelete(void *ptr) { - delete [] reinterpret_cast(ptr); - } - - // A noop delete, for buffers over other - // people's memory - static void FreeNone(void *ptr) { - } - - protected: - // Clears the buffer to EMPTY & NULL - void Clear() { - this->BufferType = SECBUFFER_EMPTY; - this->cbBuffer = 0; - this->pvBuffer = NULL; - } -}; - -// Wrapper class for SecBuffer to take care -// of initialization and destruction. -template -class CSecBuffer: public CSecBufferBase { - public: - // Initializes buffer to empty & NULL - CSecBuffer() { - } - - // Frees any allocated memory - ~CSecBuffer() { - Release(); - } - - // Frees the buffer appropriately, and re-nulls - void Release() { - pfnFreeBuffer(this->pvBuffer); - Clear(); - } - - private: - // A placeholder function for compile-time asserts on the class - void CompileAsserts() { - // never invoked... - assert(false); // _T("Notreached") - - // This class must not extend the size of SecBuffer, since - // we use arrays of CSecBuffer in CSecBufferBundle below - cassert(sizeof(CSecBuffer == sizeof(SecBuffer))); - } -}; - -// Contains all generic implementation for the -// SecBufferBundle class -class SecBufferBundleBase { - public: -}; - -// A template class that bundles a SecBufferDesc with -// one or more SecBuffers for convenience. Can take -// care of deallocating buffers appropriately, as indicated -// by pfnFreeBuffer function. -// By default does no deallocation. -template -class CSecBufferBundle : public SecBufferBundleBase { - public: - // Constructs a security buffer bundle with num_buffers - // buffers, all of which are empty and nulled. - CSecBufferBundle() { - desc_.ulVersion = SECBUFFER_VERSION; - desc_.cBuffers = num_buffers; - desc_.pBuffers = buffers_; - } - - // Frees all currently used buffers. - ~CSecBufferBundle() { - Release(); - } - - // Accessor for the descriptor - PSecBufferDesc desc() { - return &desc_; - } - - // Accessor for the descriptor - PSecBufferDesc desc() const { - return &desc_; - } - - // returns the i-th security buffer - SecBuffer &operator[] (size_t num) { - ASSERT(num < num_buffers); // "Buffer index out of bounds" - return buffers_[num]; - } - - // returns the i-th security buffer - const SecBuffer &operator[] (size_t num) const { - ASSERT(num < num_buffers); // "Buffer index out of bounds" - return buffers_[num]; - } - - // Frees all non-NULL security buffers, - // using the deallocation function - void Release() { - for ( size_t i = 0; i < num_buffers; ++i ) { - buffers_[i].Release(); - } - } - - private: - // Our descriptor - SecBufferDesc desc_; - // Our bundled buffers, each takes care of its own - // initialization and destruction - CSecBuffer buffers_[num_buffers]; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_SEC_BUFFER_H__ diff --git a/include/webrtc/base/sequenced_task_checker.h b/include/webrtc/base/sequenced_task_checker.h new file mode 100644 index 0000000..4df5b54 --- /dev/null +++ b/include/webrtc/base/sequenced_task_checker.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_SEQUENCED_TASK_CHECKER_H_ +#define WEBRTC_BASE_SEQUENCED_TASK_CHECKER_H_ + +// Apart from debug builds, we also enable the sequence checker in +// builds with RTC_DCHECK_IS_ON so that trybots and waterfall bots +// with this define will get the same level of checking as debug bots. +#define ENABLE_SEQUENCED_TASK_CHECKER RTC_DCHECK_IS_ON + +#include "webrtc/base/checks.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/sequenced_task_checker_impl.h" + +namespace rtc { + +// Do nothing implementation, for use in release mode. +// +// Note: You should almost always use the SequencedTaskChecker class to get the +// right version for your build configuration. +class SequencedTaskCheckerDoNothing { + public: + bool CalledSequentially() const { return true; } + + void Detach() {} +}; + +// SequencedTaskChecker is a helper class used to help verify that some methods +// of a class are called on the same task queue or thread. A +// SequencedTaskChecker is bound to a a task queue if the object is +// created on a task queue, or a thread otherwise. +// +// +// Example: +// class MyClass { +// public: +// void Foo() { +// RTC_DCHECK(sequence_checker_.CalledSequentially()); +// ... (do stuff) ... +// } +// +// private: +// SequencedTaskChecker sequence_checker_; +// } +// +// In Release mode, CalledOnValidThread will always return true. +#if ENABLE_SEQUENCED_TASK_CHECKER +class LOCKABLE SequencedTaskChecker : public SequencedTaskCheckerImpl {}; +#else +class LOCKABLE SequencedTaskChecker : public SequencedTaskCheckerDoNothing {}; +#endif // ENABLE_SEQUENCED_TASK_CHECKER_H_ + +namespace internal { +class SCOPED_LOCKABLE SequencedTaskCheckerScope { + public: + explicit SequencedTaskCheckerScope(const SequencedTaskChecker* checker) + EXCLUSIVE_LOCK_FUNCTION(checker); + ~SequencedTaskCheckerScope() UNLOCK_FUNCTION(); +}; + +} // namespace internal + +#define RTC_DCHECK_CALLED_SEQUENTIALLY(x) \ + rtc::internal::SequencedTaskCheckerScope checker(x) + +#undef ENABLE_SEQUENCED_TASK_CHECKER + +} // namespace rtc +#endif // WEBRTC_BASE_SEQUENCED_TASK_CHECKER_H_ diff --git a/include/webrtc/base/sequenced_task_checker_impl.h b/include/webrtc/base/sequenced_task_checker_impl.h new file mode 100644 index 0000000..684b1dc --- /dev/null +++ b/include/webrtc/base/sequenced_task_checker_impl.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_SEQUENCED_TASK_CHECKER_IMPL_H_ +#define WEBRTC_BASE_SEQUENCED_TASK_CHECKER_IMPL_H_ + +#include "webrtc/base/thread_checker.h" + +namespace rtc { + +class TaskQueue; +// Real implementation of SequencedTaskChecker, for use in debug mode, or +// for temporary use in release mode. +// +// Note: You should almost always use the SequencedTaskChecker class to get the +// right version for your build configuration. +class SequencedTaskCheckerImpl { + public: + SequencedTaskCheckerImpl(); + ~SequencedTaskCheckerImpl(); + + bool CalledSequentially() const; + + // Changes the task queue or thread that is checked for in IsCurrent. This + // may be useful when an object may be created on one task queue / thread and + // then used exclusively on another thread. + void Detach(); + + private: + typedef const void* QueueId; + CriticalSection lock_; + ThreadChecker thread_checker_; + mutable bool attached_; + mutable QueueId valid_queue_; +}; + +} // namespace rtc +#endif // WEBRTC_BASE_SEQUENCED_TASK_CHECKER_IMPL_H_ diff --git a/include/webrtc/base/signalthread.h b/include/webrtc/base/signalthread.h index ec250c6..d42d6ef 100644 --- a/include/webrtc/base/signalthread.h +++ b/include/webrtc/base/signalthread.h @@ -13,7 +13,9 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/nullsocketserver.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" @@ -40,7 +42,7 @@ class SignalThread : public sigslot::has_slots<>, protected MessageHandler { public: - SignalThread(); + explicit SignalThread(bool use_socket_server = true); // Context: Main Thread. Call before Start to change the worker's name. bool SetName(const std::string& name, const void* obj); @@ -102,9 +104,14 @@ class SignalThread class Worker : public Thread { public: - explicit Worker(SignalThread* parent) : parent_(parent) {} + explicit Worker(SignalThread* parent, bool use_socket_server) + : Thread(use_socket_server + ? SocketServer::CreateDefault() + : std::unique_ptr(new NullSocketServer())), + parent_(parent) {} ~Worker() override; void Run() override; + bool IsProcessingMessages() override; private: SignalThread* parent_; @@ -119,7 +126,7 @@ class SignalThread t_->cs_.Enter(); // If refcount_ is zero then the object has already been deleted and we // will be double-deleting it in ~EnterExit()! (shouldn't happen) - ASSERT(t_->refcount_ != 0); + RTC_DCHECK_NE(0, t_->refcount_); ++t_->refcount_; } ~EnterExit() UNLOCK_FUNCTION() { diff --git a/include/webrtc/base/sigslot.h b/include/webrtc/base/sigslot.h index a5fd5f7..4534ec9 100644 --- a/include/webrtc/base/sigslot.h +++ b/include/webrtc/base/sigslot.h @@ -87,6 +87,7 @@ #ifndef WEBRTC_BASE_SIGSLOT_H__ #define WEBRTC_BASE_SIGSLOT_H__ +#include #include #include #include @@ -123,17 +124,9 @@ namespace sigslot { class single_threaded { public: - single_threaded() - { - ; - } - - virtual ~single_threaded() {} - - virtual void lock() {} - - virtual void unlock() {} - }; + void lock() {} + void unlock() {} + }; #ifdef _SIGSLOT_HAS_WIN32_THREADS // The multi threading policies only get compiled in if they are enabled. @@ -151,22 +144,12 @@ namespace sigslot { } } - multi_threaded_global(const multi_threaded_global&) - { - ; - } - - virtual ~multi_threaded_global() - { - ; - } - - virtual void lock() + void lock() { EnterCriticalSection(get_critsec()); } - virtual void unlock() + void unlock() { LeaveCriticalSection(get_critsec()); } @@ -192,17 +175,17 @@ namespace sigslot { InitializeCriticalSection(&m_critsec); } - virtual ~multi_threaded_local() + ~multi_threaded_local() { DeleteCriticalSection(&m_critsec); } - virtual void lock() + void lock() { EnterCriticalSection(&m_critsec); } - virtual void unlock() + void unlock() { LeaveCriticalSection(&m_critsec); } @@ -217,30 +200,40 @@ namespace sigslot { class multi_threaded_global { public: - multi_threaded_global(); - multi_threaded_global(const multi_threaded_global&); - virtual ~multi_threaded_global(); - virtual void lock(); - virtual void unlock(); - - private: - pthread_mutex_t* get_mutex() + void lock() { - static pthread_mutex_t g_mutex; - return &g_mutex; + pthread_mutex_lock(get_mutex()); } + void unlock() + { + pthread_mutex_unlock(get_mutex()); + } + + private: + static pthread_mutex_t* get_mutex(); }; class multi_threaded_local { public: - multi_threaded_local(); - multi_threaded_local(const multi_threaded_local&); - virtual ~multi_threaded_local(); - virtual void lock(); - virtual void unlock(); + multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); } + multi_threaded_local(const multi_threaded_local&) { + pthread_mutex_init(&m_mutex, nullptr); + } + ~multi_threaded_local() + { + pthread_mutex_destroy(&m_mutex); + } + void lock() + { + pthread_mutex_lock(&m_mutex); + } + void unlock() + { + pthread_mutex_unlock(&m_mutex); + } - private: + private: pthread_mutex_t m_mutex; }; #endif // _SIGSLOT_HAS_POSIX_THREADS @@ -263,288 +256,198 @@ namespace sigslot { } }; - class has_slots_interface; - - template - class _connection_base0 - { - public: - virtual ~_connection_base0() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit() = 0; - virtual _connection_base0* clone() = 0; - virtual _connection_base0* duplicate(has_slots_interface* pnewdest) = 0; - }; - - template - class _connection_base1 - { - public: - virtual ~_connection_base1() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type) = 0; - virtual _connection_base1* clone() = 0; - virtual _connection_base1* duplicate(has_slots_interface* pnewdest) = 0; - }; + class _signal_base_interface; - template - class _connection_base2 + class has_slots_interface { - public: - virtual ~_connection_base2() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type) = 0; - virtual _connection_base2* clone() = 0; - virtual _connection_base2* duplicate(has_slots_interface* pnewdest) = 0; - }; + private: + typedef void (*signal_connect_t)(has_slots_interface* self, _signal_base_interface* sender); + typedef void (*signal_disconnect_t)(has_slots_interface* self, _signal_base_interface* sender); + typedef void (*disconnect_all_t)(has_slots_interface* self); - template - class _connection_base3 - { - public: - virtual ~_connection_base3() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type) = 0; - virtual _connection_base3* clone() = 0; - virtual _connection_base3* duplicate(has_slots_interface* pnewdest) = 0; - }; + const signal_connect_t m_signal_connect; + const signal_disconnect_t m_signal_disconnect; + const disconnect_all_t m_disconnect_all; - template - class _connection_base4 - { - public: - virtual ~_connection_base4() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0; - virtual _connection_base4* clone() = 0; - virtual _connection_base4* duplicate(has_slots_interface* pnewdest) = 0; - }; + protected: + has_slots_interface(signal_connect_t conn, signal_disconnect_t disc, disconnect_all_t disc_all) : + m_signal_connect(conn), m_signal_disconnect(disc), m_disconnect_all(disc_all) + { + } - template - class _connection_base5 - { - public: - virtual ~_connection_base5() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type) = 0; - virtual _connection_base5* clone() = 0; - virtual _connection_base5* duplicate(has_slots_interface* pnewdest) = 0; - }; + // Doesn't really need to be virtual, but is for backwards compatibility + // (it was virtual in a previous version of sigslot). + virtual ~has_slots_interface() {} - template - class _connection_base6 - { public: - virtual ~_connection_base6() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type) = 0; - virtual _connection_base6* clone() = 0; - virtual _connection_base6* duplicate(has_slots_interface* pnewdest) = 0; - }; + void signal_connect(_signal_base_interface* sender) + { + m_signal_connect(this, sender); + } - template - class _connection_base7 - { - public: - virtual ~_connection_base7() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type) = 0; - virtual _connection_base7* clone() = 0; - virtual _connection_base7* duplicate(has_slots_interface* pnewdest) = 0; - }; + void signal_disconnect(_signal_base_interface* sender) + { + m_signal_disconnect(this, sender); + } - template - class _connection_base8 - { - public: - virtual ~_connection_base8() {} - virtual has_slots_interface* getdest() const = 0; - virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, - arg6_type, arg7_type, arg8_type) = 0; - virtual _connection_base8* clone() = 0; - virtual _connection_base8* duplicate(has_slots_interface* pnewdest) = 0; + void disconnect_all() + { + m_disconnect_all(this); + } }; class _signal_base_interface { - public: - virtual ~_signal_base_interface() {} - virtual void slot_disconnect(has_slots_interface* pslot) = 0; - virtual void slot_duplicate(const has_slots_interface* poldslot, has_slots_interface* pnewslot) = 0; - }; + private: + typedef void (*slot_disconnect_t)(_signal_base_interface* self, has_slots_interface* pslot); + typedef void (*slot_duplicate_t)(_signal_base_interface* self, const has_slots_interface* poldslot, has_slots_interface* pnewslot); - template - class _signal_base : public _signal_base_interface, public mt_policy - { - }; + const slot_disconnect_t m_slot_disconnect; + const slot_duplicate_t m_slot_duplicate; - class has_slots_interface - { - public: - has_slots_interface() + protected: + _signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl) : + m_slot_disconnect(disc), m_slot_duplicate(dupl) { - ; } - virtual void signal_connect(_signal_base_interface* sender) = 0; + ~_signal_base_interface() {} - virtual void signal_disconnect(_signal_base_interface* sender) = 0; - - virtual ~has_slots_interface() + public: + void slot_disconnect(has_slots_interface* pslot) { + m_slot_disconnect(this, pslot); } - virtual void disconnect_all() = 0; + void slot_duplicate(const has_slots_interface* poldslot, has_slots_interface* pnewslot) + { + m_slot_duplicate(this, poldslot, pnewslot); + } }; - template - class has_slots : public has_slots_interface, public mt_policy + class _opaque_connection { private: - typedef std::set<_signal_base_interface*> sender_set; - typedef sender_set::const_iterator const_iterator; + typedef void (*emit_t)(const _opaque_connection*); + template< typename FromT, typename ToT > + union union_caster + { + FromT from; + ToT to; + }; + + emit_t pemit; + has_slots_interface* pdest; + // Pointers to member functions may be up to 16 bytes for virtual classes, + // so make sure we have enough space to store it. + unsigned char pmethod[16]; public: - has_slots() + template< typename DestT, typename ... Args > + _opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) { - ; - } + typedef void (DestT::*pm_t)(Args...); + static_assert(sizeof(pm_t) <= sizeof(pmethod), "Size of slot function pointer too large."); - has_slots(const has_slots& hs) - { - lock_block lock(this); - const_iterator it = hs.m_senders.begin(); - const_iterator itEnd = hs.m_senders.end(); + std::memcpy(pmethod, &pm, sizeof(pm_t)); - while(it != itEnd) - { - (*it)->slot_duplicate(&hs, this); - m_senders.insert(*it); - ++it; - } + typedef void (*em_t)(const _opaque_connection* self, Args...); + union_caster< em_t, emit_t > caster2; + caster2.from = &_opaque_connection::emitter< DestT, Args... >; + pemit = caster2.to; } - void signal_connect(_signal_base_interface* sender) - { - lock_block lock(this); - m_senders.insert(sender); - } + has_slots_interface* getdest() const { return pdest; } - void signal_disconnect(_signal_base_interface* sender) + _opaque_connection duplicate(has_slots_interface* newtarget) const { - lock_block lock(this); - m_senders.erase(sender); + _opaque_connection res = *this; + res.pdest = newtarget; + return res; } - virtual ~has_slots() + // Just calls the stored "emitter" function pointer stored at construction + // time. + template< typename ... Args > + void emit(Args... args) const { - disconnect_all(); + typedef void (*em_t)(const _opaque_connection*, Args...); + union_caster< emit_t, em_t > caster; + caster.from = pemit; + (caster.to)(this, args...); } - void disconnect_all() + private: + template< typename DestT, typename ... Args > + static void emitter(const _opaque_connection* self, Args... args) { - lock_block lock(this); - const_iterator it = m_senders.begin(); - const_iterator itEnd = m_senders.end(); - - while(it != itEnd) - { - (*it)->slot_disconnect(this); - ++it; - } - - m_senders.erase(m_senders.begin(), m_senders.end()); + typedef void (DestT::*pm_t)(Args...); + pm_t pm; + std::memcpy(&pm, self->pmethod, sizeof(pm_t)); + (static_cast< DestT* >(self->pdest)->*(pm))(args...); } - - private: - sender_set m_senders; }; template - class _signal_base0 : public _signal_base + class _signal_base : public _signal_base_interface, public mt_policy { - public: - typedef std::list<_connection_base0 *> connections_list; + protected: + typedef std::list< _opaque_connection > connections_list; - _signal_base0() + _signal_base() : _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate) { - ; } - _signal_base0(const _signal_base0& s) - : _signal_base(s) + ~_signal_base() { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); + disconnect_all(); + } + + private: + _signal_base& operator= (_signal_base const& that); + public: + _signal_base(const _signal_base& s) : _signal_base_interface(&_signal_base::do_slot_disconnect, &_signal_base::do_slot_duplicate) { + lock_block lock(this); + connections_list::const_iterator it = m_connected_slots.begin(); + connections_list::const_iterator itEnd = m_connected_slots.end(); while(it != itEnd) { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - + it->getdest()->signal_connect(this); + m_connected_slots.push_back(*it); ++it; } } - ~_signal_base0() - { - disconnect_all(); - } - bool is_empty() { lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; + return m_connected_slots.empty(); } void disconnect_all() { lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) + while(!m_connected_slots.empty()) { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; + has_slots_interface* pdest = m_connected_slots.front().getdest(); + m_connected_slots.pop_front(); + pdest->signal_disconnect(static_cast< _signal_base_interface* >(this)); } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); } #if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) + bool connected(has_slots_interface* pclass) { lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); + connections_list::const_iterator it = m_connected_slots.begin(); + connections_list::const_iterator itEnd = m_connected_slots.end(); while(it != itEnd) { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) + if (it->getdest() == pclass) return true; - it = itNext; + ++it; } return false; } @@ -553,16 +456,15 @@ namespace sigslot { void disconnect(has_slots_interface* pclass) { lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); + connections_list::iterator it = m_connected_slots.begin(); + connections_list::iterator itEnd = m_connected_slots.end(); while(it != itEnd) { - if((*it)->getdest() == pclass) + if(it->getdest() == pclass) { - delete *it; m_connected_slots.erase(it); - pclass->signal_disconnect(this); + pclass->signal_disconnect(static_cast< _signal_base_interface* >(this)); return; } @@ -570,38 +472,40 @@ namespace sigslot { } } - void slot_disconnect(has_slots_interface* pslot) + private: + static void do_slot_disconnect(_signal_base_interface* p, has_slots_interface* pslot) { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); + _signal_base* const self = static_cast< _signal_base* >(p); + lock_block lock(self); + connections_list::iterator it = self->m_connected_slots.begin(); + connections_list::iterator itEnd = self->m_connected_slots.end(); while(it != itEnd) { - typename connections_list::iterator itNext = it; + connections_list::iterator itNext = it; ++itNext; - if((*it)->getdest() == pslot) + if(it->getdest() == pslot) { - delete *it; - m_connected_slots.erase(it); + self->m_connected_slots.erase(it); } it = itNext; } } - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) + static void do_slot_duplicate(_signal_base_interface* p, const has_slots_interface* oldtarget, has_slots_interface* newtarget) { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); + _signal_base* const self = static_cast< _signal_base* >(p); + lock_block lock(self); + connections_list::iterator it = self->m_connected_slots.begin(); + connections_list::iterator itEnd = self->m_connected_slots.end(); while(it != itEnd) { - if((*it)->getdest() == oldtarget) + if(it->getdest() == oldtarget) { - m_connected_slots.push_back((*it)->duplicate(newtarget)); + self->m_connected_slots.push_back(it->duplicate(newtarget)); } ++it; @@ -612,2193 +516,145 @@ namespace sigslot { connections_list m_connected_slots; }; - template - class _signal_base1 : public _signal_base + template + class has_slots : public has_slots_interface, public mt_policy { - public: - typedef std::list<_connection_base1 *> connections_list; - - _signal_base1() - { - ; - } + private: + typedef std::set< _signal_base_interface* > sender_set; + typedef sender_set::const_iterator const_iterator; - _signal_base1(const _signal_base1& s) - : _signal_base(s) + public: + has_slots() : has_slots_interface(&has_slots::do_signal_connect, &has_slots::do_signal_disconnect, &has_slots::do_disconnect_all) { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } } - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) + ~has_slots() { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } + this->disconnect_all(); } - ~_signal_base1() - { - disconnect_all(); - } + private: + has_slots(has_slots const&); + has_slots& operator= (has_slots const&); - bool is_empty() + static void do_signal_connect(has_slots_interface* p, _signal_base_interface* sender) { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; + has_slots* const self = static_cast< has_slots* >(p); + lock_block lock(self); + self->m_senders.insert(sender); } - void disconnect_all() + static void do_signal_disconnect(has_slots_interface* p, _signal_base_interface* sender) { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); + has_slots* const self = static_cast< has_slots* >(p); + lock_block lock(self); + self->m_senders.erase(sender); } -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) + static void do_disconnect_all(has_slots_interface* p) { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) + has_slots* const self = static_cast< has_slots* >(p); + lock_block lock(self); + while (!self->m_senders.empty()) { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); + std::set< _signal_base_interface* > senders; + senders.swap(self->m_senders); + const_iterator it = senders.begin(); + const_iterator itEnd = senders.end(); - while(it != itEnd) - { - if((*it)->getdest() == pclass) + while(it != itEnd) { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; + _signal_base_interface* s = *it; + ++it; + s->slot_disconnect(p); } - - ++it; } } - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } + private: + sender_set m_senders; + }; + template + class signal_with_thread_policy : public _signal_base + { + private: + typedef _signal_base base; protected: - connections_list m_connected_slots; - }; + typedef typename base::connections_list connections_list; - template - class _signal_base2 : public _signal_base - { public: - typedef std::list<_connection_base2 *> - connections_list; - - _signal_base2() + signal_with_thread_policy() { - ; } - _signal_base2(const _signal_base2& s) - : _signal_base(s) + template + void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) { lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } + this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun)); + pclass->signal_connect(static_cast< _signal_base_interface* >(this)); } - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) + void emit(Args... args) { lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); + typename connections_list::const_iterator it = this->m_connected_slots.begin(); + typename connections_list::const_iterator itEnd = this->m_connected_slots.end(); while(it != itEnd) { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - + _opaque_connection const& conn = *it; ++it; + + conn.emit(args...); } } - ~_signal_base2() + void operator()(Args... args) { - disconnect_all(); + emit(args...); } + }; - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } + // Alias with default thread policy. Needed because both default arguments + // and variadic template arguments must go at the end of the list, so we + // can't have both at once. + template + using signal = signal_with_thread_policy; - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); + // The previous verion of sigslot didn't use variadic templates, so you would + // need to write "sigslot::signal2", for example. + // Now you can just write "sigslot::signal", but these aliases + // exist for backwards compatibility. + template + using signal0 = signal_with_thread_policy; - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; + template + using signal1 = signal_with_thread_policy; - ++it; - } + template + using signal2 = signal_with_thread_policy; - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } + template + using signal3 = signal_with_thread_policy; -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base3 : public _signal_base - { - public: - typedef std::list<_connection_base3 *> - connections_list; - - _signal_base3() - { - ; - } - - _signal_base3(const _signal_base3& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base3() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base4 : public _signal_base - { - public: - typedef std::list<_connection_base4 *> connections_list; - - _signal_base4() - { - ; - } - - _signal_base4(const _signal_base4& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base4() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base5 : public _signal_base - { - public: - typedef std::list<_connection_base5 *> connections_list; - - _signal_base5() - { - ; - } - - _signal_base5(const _signal_base5& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base5() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base6 : public _signal_base - { - public: - typedef std::list<_connection_base6 *> connections_list; - - _signal_base6() - { - ; - } - - _signal_base6(const _signal_base6& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base6() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base7 : public _signal_base - { - public: - typedef std::list<_connection_base7 *> connections_list; - - _signal_base7() - { - ; - } - - _signal_base7(const _signal_base7& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base7() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - template - class _signal_base8 : public _signal_base - { - public: - typedef std::list<_connection_base8 *> - connections_list; - - _signal_base8() - { - ; - } - - _signal_base8(const _signal_base8& s) - : _signal_base(s) - { - lock_block lock(this); - typename connections_list::const_iterator it = s.m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = s.m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_connect(this); - m_connected_slots.push_back((*it)->clone()); - - ++it; - } - } - - void slot_duplicate(const has_slots_interface* oldtarget, has_slots_interface* newtarget) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == oldtarget) - { - m_connected_slots.push_back((*it)->duplicate(newtarget)); - } - - ++it; - } - } - - ~_signal_base8() - { - disconnect_all(); - } - - bool is_empty() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - return it == itEnd; - } - - void disconnect_all() - { - lock_block lock(this); - typename connections_list::const_iterator it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - (*it)->getdest()->signal_disconnect(this); - delete *it; - - ++it; - } - - m_connected_slots.erase(m_connected_slots.begin(), m_connected_slots.end()); - } - -#if !defined(NDEBUG) - bool connected(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - while(it != itEnd) - { - itNext = it; - ++itNext; - if ((*it)->getdest() == pclass) - return true; - it = itNext; - } - return false; - } -#endif - - void disconnect(has_slots_interface* pclass) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - if((*it)->getdest() == pclass) - { - delete *it; - m_connected_slots.erase(it); - pclass->signal_disconnect(this); - return; - } - - ++it; - } - } - - void slot_disconnect(has_slots_interface* pslot) - { - lock_block lock(this); - typename connections_list::iterator it = m_connected_slots.begin(); - typename connections_list::iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - typename connections_list::iterator itNext = it; - ++itNext; - - if((*it)->getdest() == pslot) - { - delete *it; - m_connected_slots.erase(it); - } - - it = itNext; - } - } - - protected: - connections_list m_connected_slots; - }; - - - template - class _connection0 : public _connection_base0 - { - public: - _connection0() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection0(dest_type* pobject, void (dest_type::*pmemfun)()) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection0() - { - } - - virtual _connection_base0* clone() - { - return new _connection0(*this); - } - - virtual _connection_base0* duplicate(has_slots_interface* pnewdest) - { - return new _connection0((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit() - { - (m_pobject->*m_pmemfun)(); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(); - }; - - template - class _connection1 : public _connection_base1 - { - public: - _connection1() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection1(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection1() - { - } - - virtual _connection_base1* clone() - { - return new _connection1(*this); - } - - virtual _connection_base1* duplicate(has_slots_interface* pnewdest) - { - return new _connection1((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1) - { - (m_pobject->*m_pmemfun)(a1); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type); - }; - - template - class _connection2 : public _connection_base2 - { - public: - _connection2() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection2() - { - } - - virtual _connection_base2* clone() - { - return new _connection2(*this); - } - - virtual _connection_base2* duplicate(has_slots_interface* pnewdest) - { - return new _connection2((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2) - { - (m_pobject->*m_pmemfun)(a1, a2); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type); - }; - - template - class _connection3 : public _connection_base3 - { - public: - _connection3() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection3(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection3() - { - } - - virtual _connection_base3* clone() - { - return new _connection3(*this); - } - - virtual _connection_base3* duplicate(has_slots_interface* pnewdest) - { - return new _connection3((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - (m_pobject->*m_pmemfun)(a1, a2, a3); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type); - }; - - template - class _connection4 : public _connection_base4 - { - public: - _connection4() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection4(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection4() - { - } - - virtual _connection_base4* clone() - { - return new _connection4(*this); - } - - virtual _connection_base4* duplicate(has_slots_interface* pnewdest) - { - return new _connection4((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, - arg4_type a4) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, - arg4_type); - }; - - template - class _connection5 : public _connection_base5 - { - public: - _connection5() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection5(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection5() - { - } - - virtual _connection_base5* clone() - { - return new _connection5(*this); - } - - virtual _connection_base5* duplicate(has_slots_interface* pnewdest) - { - return new _connection5((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type); - }; - - template - class _connection6 : public _connection_base6 - { - public: - _connection6() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection6(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection6() - { - } - - virtual _connection_base6* clone() - { - return new _connection6(*this); - } - - virtual _connection_base6* duplicate(has_slots_interface* pnewdest) - { - return new _connection6((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type); - }; - - template - class _connection7 : public _connection_base7 - { - public: - _connection7() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection7(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, arg7_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection7() - { - } - - virtual _connection_base7* clone() - { - return new _connection7(*this); - } - - virtual _connection_base7* duplicate(has_slots_interface* pnewdest) - { - return new _connection7((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type); - }; - - template - class _connection8 : public _connection_base8 - { - public: - _connection8() - { - m_pobject = NULL; - m_pmemfun = NULL; - } - - _connection8(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - m_pobject = pobject; - m_pmemfun = pmemfun; - } - - virtual ~_connection8() - { - } - - virtual _connection_base8* clone() - { - return new _connection8(*this); - } - - virtual _connection_base8* duplicate(has_slots_interface* pnewdest) - { - return new _connection8((dest_type *)pnewdest, m_pmemfun); - } - - virtual void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - (m_pobject->*m_pmemfun)(a1, a2, a3, a4, a5, a6, a7, a8); - } - - virtual has_slots_interface* getdest() const - { - return m_pobject; - } - - private: - dest_type* m_pobject; - void (dest_type::* m_pmemfun)(arg1_type, arg2_type, arg3_type, arg4_type, - arg5_type, arg6_type, arg7_type, arg8_type); - }; - - template - class signal0 : public _signal_base0 - { - public: - typedef _signal_base0 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal0() - { - ; - } - - signal0(const signal0& s) - : _signal_base0(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)()) - { - lock_block lock(this); - _connection0* conn = - new _connection0(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit() - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - - void operator()() - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(); - - it = itNext; - } - } - }; - - template - class signal1 : public _signal_base1 - { - public: - typedef _signal_base1 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal1() - { - ; - } - - signal1(const signal1& s) - : _signal_base1(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type)) - { - lock_block lock(this); - _connection1* conn = - new _connection1(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - - void operator()(arg1_type a1) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1); - - it = itNext; - } - } - }; - - template - class signal2 : public _signal_base2 - { - public: - typedef _signal_base2 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal2() - { - ; - } - - signal2(const signal2& s) - : _signal_base2(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type)) - { - lock_block lock(this); - _connection2* conn = new - _connection2(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2); - - it = itNext; - } - } - }; - - template - class signal3 : public _signal_base3 - { - public: - typedef _signal_base3 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal3() - { - ; - } - - signal3(const signal3& s) - : _signal_base3(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type)) - { - lock_block lock(this); - _connection3* conn = - new _connection3(pclass, - pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3); - - it = itNext; - } - } - }; - - template - class signal4 : public _signal_base4 - { - public: - typedef _signal_base4 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal4() - { - ; - } - - signal4(const signal4& s) - : _signal_base4(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type)) - { - lock_block lock(this); - _connection4* - conn = new _connection4(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4); - - it = itNext; - } - } - }; - - template - class signal5 : public _signal_base5 - { - public: - typedef _signal_base5 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal5() - { - ; - } - - signal5(const signal5& s) - : _signal_base5(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type)) - { - lock_block lock(this); - _connection5* conn = new _connection5(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5); - - it = itNext; - } - } - }; - - - template - class signal6 : public _signal_base6 - { - public: - typedef _signal_base6 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal6() - { - ; - } - - signal6(const signal6& s) - : _signal_base6(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type)) - { - lock_block lock(this); - _connection6* conn = - new _connection6(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6); - - it = itNext; - } - } - }; - - template - class signal7 : public _signal_base7 - { - public: - typedef _signal_base7 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; - - signal7() - { - ; - } - - signal7(const signal7& s) - : _signal_base7(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type)) - { - lock_block lock(this); - _connection7* conn = - new _connection7(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7); - - it = itNext; - } - } - }; - - template - class signal8 : public _signal_base8 - { - public: - typedef _signal_base8 base; - typedef typename base::connections_list connections_list; - using base::m_connected_slots; + template + using signal4 = signal_with_thread_policy; - signal8() - { - ; - } - - signal8(const signal8& s) - : _signal_base8(s) - { - ; - } - - template - void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type, - arg2_type, arg3_type, arg4_type, arg5_type, arg6_type, - arg7_type, arg8_type)) - { - lock_block lock(this); - _connection8* conn = - new _connection8(pclass, pmemfun); - m_connected_slots.push_back(conn); - pclass->signal_connect(this); - } - - void emit(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); - - while(it != itEnd) - { - itNext = it; - ++itNext; - - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); - - it = itNext; - } - } - - void operator()(arg1_type a1, arg2_type a2, arg3_type a3, arg4_type a4, - arg5_type a5, arg6_type a6, arg7_type a7, arg8_type a8) - { - lock_block lock(this); - typename connections_list::const_iterator itNext, it = m_connected_slots.begin(); - typename connections_list::const_iterator itEnd = m_connected_slots.end(); + template + using signal5 = signal_with_thread_policy; - while(it != itEnd) - { - itNext = it; - ++itNext; + template + using signal6 = signal_with_thread_policy; - (*it)->emit(a1, a2, a3, a4, a5, a6, a7, a8); + template + using signal7 = signal_with_thread_policy; - it = itNext; - } - } - }; + template + using signal8 = signal_with_thread_policy; -}; // namespace sigslot +} // namespace sigslot #endif // WEBRTC_BASE_SIGSLOT_H__ diff --git a/include/webrtc/base/sigslottester.h b/include/webrtc/base/sigslottester.h index cdbd44a..18ddde3 100755 --- a/include/webrtc/base/sigslottester.h +++ b/include/webrtc/base/sigslottester.h @@ -44,7 +44,24 @@ namespace rtc { -// For all the templates below: +// Base version for testing signals that passes no arguments. +class SigslotTester0 : public sigslot::has_slots<> { + public: + explicit SigslotTester0(sigslot::signal0<>* signal) : callback_count_(0) { + signal->connect(this, &SigslotTester0::OnSignalCallback); + } + + int callback_count() const { return callback_count_; } + + private: + void OnSignalCallback() { callback_count_++; } + int callback_count_; + + RTC_DISALLOW_COPY_AND_ASSIGN(SigslotTester0); +}; + +// Versions below are for testing signals that pass arguments. For all the +// templates below: // - A1-A5 is the type of the argument i in the callback. Signals may and often // do use const-references here for efficiency. // - C1-C5 is the type of the variable to capture argument i. These should be diff --git a/include/webrtc/base/socket.h b/include/webrtc/base/socket.h index 22326cb..73dfdbb 100644 --- a/include/webrtc/base/socket.h +++ b/include/webrtc/base/socket.h @@ -151,8 +151,12 @@ class Socket { virtual int Connect(const SocketAddress& addr) = 0; virtual int Send(const void *pv, size_t cb) = 0; virtual int SendTo(const void *pv, size_t cb, const SocketAddress& addr) = 0; - virtual int Recv(void *pv, size_t cb) = 0; - virtual int RecvFrom(void *pv, size_t cb, SocketAddress *paddr) = 0; + // |timestamp| is in units of microseconds. + virtual int Recv(void* pv, size_t cb, int64_t* timestamp) = 0; + virtual int RecvFrom(void* pv, + size_t cb, + SocketAddress* paddr, + int64_t* timestamp) = 0; virtual int Listen(int backlog) = 0; virtual Socket *Accept(SocketAddress *paddr) = 0; virtual int Close() = 0; diff --git a/include/webrtc/base/socket_unittest.h b/include/webrtc/base/socket_unittest.h index adc69f1..8172edd 100644 --- a/include/webrtc/base/socket_unittest.h +++ b/include/webrtc/base/socket_unittest.h @@ -57,6 +57,8 @@ class SocketTest : public testing::Test { void TestUdpReadyToSendIPv6(); void TestGetSetOptionsIPv4(); void TestGetSetOptionsIPv6(); + void TestSocketRecvTimestampIPv4(); + void TestSocketRecvTimestampIPv6(); static const int kTimeout = 5000; // ms const IPAddress kIPv4Loopback; @@ -64,7 +66,7 @@ class SocketTest : public testing::Test { protected: void TcpInternal(const IPAddress& loopback, size_t data_size, - ssize_t max_send_size); + ptrdiff_t max_send_size); private: void ConnectInternal(const IPAddress& loopback); @@ -84,6 +86,7 @@ class SocketTest : public testing::Test { void UdpInternal(const IPAddress& loopback); void UdpReadyToSend(const IPAddress& loopback); void GetSetOptionsInternal(const IPAddress& loopback); + void SocketRecvTimestamp(const IPAddress& loopback); SocketServer* ss_; }; diff --git a/include/webrtc/base/socketadapters.h b/include/webrtc/base/socketadapters.h index 970a3b5..3b5be10 100644 --- a/include/webrtc/base/socketadapters.h +++ b/include/webrtc/base/socketadapters.h @@ -36,7 +36,7 @@ class BufferedReadAdapter : public AsyncSocketAdapter { ~BufferedReadAdapter() override; int Send(const void* pv, size_t cb) override; - int Recv(void* pv, size_t cb) override; + int Recv(void* pv, size_t cb, int64_t* timestamp) override; protected: int DirectSend(const void* pv, size_t cb) { @@ -142,18 +142,6 @@ class AsyncHttpsProxySocket : public BufferedReadAdapter { RTC_DISALLOW_COPY_AND_ASSIGN(AsyncHttpsProxySocket); }; -/* TODO: Implement this. -class AsyncHttpsProxyServerSocket : public AsyncProxyServerSocket { - public: - explicit AsyncHttpsProxyServerSocket(AsyncSocket* socket); - - private: - virtual void ProcessInput(char * data, size_t& len); - void Error(int error); - RTC_DISALLOW_COPY_AND_ASSIGN(AsyncHttpsProxyServerSocket); -}; -*/ - /////////////////////////////////////////////////////////////////////////////// // Implements a socket adapter that speaks the SOCKS proxy protocol. @@ -214,34 +202,6 @@ class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket { RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket); }; -/////////////////////////////////////////////////////////////////////////////// - -// Implements a socket adapter that logs everything that it sends and receives. -class LoggingSocketAdapter : public AsyncSocketAdapter { - public: - LoggingSocketAdapter(AsyncSocket* socket, LoggingSeverity level, - const char * label, bool hex_mode = false); - - int Send(const void* pv, size_t cb) override; - int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override; - int Recv(void* pv, size_t cb) override; - int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override; - int Close() override; - - protected: - void OnConnectEvent(AsyncSocket* socket) override; - void OnCloseEvent(AsyncSocket* socket, int err) override; - - private: - LoggingSeverity level_; - std::string label_; - bool hex_mode_; - LogMultilineState lms_; - RTC_DISALLOW_COPY_AND_ASSIGN(LoggingSocketAdapter); -}; - -/////////////////////////////////////////////////////////////////////////////// - } // namespace rtc #endif // WEBRTC_BASE_SOCKETADAPTERS_H_ diff --git a/include/webrtc/base/socketaddress.h b/include/webrtc/base/socketaddress.h index 175d7a9..bcff390 100644 --- a/include/webrtc/base/socketaddress.h +++ b/include/webrtc/base/socketaddress.h @@ -32,13 +32,16 @@ class SocketAddress { // Creates the address with the given host and port. Host may be a // literal IP string or a hostname to be resolved later. + // DCHECKs that port is in valid range (0 to 2^16-1). SocketAddress(const std::string& hostname, int port); // Creates the address with the given IP and port. // IP is given as an integer in host byte order. V4 only, to be deprecated. + // DCHECKs that port is in valid range (0 to 2^16-1). SocketAddress(uint32_t ip_as_host_order_integer, int port); // Creates the address with the given IP and port. + // DCHECKs that port is in valid range (0 to 2^16-1). SocketAddress(const IPAddress& ip, int port); // Creates a copy of the given address. @@ -77,6 +80,7 @@ class SocketAddress { void SetResolvedIP(const IPAddress& ip); // Changes the port of this address to the given one. + // DCHECKs that port is in valid range (0 to 2^16-1). void SetPort(int port); // Returns the hostname. diff --git a/include/webrtc/base/socketpool.h b/include/webrtc/base/socketpool.h deleted file mode 100644 index 5ceab20..0000000 --- a/include/webrtc/base/socketpool.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_SOCKETPOOL_H_ -#define WEBRTC_BASE_SOCKETPOOL_H_ - -#include -#include -#include "webrtc/base/logging.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/base/socketaddress.h" - -namespace rtc { - -class AsyncSocket; -class LoggingAdapter; -class SocketFactory; -class SocketStream; -class StreamInterface; - -////////////////////////////////////////////////////////////////////// -// StreamPool -////////////////////////////////////////////////////////////////////// - -class StreamPool { -public: - virtual ~StreamPool() { } - - virtual StreamInterface* RequestConnectedStream(const SocketAddress& remote, - int* err) = 0; - virtual void ReturnConnectedStream(StreamInterface* stream) = 0; -}; - -/////////////////////////////////////////////////////////////////////////////// -// StreamCache - Caches a set of open streams, defers creation/destruction to -// the supplied StreamPool. -/////////////////////////////////////////////////////////////////////////////// - -class StreamCache : public StreamPool, public sigslot::has_slots<> { -public: - StreamCache(StreamPool* pool); - ~StreamCache() override; - - // StreamPool Interface - StreamInterface* RequestConnectedStream(const SocketAddress& remote, - int* err) override; - void ReturnConnectedStream(StreamInterface* stream) override; - -private: - typedef std::pair ConnectedStream; - typedef std::list ConnectedList; - - void OnStreamEvent(StreamInterface* stream, int events, int err); - - // We delegate stream creation and deletion to this pool. - StreamPool* pool_; - // Streams that are in use (returned from RequestConnectedStream). - ConnectedList active_; - // Streams which were returned to us, but are still open. - ConnectedList cached_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// NewSocketPool -// Creates a new stream on every request -/////////////////////////////////////////////////////////////////////////////// - -class NewSocketPool : public StreamPool { -public: - NewSocketPool(SocketFactory* factory); - ~NewSocketPool() override; - - // StreamPool Interface - StreamInterface* RequestConnectedStream(const SocketAddress& remote, - int* err) override; - void ReturnConnectedStream(StreamInterface* stream) override; - -private: - SocketFactory* factory_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// ReuseSocketPool -// Maintains a single socket at a time, and will reuse it without closing if -// the destination address is the same. -/////////////////////////////////////////////////////////////////////////////// - -class ReuseSocketPool : public StreamPool, public sigslot::has_slots<> { -public: - ReuseSocketPool(SocketFactory* factory); - ~ReuseSocketPool() override; - - // StreamPool Interface - StreamInterface* RequestConnectedStream(const SocketAddress& remote, - int* err) override; - void ReturnConnectedStream(StreamInterface* stream) override; - -private: - void OnStreamEvent(StreamInterface* stream, int events, int err); - - SocketFactory* factory_; - SocketStream* stream_; - SocketAddress remote_; - bool checked_out_; // Whether the stream is currently checked out -}; - -/////////////////////////////////////////////////////////////////////////////// -// LoggingPoolAdapter - Adapts a StreamPool to supply streams with attached -// LoggingAdapters. -/////////////////////////////////////////////////////////////////////////////// - -class LoggingPoolAdapter : public StreamPool { -public: - LoggingPoolAdapter(StreamPool* pool, LoggingSeverity level, - const std::string& label, bool binary_mode); - ~LoggingPoolAdapter() override; - - // StreamPool Interface - StreamInterface* RequestConnectedStream(const SocketAddress& remote, - int* err) override; - void ReturnConnectedStream(StreamInterface* stream) override; - -private: - StreamPool* pool_; - LoggingSeverity level_; - std::string label_; - bool binary_mode_; - typedef std::deque StreamList; - StreamList recycle_bin_; -}; - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_SOCKETPOOL_H_ diff --git a/include/webrtc/base/socketserver.h b/include/webrtc/base/socketserver.h index 7071f22..5eada4a 100644 --- a/include/webrtc/base/socketserver.h +++ b/include/webrtc/base/socketserver.h @@ -17,6 +17,9 @@ namespace rtc { class MessageQueue; +// Needs to be forward declared because there's a circular dependency between +// NetworkMonitor and Thread. +// TODO(deadbeef): Fix this. class NetworkBinderInterface; // Provides the ability to wait for activity on a set of sockets. The Thread diff --git a/include/webrtc/base/socketstream.h b/include/webrtc/base/socketstream.h index c646563..a1f8ad9 100644 --- a/include/webrtc/base/socketstream.h +++ b/include/webrtc/base/socketstream.h @@ -12,7 +12,6 @@ #define WEBRTC_BASE_SOCKETSTREAM_H_ #include "webrtc/base/asyncsocket.h" -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/stream.h" diff --git a/include/webrtc/base/ssladapter.h b/include/webrtc/base/ssladapter.h index 57e8ee9..0317544 100644 --- a/include/webrtc/base/ssladapter.h +++ b/include/webrtc/base/ssladapter.h @@ -34,7 +34,7 @@ class SSLAdapter : public AsyncSocketAdapter { // negotiation will begin as soon as the socket connects. virtual int StartSSL(const char* hostname, bool restartable) = 0; - // Create the default SSL adapter for this platform. On failure, returns NULL + // Create the default SSL adapter for this platform. On failure, returns null // and deletes |socket|. Otherwise, the returned SSLAdapter takes ownership // of |socket|. static SSLAdapter* Create(AsyncSocket* socket); @@ -50,7 +50,7 @@ typedef bool (*VerificationCallback)(void* cert); // Call this on the main thread, before using SSL. // Call CleanupSSLThread when finished with SSL. -bool InitializeSSL(VerificationCallback callback = NULL); +bool InitializeSSL(VerificationCallback callback = nullptr); // Call to initialize additional threads. bool InitializeSSLThread(); diff --git a/include/webrtc/base/sslconfig.h b/include/webrtc/base/sslconfig.h deleted file mode 100644 index 6aabad0..0000000 --- a/include/webrtc/base/sslconfig.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_SSLCONFIG_H_ -#define WEBRTC_BASE_SSLCONFIG_H_ - -// If no preference has been indicated, default to SChannel on Windows and -// OpenSSL everywhere else, if it is available. -#if !defined(SSL_USE_SCHANNEL) && !defined(SSL_USE_OPENSSL) -#if defined(WEBRTC_WIN) - -#define SSL_USE_SCHANNEL 1 - -#else // defined(WEBRTC_WIN) - -#if defined(HAVE_OPENSSL_SSL_H) -#define SSL_USE_OPENSSL 1 -#endif - -#endif // !defined(WEBRTC_WIN) -#endif - -#endif // WEBRTC_BASE_SSLCONFIG_H_ diff --git a/include/webrtc/base/sslfingerprint.h b/include/webrtc/base/sslfingerprint.h index 4ffb2b0..62b4bc8 100644 --- a/include/webrtc/base/sslfingerprint.h +++ b/include/webrtc/base/sslfingerprint.h @@ -15,6 +15,7 @@ #include "webrtc/base/basictypes.h" #include "webrtc/base/copyonwritebuffer.h" +#include "webrtc/base/rtccertificate.h" #include "webrtc/base/sslidentity.h" namespace rtc { @@ -31,6 +32,10 @@ struct SSLFingerprint { static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm, const std::string& fingerprint); + // Creates a fingerprint from a certificate, using the same digest algorithm + // as the certificate's signature. + static SSLFingerprint* CreateFromCertificate(const RTCCertificate* cert); + SSLFingerprint(const std::string& algorithm, const uint8_t* digest_in, size_t digest_len); diff --git a/include/webrtc/base/sslidentity.h b/include/webrtc/base/sslidentity.h index 8e7e786..263d0dc 100644 --- a/include/webrtc/base/sslidentity.h +++ b/include/webrtc/base/sslidentity.h @@ -28,6 +28,18 @@ namespace rtc { // Forward declaration due to circular dependency with SSLCertificate. class SSLCertChain; +struct SSLCertificateStats { + SSLCertificateStats(std::string&& fingerprint, + std::string&& fingerprint_algorithm, + std::string&& base64_certificate, + std::unique_ptr&& issuer); + ~SSLCertificateStats(); + std::string fingerprint; + std::string fingerprint_algorithm; + std::string base64_certificate; + std::unique_ptr issuer; +}; + // Abstract interface overridden by SSL library specific // implementations. @@ -39,9 +51,9 @@ class SSLCertChain; class SSLCertificate { public: // Parses and builds a certificate from a PEM encoded string. - // Returns NULL on failure. + // Returns null on failure. // The length of the string representation of the certificate is - // stored in *pem_length if it is non-NULL, and only if + // stored in *pem_length if it is non-null, and only if // parsing was successful. // Caller is responsible for freeing the returned object. static SSLCertificate* FromPEMString(const std::string& pem_string); @@ -75,6 +87,15 @@ class SSLCertificate { // Returns the time in seconds relative to epoch, 1970-01-01T00:00:00Z (UTC), // or -1 if an expiration time could not be retrieved. virtual int64_t CertificateExpirationTime() const = 0; + + // Gets information (fingerprint, etc.) about this certificate and its chain + // (if it has a certificate chain). This is used for certificate stats, see + // https://w3c.github.io/webrtc-stats/#certificatestats-dict*. + std::unique_ptr GetStats() const; + + private: + std::unique_ptr GetStats( + std::unique_ptr issuer) const; }; // SSLCertChain is a simple wrapper for a vector of SSLCertificates. It serves @@ -117,20 +138,7 @@ class SSLCertChain { // KT_LAST is intended for vector declarations and loops over all key types; // it does not represent any key type in itself. // KT_DEFAULT is used as the default KeyType for KeyParams. -enum KeyType { - KT_RSA, KT_ECDSA, KT_LAST, -#if defined(WEBRTC_CHROMIUM_BUILD) - // TODO(hbos): Because of an experiment running in Chromium which relies on - // RSA being the default (for performance reasons) we have this #if. ECDSA - // launches in Chromium by flipping a flag which overrides the default. As - // soon as the experiment has ended and there is no risk of RSA being the - // default we should make KT_DEFAULT = KT_ECDSA unconditionally. - // crbug.com/611698 - KT_DEFAULT = KT_RSA -#else - KT_DEFAULT = KT_ECDSA -#endif -}; +enum KeyType { KT_RSA, KT_ECDSA, KT_LAST, KT_DEFAULT = KT_ECDSA }; static const int kRsaDefaultModSize = 1024; static const int kRsaDefaultExponent = 0x10001; // = 2^16+1 = 65537 @@ -208,7 +216,7 @@ class SSLIdentity { // parameters are defined in |key_param|. The certificate's lifetime in // seconds from the current time is defined in |certificate_lifetime|; it // should be a non-negative number. - // Returns NULL on failure. + // Returns null on failure. // Caller is responsible for freeing the returned object. static SSLIdentity* GenerateWithExpiration(const std::string& common_name, const KeyParams& key_param, diff --git a/include/webrtc/base/sslsocketfactory.h b/include/webrtc/base/sslsocketfactory.h deleted file mode 100644 index 792c15c..0000000 --- a/include/webrtc/base/sslsocketfactory.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2007 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_SSLSOCKETFACTORY_H__ -#define WEBRTC_BASE_SSLSOCKETFACTORY_H__ - -#include "webrtc/base/proxyinfo.h" -#include "webrtc/base/socketserver.h" - -namespace rtc { - -/////////////////////////////////////////////////////////////////////////////// -// SslSocketFactory -/////////////////////////////////////////////////////////////////////////////// - -class SslSocketFactory : public SocketFactory { - public: - SslSocketFactory(SocketFactory* factory, const std::string& user_agent); - ~SslSocketFactory() override; - - void SetAutoDetectProxy() { - autodetect_proxy_ = true; - } - void SetForceConnect(bool force) { - force_connect_ = force; - } - void SetProxy(const ProxyInfo& proxy) { - autodetect_proxy_ = false; - proxy_ = proxy; - } - bool autodetect_proxy() const { return autodetect_proxy_; } - const ProxyInfo& proxy() const { return proxy_; } - - void UseSSL(const char* hostname) { hostname_ = hostname; } - void DisableSSL() { hostname_.clear(); } - void SetIgnoreBadCert(bool ignore) { ignore_bad_cert_ = ignore; } - bool ignore_bad_cert() const { return ignore_bad_cert_; } - - void SetLogging(LoggingSeverity level, const std::string& label, - bool binary_mode = false) { - logging_level_ = level; - logging_label_ = label; - binary_mode_ = binary_mode; - } - - // SocketFactory Interface - Socket* CreateSocket(int type) override; - Socket* CreateSocket(int family, int type) override; - - AsyncSocket* CreateAsyncSocket(int type) override; - AsyncSocket* CreateAsyncSocket(int family, int type) override; - - private: - friend class ProxySocketAdapter; - AsyncSocket* CreateProxySocket(const ProxyInfo& proxy, int family, int type); - - SocketFactory* factory_; - std::string agent_; - bool autodetect_proxy_, force_connect_; - ProxyInfo proxy_; - std::string hostname_, logging_label_; - LoggingSeverity logging_level_; - bool binary_mode_; - bool ignore_bad_cert_; -}; - -/////////////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_SSLSOCKETFACTORY_H__ diff --git a/include/webrtc/base/sslstreamadapter.h b/include/webrtc/base/sslstreamadapter.h index c5045f1..e1d1d85 100644 --- a/include/webrtc/base/sslstreamadapter.h +++ b/include/webrtc/base/sslstreamadapter.h @@ -31,6 +31,12 @@ const int SRTP_AES128_CM_SHA1_80 = 0x0001; #ifndef SRTP_AES128_CM_SHA1_32 const int SRTP_AES128_CM_SHA1_32 = 0x0002; #endif +#ifndef SRTP_AEAD_AES_128_GCM +const int SRTP_AEAD_AES_128_GCM = 0x0007; +#endif +#ifndef SRTP_AEAD_AES_256_GCM +const int SRTP_AEAD_AES_256_GCM = 0x0008; +#endif // Cipher suite to use for SRTP. Typically a 80-bit HMAC will be used, except // in applications (voice) where the additional bandwidth may be significant. @@ -39,6 +45,10 @@ const int SRTP_AES128_CM_SHA1_32 = 0x0002; extern const char CS_AES_CM_128_HMAC_SHA1_80[]; // 128-bit AES with 32-bit SHA-1 HMAC. extern const char CS_AES_CM_128_HMAC_SHA1_32[]; +// 128-bit AES GCM with 16 byte AEAD auth tag. +extern const char CS_AEAD_AES_128_GCM[]; +// 256-bit AES GCM with 16 byte AEAD auth tag. +extern const char CS_AEAD_AES_256_GCM[]; // Given the DTLS-SRTP protection profile ID, as defined in // https://tools.ietf.org/html/rfc4568#section-6.2 , return the SRTP profile @@ -48,6 +58,30 @@ std::string SrtpCryptoSuiteToName(int crypto_suite); // The reverse of above conversion. int SrtpCryptoSuiteFromName(const std::string& crypto_suite); +// Get key length and salt length for given crypto suite. Returns true for +// valid suites, otherwise false. +bool GetSrtpKeyAndSaltLengths(int crypto_suite, int *key_length, + int *salt_length); + +// Returns true if the given crypto suite id uses a GCM cipher. +bool IsGcmCryptoSuite(int crypto_suite); + +// Returns true if the given crypto suite name uses a GCM cipher. +bool IsGcmCryptoSuiteName(const std::string& crypto_suite); + +struct CryptoOptions { + CryptoOptions() {} + + // Helper method to return an instance of the CryptoOptions with GCM crypto + // suites disabled. This method should be used instead of depending on current + // default values set by the constructor. + static CryptoOptions NoGcm(); + + // Enable GCM crypto suites from RFC 7714 for SRTP. GCM will only be used + // if both sides enable it. + bool enable_gcm_crypto_suites = false; +}; + // SSLStreamAdapter : A StreamInterfaceAdapter that does SSL/TLS. // After SSL has been started, the stream will only open on successful // SSL verification of certificates, and the communication is @@ -72,10 +106,19 @@ enum SSLProtocolVersion { SSL_PROTOCOL_DTLS_10 = SSL_PROTOCOL_TLS_11, SSL_PROTOCOL_DTLS_12 = SSL_PROTOCOL_TLS_12, }; +enum class SSLPeerCertificateDigestError { + NONE, + UNKNOWN_ALGORITHM, + INVALID_LENGTH, + VERIFICATION_FAILED, +}; // Errors for Read -- in the high range so no conflict with OpenSSL. enum { SSE_MSG_TRUNC = 0xff0001 }; +// Used to send back UMA histogram value. Logged when Dtls handshake fails. +enum class SSLHandshakeError { UNKNOWN, INCOMPATIBLE_CIPHERSUITE, MAX_VALUE }; + class SSLStreamAdapter : public StreamAdapterInterface { public: // Instantiate an SSLStreamAdapter wrapping the given stream, @@ -83,9 +126,8 @@ class SSLStreamAdapter : public StreamAdapterInterface { // Caller is responsible for freeing the returned object. static SSLStreamAdapter* Create(StreamInterface* stream); - explicit SSLStreamAdapter(StreamInterface* stream) - : StreamAdapterInterface(stream), ignore_bad_cert_(false), - client_auth_enabled_(true) { } + explicit SSLStreamAdapter(StreamInterface* stream); + ~SSLStreamAdapter() override; void set_ignore_bad_cert(bool ignore) { ignore_bad_cert_ = ignore; } bool ignore_bad_cert() const { return ignore_bad_cert_; } @@ -93,21 +135,18 @@ class SSLStreamAdapter : public StreamAdapterInterface { void set_client_auth_enabled(bool enabled) { client_auth_enabled_ = enabled; } bool client_auth_enabled() const { return client_auth_enabled_; } - // Specify our SSL identity: key and certificate. Mostly this is - // only used in the peer-to-peer mode (unless we actually want to - // provide a client certificate to a server). - // SSLStream takes ownership of the SSLIdentity object and will - // free it when appropriate. Should be called no more than once on a - // given SSLStream instance. + // Specify our SSL identity: key and certificate. SSLStream takes ownership + // of the SSLIdentity object and will free it when appropriate. Should be + // called no more than once on a given SSLStream instance. virtual void SetIdentity(SSLIdentity* identity) = 0; - // Call this to indicate that we are to play the server's role in - // the peer-to-peer mode. - // The default argument is for backward compatibility + // Call this to indicate that we are to play the server role (or client role, + // if the default argument is replaced by SSL_CLIENT). + // The default argument is for backward compatibility. // TODO(ekr@rtfm.com): rename this SetRole to reflect its new function virtual void SetServerRole(SSLRole role = SSL_SERVER) = 0; - // Do DTLS or TLS + // Do DTLS or TLS. virtual void SetMode(SSLMode mode) = 0; // Set maximum supported protocol version. The highest version supported by @@ -117,45 +156,43 @@ class SSLStreamAdapter : public StreamAdapterInterface { // next lower will be used. virtual void SetMaxProtocolVersion(SSLProtocolVersion version) = 0; - // The mode of operation is selected by calling either - // StartSSLWithServer or StartSSLWithPeer. - // Use of the stream prior to calling either of these functions will - // pass data in clear text. - // Calling one of these functions causes SSL negotiation to begin as - // soon as possible: right away if the underlying wrapped stream is - // already opened, or else as soon as it opens. + // Set the initial retransmission timeout for DTLS messages. When the timeout + // expires, the message gets retransmitted and the timeout is exponentially + // increased. + // This should only be called before StartSSL(). + virtual void SetInitialRetransmissionTimeout(int timeout_ms) = 0; + + // StartSSL starts negotiation with a peer, whose certificate is verified + // using the certificate digest. Generally, SetIdentity() and possibly + // SetServerRole() should have been called before this. + // SetPeerCertificateDigest() must also be called. It may be called after + // StartSSLWithPeer() but must be called before the underlying stream opens. + // + // Use of the stream prior to calling StartSSL will pass data in clear text. + // Calling StartSSL causes SSL negotiation to begin as soon as possible: right + // away if the underlying wrapped stream is already opened, or else as soon as + // it opens. // - // These functions return a negative error code on failure. - // Returning 0 means success so far, but negotiation is probably not - // complete and will continue asynchronously. In that case, the - // exposed stream will open after successful negotiation and - // verification, or an SE_CLOSE event will be raised if negotiation - // fails. - - // StartSSLWithServer starts SSL negotiation with a server in - // traditional mode. server_name specifies the expected server name - // which the server's certificate needs to specify. - virtual int StartSSLWithServer(const char* server_name) = 0; - - // StartSSLWithPeer starts negotiation in the special peer-to-peer - // mode. - // Generally, SetIdentity() and possibly SetServerRole() should have - // been called before this. - // SetPeerCertificate() or SetPeerCertificateDigest() must also be called. - // It may be called after StartSSLWithPeer() but must be called before the - // underlying stream opens. - virtual int StartSSLWithPeer() = 0; - - // Specify the digest of the certificate that our peer is expected to use in - // peer-to-peer mode. Only this certificate will be accepted during - // SSL verification. The certificate is assumed to have been - // obtained through some other secure channel (such as the XMPP - // channel). Unlike SetPeerCertificate(), this must specify the - // terminal certificate, not just a CA. - // SSLStream makes a copy of the digest value. - virtual bool SetPeerCertificateDigest(const std::string& digest_alg, - const unsigned char* digest_val, - size_t digest_len) = 0; + // StartSSL returns a negative error code on failure. Returning 0 means + // success so far, but negotiation is probably not complete and will continue + // asynchronously. In that case, the exposed stream will open after + // successful negotiation and verification, or an SE_CLOSE event will be + // raised if negotiation fails. + virtual int StartSSL() = 0; + + // Specify the digest of the certificate that our peer is expected to use. + // Only this certificate will be accepted during SSL verification. The + // certificate is assumed to have been obtained through some other secure + // channel (such as the signaling channel). This must specify the terminal + // certificate, not just a CA. SSLStream makes a copy of the digest value. + // + // Returns true if successful. + // |error| is optional and provides more information about the failure. + virtual bool SetPeerCertificateDigest( + const std::string& digest_alg, + const unsigned char* digest_val, + size_t digest_len, + SSLPeerCertificateDigestError* error = nullptr) = 0; // Retrieves the peer's X.509 certificate, if a connection has been // established. It returns the transmitted over SSL, including the entire @@ -174,7 +211,7 @@ class SSLStreamAdapter : public StreamAdapterInterface { // part of the RFC defining each exporter // usage (IN) // context/context_len -- a context to bind to for this connection; - // optional, can be NULL, 0 (IN) + // optional, can be null, 0 (IN) // use_context -- whether to use the context value // (needed to distinguish no context from // zero-length ones). @@ -191,10 +228,16 @@ class SSLStreamAdapter : public StreamAdapterInterface { virtual bool SetDtlsSrtpCryptoSuites(const std::vector& crypto_suites); virtual bool GetDtlsSrtpCryptoSuite(int* crypto_suite); - // Capabilities testing - static bool HaveDtls(); - static bool HaveDtlsSrtp(); - static bool HaveExporter(); + // Returns true if a TLS connection has been established. + // The only difference between this and "GetState() == SE_OPEN" is that if + // the peer certificate digest hasn't been verified, the state will still be + // SS_OPENING but IsTlsConnected should return true. + virtual bool IsTlsConnected() = 0; + + // Capabilities testing. + // Used to have "DTLS supported", "DTLS-SRTP supported" etc. methods, but now + // that's assumed. + static bool IsBoringSsl(); // Returns true iff the supplied cipher is deemed to be strong. // TODO(torbjorng): Consider removing the KeyType argument. @@ -206,6 +249,12 @@ class SSLStreamAdapter : public StreamAdapterInterface { // depending on specific SSL implementation. static std::string SslCipherSuiteToName(int cipher_suite); + // Use our timeutils.h source of timing in BoringSSL, allowing us to test + // using a fake clock. + static void enable_time_callback_for_testing(); + + sigslot::signal1 SignalSSLHandshakeError; + private: // If true, the server certificate need not match the configured // server_name, and in fact missing certificate authority and other diff --git a/include/webrtc/base/stream.h b/include/webrtc/base/stream.h index bc94906..dbc2ad7 100644 --- a/include/webrtc/base/stream.h +++ b/include/webrtc/base/stream.h @@ -11,10 +11,10 @@ #ifndef WEBRTC_BASE_STREAM_H_ #define WEBRTC_BASE_STREAM_H_ -#include #include -#include "webrtc/base/basictypes.h" +#include + #include "webrtc/base/buffer.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" @@ -125,7 +125,7 @@ class StreamInterface : public MessageHandler { // The following four methods are used to avoid copying data multiple times. // GetReadData returns a pointer to a buffer which is owned by the stream. - // The buffer contains data_len bytes. NULL is returned if no data is + // The buffer contains data_len bytes. null is returned if no data is // available, or if the method fails. If the caller processes the data, it // must call ConsumeReadData with the number of processed bytes. GetReadData // does not require a matching call to ConsumeReadData if the data is not @@ -135,14 +135,14 @@ class StreamInterface : public MessageHandler { virtual void ConsumeReadData(size_t used) {} // GetWriteBuffer returns a pointer to a buffer which is owned by the stream. - // The buffer has a capacity of buf_len bytes. NULL is returned if there is + // The buffer has a capacity of buf_len bytes. null is returned if there is // no buffer available, or if the method fails. The call may write data to // the buffer, and then call ConsumeWriteBuffer with the number of bytes // written. GetWriteBuffer does not require a matching call to // ConsumeWriteData if no data is written. Write, ForceWrite, and // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer. // TODO: Allow the caller to specify a minimum buffer size. If the specified - // amount of buffer is not yet available, return NULL and Signal SE_WRITE + // amount of buffer is not yet available, return null and Signal SE_WRITE // when it is available. If the requested amount is too large, return an // error. virtual void* GetWriteBuffer(size_t* buf_len); @@ -703,8 +703,10 @@ class StreamReference : public StreamAdapterInterface { // this is the data that read from source but can't move to destination. // as a pass in parameter, it indicates data in buffer that should move to sink StreamResult Flow(StreamInterface* source, - char* buffer, size_t buffer_len, - StreamInterface* sink, size_t* data_len = NULL); + char* buffer, + size_t buffer_len, + StreamInterface* sink, + size_t* data_len = nullptr); /////////////////////////////////////////////////////////////////////////////// diff --git a/include/webrtc/base/stringutils.h b/include/webrtc/base/stringutils.h index 5a6f42a..4c241f0 100644 --- a/include/webrtc/base/stringutils.h +++ b/include/webrtc/base/stringutils.h @@ -32,8 +32,6 @@ #include -#include "webrtc/base/basictypes.h" - /////////////////////////////////////////////////////////////////////////////// // Generic string/memory utilities /////////////////////////////////////////////////////////////////////////////// @@ -138,8 +136,8 @@ struct Traits { // String utilities which work with char or wchar_t /////////////////////////////////////////////////////////////////////////////// -template -inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) { +template +inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = nullptr) { return str ? str : (def_str ? def_str : Traits::empty_str()); } diff --git a/include/webrtc/base/systeminfo.h b/include/webrtc/base/systeminfo.h deleted file mode 100644 index 99d18b2..0000000 --- a/include/webrtc/base/systeminfo.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_SYSTEMINFO_H__ -#define WEBRTC_BASE_SYSTEMINFO_H__ - -#include - -#include "webrtc/base/basictypes.h" - -namespace rtc { - -class SystemInfo { - public: - enum Architecture { - SI_ARCH_UNKNOWN = -1, - SI_ARCH_X86 = 0, - SI_ARCH_X64 = 1, - SI_ARCH_ARM = 2 - }; - - SystemInfo(); - - // The number of CPU Threads in the system. - static int GetMaxCpus(); - // The number of CPU Threads currently available to this process. - static int GetCurCpus(); - // Identity of the CPUs. - Architecture GetCpuArchitecture(); - std::string GetCpuVendor(); - // Total amount of physical memory, in bytes. - int64_t GetMemorySize(); - // The model name of the machine, e.g. "MacBookAir1,1" - std::string GetMachineModel(); - - private: - static int logical_cpus_; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_SYSTEMINFO_H__ diff --git a/include/webrtc/base/task.h b/include/webrtc/base/task.h index b2a6067..4d54cfe 100644 --- a/include/webrtc/base/task.h +++ b/include/webrtc/base/task.h @@ -11,8 +11,10 @@ #ifndef WEBRTC_BASE_TASK_H__ #define WEBRTC_BASE_TASK_H__ +#include + #include -#include "webrtc/base/basictypes.h" + #include "webrtc/base/sigslot.h" #include "webrtc/base/taskparent.h" diff --git a/include/webrtc/base/task_queue.h b/include/webrtc/base/task_queue.h index dad4f43..7d0d414 100644 --- a/include/webrtc/base/task_queue.h +++ b/include/webrtc/base/task_queue.h @@ -13,6 +13,7 @@ #include #include +#include #if defined(WEBRTC_MAC) && !defined(WEBRTC_BUILD_LIBEVENT) #include @@ -26,6 +27,9 @@ #endif #if defined(WEBRTC_BUILD_LIBEVENT) +#include "webrtc/base/refcountedobject.h" +#include "webrtc/base/scoped_ref_ptr.h" + struct event_base; struct event; #endif @@ -155,10 +159,18 @@ static std::unique_ptr NewClosure(const Closure& closure, // TaskQueue itself has been deleted or it may happen synchronously while the // TaskQueue instance is being deleted. This may vary from one OS to the next // so assumptions about lifetimes of pending tasks should not be made. -class TaskQueue { +class LOCKABLE TaskQueue { public: - explicit TaskQueue(const char* queue_name); - // TODO(tommi): Implement move semantics? + // TaskQueue priority levels. On some platforms these will map to thread + // priorities, on others such as Mac and iOS, GCD queue priorities. + enum class Priority { + NORMAL = 0, + HIGH, + LOW, + }; + + explicit TaskQueue(const char* queue_name, + Priority priority = Priority::NORMAL); ~TaskQueue(); static TaskQueue* Current(); @@ -167,7 +179,7 @@ class TaskQueue { static bool IsCurrent(const char* queue_name); bool IsCurrent() const; - // TODO(tommi): For better debuggability, implement FROM_HERE. + // TODO(tommi): For better debuggability, implement RTC_FROM_HERE. // Ownership of the task is passed to PostTask. void PostTask(std::unique_ptr task); @@ -177,6 +189,11 @@ class TaskQueue { void PostTaskAndReply(std::unique_ptr task, std::unique_ptr reply); + // Schedules a task to execute a specified number of milliseconds from when + // the call is made. The precision should be considered as "best effort" + // and in some cases, such as on Windows when all high precision timers have + // been used up, can be off by as much as 15 millseconds (although 8 would be + // more likely). This can be mitigated by limiting the use of delayed tasks. void PostDelayedTask(std::unique_ptr task, uint32_t milliseconds); template @@ -184,6 +201,7 @@ class TaskQueue { PostTask(std::unique_ptr(new ClosureTask(closure))); } + // See documentation above for performance expectations. template void PostDelayedTask(const Closure& closure, uint32_t milliseconds) { PostDelayedTask( @@ -225,16 +243,18 @@ class TaskQueue { private: #if defined(WEBRTC_BUILD_LIBEVENT) - static bool ThreadMain(void* context); + static void ThreadMain(void* context); static void OnWakeup(int socket, short flags, void* context); // NOLINT static void RunTask(int fd, short flags, void* context); // NOLINT static void RunTimer(int fd, short flags, void* context); // NOLINT + class ReplyTaskOwner; class PostAndReplyTask; class SetTimerTask; - void PrepareReplyTask(PostAndReplyTask* reply_task); - void ReplyTaskDone(PostAndReplyTask* reply_task); + typedef RefCountedObject ReplyTaskOwnerRef; + + void PrepareReplyTask(scoped_refptr reply_task); struct QueueContext; @@ -245,7 +265,8 @@ class TaskQueue { PlatformThread thread_; rtc::CriticalSection pending_lock_; std::list> pending_ GUARDED_BY(pending_lock_); - std::list pending_replies_ GUARDED_BY(pending_lock_); + std::list> pending_replies_ + GUARDED_BY(pending_lock_); #elif defined(WEBRTC_MAC) struct QueueContext; struct TaskContext; @@ -253,12 +274,20 @@ class TaskQueue { dispatch_queue_t queue_; QueueContext* const context_; #elif defined(WEBRTC_WIN) - static bool ThreadMain(void* context); + class MultimediaTimer; + typedef std::unordered_map> + DelayedTasks; + static void ThreadMain(void* context); + static bool ProcessQueuedMessages(DelayedTasks* delayed_tasks, + std::vector* timers); class WorkerThread : public PlatformThread { public: - WorkerThread(ThreadRunFunction func, void* obj, const char* thread_name) - : PlatformThread(func, obj, thread_name) {} + WorkerThread(ThreadRunFunction func, + void* obj, + const char* thread_name, + ThreadPriority priority) + : PlatformThread(func, obj, thread_name, priority) {} bool QueueAPC(PAPCFUNC apc_function, ULONG_PTR data) { return PlatformThread::QueueAPC(apc_function, data); diff --git a/include/webrtc/base/taskparent.h b/include/webrtc/base/taskparent.h index 3c0b81c..0021164 100644 --- a/include/webrtc/base/taskparent.h +++ b/include/webrtc/base/taskparent.h @@ -14,7 +14,7 @@ #include #include -#include "webrtc/base/basictypes.h" +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" namespace rtc { @@ -33,7 +33,7 @@ class TaskParent { bool AllChildrenDone(); bool AnyChildError(); -#if !defined(NDEBUG) +#if RTC_DCHECK_IS_ON bool IsChildTask(Task *task); #endif diff --git a/include/webrtc/base/taskrunner.h b/include/webrtc/base/taskrunner.h index e0cf175..f59677a 100644 --- a/include/webrtc/base/taskrunner.h +++ b/include/webrtc/base/taskrunner.h @@ -11,9 +11,11 @@ #ifndef WEBRTC_BASE_TASKRUNNER_H__ #define WEBRTC_BASE_TASKRUNNER_H__ +#include + #include -#include "webrtc/base/basictypes.h" +#include "webrtc/base/checks.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/taskparent.h" @@ -44,7 +46,7 @@ class TaskRunner : public TaskParent, public sigslot::has_slots<> { void UpdateTaskTimeout(Task* task, int64_t previous_task_timeout_time); -#if !defined(NDEBUG) +#if RTC_DCHECK_IS_ON bool is_ok_to_delete(Task* task) { return task == deleting_task_; } @@ -85,11 +87,11 @@ class TaskRunner : public TaskParent, public sigslot::has_slots<> { void CheckForTimeoutChange(int64_t previous_timeout_time); std::vector tasks_; - Task *next_timeout_task_; - bool tasks_running_; -#if !defined(NDEBUG) - int abort_count_; - Task* deleting_task_; + Task *next_timeout_task_ = nullptr; + bool tasks_running_ = false; +#if RTC_DCHECK_IS_ON + int abort_count_ = 0; + Task* deleting_task_ = nullptr; #endif void RecalcNextTimeout(Task *exclude_task); diff --git a/include/webrtc/base/template_util.h b/include/webrtc/base/template_util.h index 31464cf..f3565a4 100644 --- a/include/webrtc/base/template_util.h +++ b/include/webrtc/base/template_util.h @@ -48,17 +48,17 @@ template struct is_non_const_reference : false_type {}; template struct is_void : false_type {}; template <> struct is_void : true_type {}; -template -struct remove_reference { - typedef T type; -}; -template -struct remove_reference { - typedef T type; -}; -template -struct remove_reference { - typedef T type; +// Helper useful for converting a tuple to variadic template function +// arguments. +// +// sequence_generator<3>::type will be sequence<0, 1, 2>. +template +struct sequence {}; +template +struct sequence_generator : sequence_generator {}; +template +struct sequence_generator<0, S...> { + typedef sequence type; }; namespace internal { diff --git a/include/webrtc/base/testclient.h b/include/webrtc/base/testclient.h index df831fe..74ef8cc 100644 --- a/include/webrtc/base/testclient.h +++ b/include/webrtc/base/testclient.h @@ -24,13 +24,17 @@ class TestClient : public sigslot::has_slots<> { public: // Records the contents of a packet that was received. struct Packet { - Packet(const SocketAddress& a, const char* b, size_t s); + Packet(const SocketAddress& a, + const char* b, + size_t s, + const PacketTime& packet_time); Packet(const Packet& p); virtual ~Packet(); SocketAddress addr; char* buf; size_t size; + PacketTime packet_time; }; // Default timeout for NextPacket reads. @@ -73,7 +77,10 @@ class TestClient : public sigslot::has_slots<> { int GetError(); int SetOption(Socket::Option opt, int value); - bool ready_to_send() const; + bool ready_to_send() const { return ready_to_send_count() > 0; } + + // How many times SignalReadyToSend has been fired. + int ready_to_send_count() const { return ready_to_send_count_; } private: // Timeout for reads when no packet is expected. @@ -85,11 +92,13 @@ class TestClient : public sigslot::has_slots<> { const SocketAddress& remote_addr, const PacketTime& packet_time); void OnReadyToSend(AsyncPacketSocket* socket); + bool CheckTimestamp(int64_t packet_timestamp); CriticalSection crit_; AsyncPacketSocket* socket_; std::vector* packets_; - bool ready_to_send_; + int ready_to_send_count_ = 0; + int64_t prev_packet_timestamp_; RTC_DISALLOW_COPY_AND_ASSIGN(TestClient); }; diff --git a/include/webrtc/base/testechoserver.h b/include/webrtc/base/testechoserver.h index 76d714b..97606c1 100644 --- a/include/webrtc/base/testechoserver.h +++ b/include/webrtc/base/testechoserver.h @@ -43,7 +43,7 @@ class TestEchoServer : public sigslot::has_slots<> { private: void OnAccept(AsyncSocket* socket) { - AsyncSocket* raw_socket = socket->Accept(NULL); + AsyncSocket* raw_socket = socket->Accept(nullptr); if (raw_socket) { AsyncTCPSocket* packet_socket = new AsyncTCPSocket(raw_socket, false); packet_socket->SignalReadPacket.connect(this, &TestEchoServer::OnPacket); diff --git a/include/webrtc/base/testutils.h b/include/webrtc/base/testutils.h index e5e571b..305d3d0 100644 --- a/include/webrtc/base/testutils.h +++ b/include/webrtc/base/testutils.h @@ -28,7 +28,7 @@ #include #include "webrtc/base/arraysize.h" #include "webrtc/base/asyncsocket.h" -#include "webrtc/base/common.h" +#include "webrtc/base/checks.h" #include "webrtc/base/gunit.h" #include "webrtc/base/nethelpers.h" #include "webrtc/base/pathutils.h" @@ -177,7 +177,7 @@ class StreamSource : public StreamInterface { va_start(args, format); char buffer[1024]; size_t len = vsprintfn(buffer, sizeof(buffer), format, args); - ASSERT(len < sizeof(buffer) - 1); + RTC_CHECK(len < sizeof(buffer) - 1); va_end(args); QueueData(buffer, len); } @@ -276,14 +276,12 @@ class StreamSource : public StreamInterface { class SocketTestClient : public sigslot::has_slots<> { public: - SocketTestClient() { - Init(NULL, AF_INET); - } - SocketTestClient(AsyncSocket* socket) { - Init(socket, socket->GetLocalAddress().family()); + SocketTestClient() { Init(nullptr, AF_INET); } + SocketTestClient(AsyncSocket* socket) { + Init(socket, socket->GetLocalAddress().family()); } SocketTestClient(const SocketAddress& address) { - Init(NULL, address.family()); + Init(nullptr, address.family()); socket_->Connect(address); } @@ -297,7 +295,7 @@ class SocketTestClient : public sigslot::has_slots<> { va_start(args, format); char buffer[1024]; size_t len = vsprintfn(buffer, sizeof(buffer), format, args); - ASSERT(len < sizeof(buffer) - 1); + RTC_CHECK(len < sizeof(buffer) - 1); va_end(args); QueueData(buffer, len); } @@ -359,7 +357,7 @@ class SocketTestClient : public sigslot::has_slots<> { } void OnReadEvent(AsyncSocket* socket) { char data[64 * 1024]; - int result = socket_->Recv(data, arraysize(data)); + int result = socket_->Recv(data, arraysize(data), nullptr); if (result > 0) { recv_buffer_.insert(recv_buffer_.end(), data, data + result); } @@ -408,8 +406,7 @@ class SocketTestServer : public sigslot::has_slots<> { private: void OnReadEvent(AsyncSocket* socket) { - AsyncSocket* accepted = - static_cast(socket_->Accept(NULL)); + AsyncSocket* accepted = static_cast(socket_->Accept(nullptr)); if (!accepted) return; clients_.push_back(new SocketTestClient(accepted)); @@ -419,49 +416,6 @@ class SocketTestServer : public sigslot::has_slots<> { std::vector clients_; }; -/////////////////////////////////////////////////////////////////////////////// -// Generic Utilities -/////////////////////////////////////////////////////////////////////////////// - -inline bool ReadFile(const char* filename, std::string* contents) { - FILE* fp = fopen(filename, "rb"); - if (!fp) - return false; - char buffer[1024*64]; - size_t read; - contents->clear(); - while ((read = fread(buffer, 1, sizeof(buffer), fp))) { - contents->append(buffer, read); - } - bool success = (0 != feof(fp)); - fclose(fp); - return success; -} - -// Look in parent dir for parallel directory. -inline rtc::Pathname GetSiblingDirectory( - const std::string& parallel_dir) { - rtc::Pathname path = rtc::Filesystem::GetCurrentDirectory(); - while (!path.empty()) { - rtc::Pathname potential_parallel_dir = path; - potential_parallel_dir.AppendFolder(parallel_dir); - if (rtc::Filesystem::IsFolder(potential_parallel_dir)) { - return potential_parallel_dir; - } - - path.SetFolder(path.parent_folder()); - } - return path; -} - -inline rtc::Pathname GetGoogle3Directory() { - return GetSiblingDirectory("google3"); -} - -inline rtc::Pathname GetTalkDirectory() { - return GetSiblingDirectory("talk"); -} - /////////////////////////////////////////////////////////////////////////////// // Unittest predicates which are similar to STREQ, but for raw memory /////////////////////////////////////////////////////////////////////////////// @@ -504,25 +458,6 @@ inline AssertionResult CmpHelperMemEq(const char* expected_expression, return AssertionFailure(msg); } -inline AssertionResult CmpHelperFileEq(const char* expected_expression, - const char* expected_length_expression, - const char* actual_filename, - const void* expected, - size_t expected_length, - const char* filename) -{ - std::string contents; - if (!ReadFile(filename, &contents)) { - Message msg; - msg << "File '" << filename << "' could not be read."; - return AssertionFailure(msg); - } - return CmpHelperMemEq(expected_expression, expected_length_expression, - actual_filename, "", - expected, expected_length, - contents.c_str(), contents.size()); -} - #define EXPECT_MEMEQ(expected, expected_length, actual, actual_length) \ EXPECT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \ actual, actual_length) @@ -531,14 +466,6 @@ inline AssertionResult CmpHelperFileEq(const char* expected_expression, ASSERT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \ actual, actual_length) -#define EXPECT_FILEEQ(expected, expected_length, filename) \ - EXPECT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \ - filename) - -#define ASSERT_FILEEQ(expected, expected_length, filename) \ - ASSERT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \ - filename) - /////////////////////////////////////////////////////////////////////////////// // Helpers for initializing constant memory with integers in a particular byte // order @@ -600,9 +527,9 @@ inline AssertionResult CmpHelperFileEq(const char* expected_expression, #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) struct XDisplay { - XDisplay() : display_(XOpenDisplay(NULL)) { } + XDisplay() : display_(XOpenDisplay(nullptr)) {} ~XDisplay() { if (display_) XCloseDisplay(display_); } - bool IsValid() const { return display_ != NULL; } + bool IsValid() const { return display_ != nullptr; } operator Display*() { return display_; } private: Display* display_; diff --git a/include/webrtc/base/thread.h b/include/webrtc/base/thread.h index 1a0c447..5751df3 100644 --- a/include/webrtc/base/thread.h +++ b/include/webrtc/base/thread.h @@ -56,7 +56,7 @@ class ThreadManager { // unexpected contexts (like inside browser plugins) and it would be a // shame to break it. It is also conceivable on Win32 that we won't even // be able to get synchronization privileges, in which case the result - // will have a NULL handle. + // will have a null handle. Thread *WrapCurrentThread(); void UnwrapCurrentThread(); @@ -93,7 +93,7 @@ class Runnable { // WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS! See ~Thread(). -class Thread : public MessageQueue { +class LOCKABLE Thread : public MessageQueue { public: // Create a new Thread and optionally assign it to the passed SocketServer. Thread(); @@ -133,12 +133,12 @@ class Thread : public MessageQueue { static bool SleepMs(int millis); // Sets the thread's name, for debugging. Must be called before Start(). - // If |obj| is non-NULL, its value is appended to |name|. + // If |obj| is non-null, its value is appended to |name|. const std::string& name() const { return name_; } bool SetName(const std::string& name, const void* obj); // Starts the execution of the thread. - bool Start(Runnable* runnable = NULL); + bool Start(Runnable* runnable = nullptr); // Tells the thread to stop and waits until it is joined. // Never call Stop on the current thread. Instead use the inherited Quit @@ -151,30 +151,30 @@ class Thread : public MessageQueue { // ProcessMessages occasionally. virtual void Run(); - virtual void Send(MessageHandler* phandler, + virtual void Send(const Location& posted_from, + MessageHandler* phandler, uint32_t id = 0, - MessageData* pdata = NULL); + MessageData* pdata = nullptr); // Convenience method to invoke a functor on another thread. Caller must // provide the |ReturnT| template argument, which cannot (easily) be deduced. // Uses Send() internally, which blocks the current thread until execution // is complete. - // Ex: bool result = thread.Invoke(&MyFunctionReturningBool); + // Ex: bool result = thread.Invoke(RTC_FROM_HERE, + // &MyFunctionReturningBool); // NOTE: This function can only be called when synchronous calls are allowed. // See ScopedDisallowBlockingCalls for details. template - ReturnT Invoke(const FunctorT& functor) { - InvokeBegin(); + ReturnT Invoke(const Location& posted_from, const FunctorT& functor) { FunctorMessageHandler handler(functor); - Send(&handler); - InvokeEnd(); - return handler.result(); + InvokeInternal(posted_from, &handler); + return handler.MoveResult(); } // From MessageQueue void Clear(MessageHandler* phandler, uint32_t id = MQID_ANY, - MessageList* removed = NULL) override; + MessageList* removed = nullptr) override; void ReceiveSends() override; // ProcessMessages will process I/O and dispatch messages until: @@ -238,7 +238,11 @@ class Thread : public MessageQueue { friend class ScopedDisallowBlockingCalls; private: +#if defined(WEBRTC_WIN) + static DWORD WINAPI PreRun(LPVOID context); +#else static void *PreRun(void *pv); +#endif // ThreadManager calls this instead WrapCurrent() because // ThreadManager::Instance() cannot be used while ThreadManager is @@ -251,19 +255,17 @@ class Thread : public MessageQueue { // Return true if the thread was started and hasn't yet stopped. bool running() { return running_.Wait(0); } - // Processes received "Send" requests. If |source| is not NULL, only requests + // Processes received "Send" requests. If |source| is not null, only requests // from |source| are processed, otherwise, all requests are processed. void ReceiveSendsFromThread(const Thread* source); - // If |source| is not NULL, pops the first "Send" message from |source| in + // If |source| is not null, pops the first "Send" message from |source| in // |sendlist_|, otherwise, pops the first "Send" message of |sendlist_|. // The caller must lock |crit_| before calling. // Returns true if there is such a message. bool PopSendMessageFromThread(const Thread* source, _SendMessage* msg); - // Used for tracking performance of Invoke calls. - void InvokeBegin(); - void InvokeEnd(); + void InvokeInternal(const Location& posted_from, MessageHandler* handler); std::list<_SendMessage> sendlist_; std::string name_; @@ -304,7 +306,7 @@ class AutoThread : public Thread { class ComThread : public Thread { public: ComThread() {} - ~ComThread() override { Stop(); } + ~ComThread() override; protected: void Run() override; diff --git a/include/webrtc/base/thread_annotations.h b/include/webrtc/base/thread_annotations.h index 612242d..8d5abbd 100644 --- a/include/webrtc/base/thread_annotations.h +++ b/include/webrtc/base/thread_annotations.h @@ -16,8 +16,8 @@ // of their multi-threaded code. The annotations can also help program // analysis tools to identify potential thread safety issues. -#ifndef BASE_THREAD_ANNOTATIONS_H_ -#define BASE_THREAD_ANNOTATIONS_H_ +#ifndef WEBRTC_BASE_THREAD_ANNOTATIONS_H_ +#define WEBRTC_BASE_THREAD_ANNOTATIONS_H_ #if defined(__clang__) && (!defined(SWIG)) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) @@ -31,7 +31,7 @@ // indicates a shared variable should be guarded (by any lock). GUARDED_VAR // is primarily used when the client cannot express the name of the lock. #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) -#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded) +#define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded_var) // Document if the memory location pointed to by a pointer should be guarded // by a lock when dereferencing the pointer. Similar to GUARDED_VAR, @@ -41,8 +41,8 @@ // q, which is guarded by mu1, points to a shared memory location that is // guarded by mu2, q should be annotated as follows: // int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); -#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x)) -#define PT_GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded) +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) +#define PT_GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_var) // Document the acquisition order between locks that can be held // simultaneously by a thread. For any two locks that need to be annotated @@ -65,7 +65,8 @@ // Document the locks acquired in the body of the function. These locks // cannot be held when calling this function (as google3's Mutex locks are // non-reentrant). -#define LOCKS_EXCLUDED(x) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x)) +#define LOCKS_EXCLUDED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) // Document the lock the annotated function returns without acquiring it. #define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) @@ -96,4 +97,4 @@ #define NO_THREAD_SAFETY_ANALYSIS \ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) -#endif // BASE_THREAD_ANNOTATIONS_H_ +#endif // WEBRTC_BASE_THREAD_ANNOTATIONS_H_ diff --git a/include/webrtc/base/thread_checker.h b/include/webrtc/base/thread_checker.h index 6cd7d7b..5914282 100644 --- a/include/webrtc/base/thread_checker.h +++ b/include/webrtc/base/thread_checker.h @@ -14,20 +14,14 @@ #define WEBRTC_BASE_THREAD_CHECKER_H_ // Apart from debug builds, we also enable the thread checker in -// builds with DCHECK_ALWAYS_ON so that trybots and waterfall bots +// builds with RTC_DCHECK_IS_ON so that trybots and waterfall bots // with this define will get the same level of thread checking as // debug bots. -// -// Note that this does not perfectly match situations where RTC_DCHECK is -// enabled. For example a non-official release build may have -// DCHECK_ALWAYS_ON undefined (and therefore ThreadChecker would be -// disabled) but have RTC_DCHECKs enabled at runtime. -#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) -#define ENABLE_THREAD_CHECKER 1 -#else -#define ENABLE_THREAD_CHECKER 0 -#endif +#define ENABLE_THREAD_CHECKER RTC_DCHECK_IS_ON +#include "webrtc/base/checks.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/thread_annotations.h" #include "webrtc/base/thread_checker_impl.h" namespace rtc { @@ -77,15 +71,108 @@ class ThreadCheckerDoNothing { // // In Release mode, CalledOnValidThread will always return true. #if ENABLE_THREAD_CHECKER -class ThreadChecker : public ThreadCheckerImpl { +class LOCKABLE ThreadChecker : public ThreadCheckerImpl { }; #else -class ThreadChecker : public ThreadCheckerDoNothing { +class LOCKABLE ThreadChecker : public ThreadCheckerDoNothing { }; #endif // ENABLE_THREAD_CHECKER #undef ENABLE_THREAD_CHECKER +namespace internal { +class SCOPED_LOCKABLE AnnounceOnThread { + public: + template + explicit AnnounceOnThread(const ThreadLikeObject* thread_like_object) + EXCLUSIVE_LOCK_FUNCTION(thread_like_object) {} + ~AnnounceOnThread() UNLOCK_FUNCTION() {} + + template + static bool IsCurrent(const ThreadLikeObject* thread_like_object) { + return thread_like_object->IsCurrent(); + } + static bool IsCurrent(const rtc::ThreadChecker* checker) { + return checker->CalledOnValidThread(); + } + + private: + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AnnounceOnThread); +}; + +} // namespace internal } // namespace rtc +// RUN_ON/ACCESS_ON/RTC_DCHECK_RUN_ON macros allows to annotate variables are +// accessed from same thread/task queue. +// Using tools designed to check mutexes, it checks at compile time everywhere +// variable is access, there is a run-time dcheck thread/task queue is correct. +// +// class ExampleThread { +// public: +// void NeedVar1() { +// RTC_DCHECK_RUN_ON(network_thread_); +// transport_->Send(); +// } +// +// private: +// rtc::Thread* network_thread_; +// int transport_ ACCESS_ON(network_thread_); +// }; +// +// class ExampleThreadChecker { +// public: +// int CalledFromPacer() RUN_ON(pacer_thread_checker_) { +// return var2_; +// } +// +// void CallMeFromPacer() { +// RTC_DCHECK_RUN_ON(&pacer_thread_checker_) +// << "Should be called from pacer"; +// CalledFromPacer(); +// } +// +// private: +// int pacer_var_ ACCESS_ON(pacer_thread_checker_); +// rtc::ThreadChecker pacer_thread_checker_; +// }; +// +// class TaskQueueExample { +// public: +// class Encoder { +// public: +// rtc::TaskQueue* Queue() { return encoder_queue_; } +// void Encode() { +// RTC_DCHECK_RUN_ON(encoder_queue_); +// DoSomething(var_); +// } +// +// private: +// rtc::TaskQueue* const encoder_queue_; +// Frame var_ ACCESS_ON(encoder_queue_); +// }; +// +// void Encode() { +// // Will fail at runtime when DCHECK is enabled: +// // encoder_->Encode(); +// // Will work: +// rtc::scoped_ref_ptr encoder = encoder_; +// encoder_->Queue()->PostTask([encoder] { encoder->Encode(); }); +// } +// +// private: +// rtc::scoped_ref_ptr encoder_; +// } + +// Document if a variable/field is not shared and should be accessed from +// same thread/task queue. +#define ACCESS_ON(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +// Document if a function expected to be called from same thread/task queue. +#define RUN_ON(x) THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) + +#define RTC_DCHECK_RUN_ON(thread_like_object) \ + rtc::internal::AnnounceOnThread thread_announcer(thread_like_object); \ + RTC_DCHECK(rtc::internal::AnnounceOnThread::IsCurrent(thread_like_object)) + #endif // WEBRTC_BASE_THREAD_CHECKER_H_ diff --git a/include/webrtc/base/timedelta.h b/include/webrtc/base/timedelta.h new file mode 100644 index 0000000..71c7f9f --- /dev/null +++ b/include/webrtc/base/timedelta.h @@ -0,0 +1,129 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_TIMEDELTA_H_ +#define WEBRTC_BASE_TIMEDELTA_H_ + +#include + +#include "webrtc/base/timeutils.h" + +// Convenience class to convert between different units of relative time. +// Stores time to precision of nanoseconds, as int64_t internally. +// Doesn't check for overflow/underflow. +// +// Based on TimeDelta in: +// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time.h +namespace rtc { + +class TimeDelta { + public: + TimeDelta() : delta_(0) {} + + // Converts units of time to TimeDeltas. + static constexpr TimeDelta FromSeconds(int64_t secs) { + return TimeDelta(secs * kNumNanosecsPerSec); + } + static constexpr TimeDelta FromMilliseconds(int64_t ms) { + return TimeDelta(ms * kNumNanosecsPerMillisec); + } + static constexpr TimeDelta FromMicroseconds(int64_t us) { + return TimeDelta(us * kNumNanosecsPerMicrosec); + } + static constexpr TimeDelta FromNanoseconds(int64_t ns) { + return TimeDelta(ns); + } + + // Returns true if the time delta is zero. + bool is_zero() const { return delta_ == 0; } + + // Converts TimeDelta to units of time. + int64_t ToSeconds() const { return delta_ / kNumNanosecsPerSec; } + int64_t ToMilliseconds() const { return delta_ / kNumNanosecsPerMillisec; } + int64_t ToMicroseconds() const { return delta_ / kNumNanosecsPerMicrosec; } + int64_t ToNanoseconds() const { return delta_; } + + TimeDelta& operator=(TimeDelta other) { + delta_ = other.delta_; + return *this; + } + + // Computations with other deltas. + TimeDelta operator+(TimeDelta other) const { + return TimeDelta(delta_ + other.delta_); + } + TimeDelta operator-(TimeDelta other) const { + return TimeDelta(delta_ + other.delta_); + } + + TimeDelta& operator+=(TimeDelta other) { return *this = (*this + other); } + TimeDelta& operator-=(TimeDelta other) { return *this = (*this - other); } + TimeDelta operator-() const { return TimeDelta(-delta_); } + + // Computations with numeric types. + template + TimeDelta operator*(T a) const { + return TimeDelta(delta_ * a); + } + template + TimeDelta operator/(T a) const { + return TimeDelta(delta_ / a); + } + template + TimeDelta& operator*=(T a) { + return *this = (*this * a); + } + template + TimeDelta& operator/=(T a) { + return *this = (*this / a); + } + + TimeDelta operator%(TimeDelta a) const { + return TimeDelta(delta_ % a.delta_); + } + + // Comparison operators. + constexpr bool operator==(TimeDelta other) const { + return delta_ == other.delta_; + } + constexpr bool operator!=(TimeDelta other) const { + return delta_ != other.delta_; + } + constexpr bool operator<(TimeDelta other) const { + return delta_ < other.delta_; + } + constexpr bool operator<=(TimeDelta other) const { + return delta_ <= other.delta_; + } + constexpr bool operator>(TimeDelta other) const { + return delta_ > other.delta_; + } + constexpr bool operator>=(TimeDelta other) const { + return delta_ >= other.delta_; + } + + private: + // Constructs a delta given the duration in nanoseconds. This is private + // to avoid confusion by callers with an integer constructor. Use + // FromSeconds, FromMilliseconds, etc. instead. + constexpr explicit TimeDelta(int64_t delta_ns) : delta_(delta_ns) {} + + // Delta in nanoseconds. + int64_t delta_; +}; + +template +inline TimeDelta operator*(T a, TimeDelta td) { + return td * a; +} + +} // namespace rtc + +#endif // WEBRTC_BASE_TIMEDELTA_H_ diff --git a/include/webrtc/base/timestampaligner.h b/include/webrtc/base/timestampaligner.h new file mode 100644 index 0000000..9c2cc7a --- /dev/null +++ b/include/webrtc/base/timestampaligner.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_TIMESTAMPALIGNER_H_ +#define WEBRTC_BASE_TIMESTAMPALIGNER_H_ + +#include + +#include "webrtc/base/constructormagic.h" + +namespace rtc { + +// The TimestampAligner class helps translating camera timestamps into +// the same timescale as is used by rtc::TimeMicros(). Some cameras +// have built in timestamping which is more accurate than reading the +// system clock, but using a different epoch and unknown clock drift. +// Frame timestamps in webrtc should use rtc::TimeMicros (system monotonic +// time), and this class provides a filter which lets us use the +// rtc::TimeMicros timescale, and at the same time take advantage of +// higher accuracy of the camera clock. + +// This class is not thread safe, so all calls to it must be synchronized +// externally. +class TimestampAligner { + public: + TimestampAligner(); + ~TimestampAligner(); + + public: + // Translates camera timestamps to the same timescale as is used by + // rtc::TimeMicros(). |camera_time_us| is assumed to be accurate, but + // with an unknown epoch and clock drift. |system_time_us| is + // time according to rtc::TimeMicros(), preferably read as soon as + // possible when the frame is captured. It may have poor accuracy + // due to poor resolution or scheduling delays. Returns the + // translated timestamp. + int64_t TranslateTimestamp(int64_t camera_time_us, int64_t system_time_us); + + protected: + // Update the estimated offset between camera time and system monotonic time. + int64_t UpdateOffset(int64_t camera_time_us, int64_t system_time_us); + + // Clip timestamp, return value is always + // <= |system_time_us|, and + // >= min(|prev_translated_time_us_| + |kMinFrameIntervalUs|, + // |system_time_us|). + int64_t ClipTimestamp(int64_t filtered_time_us, int64_t system_time_us); + + private: + // State for the timestamp translation. + int frames_seen_; + // Estimated offset between camera time and system monotonic time. + int64_t offset_us_; + + // State for the ClipTimestamp method, applied after the filter. + // A large negative camera clock drift tends to push translated + // timestamps into the future. |clip_bias_us_| is subtracted from the + // translated timestamps, to get them back from the future. + int64_t clip_bias_us_; + // Used to ensure that translated timestamps are monotonous. + int64_t prev_translated_time_us_; + RTC_DISALLOW_COPY_AND_ASSIGN(TimestampAligner); +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_TIMESTAMPALIGNER_H_ diff --git a/include/webrtc/base/timeutils.h b/include/webrtc/base/timeutils.h index 222d5c2..be9edab 100644 --- a/include/webrtc/base/timeutils.h +++ b/include/webrtc/base/timeutils.h @@ -11,10 +11,10 @@ #ifndef WEBRTC_BASE_TIMEUTILS_H_ #define WEBRTC_BASE_TIMEUTILS_H_ -#include +#include #include -#include "webrtc/base/basictypes.h" +#include namespace rtc { @@ -31,6 +31,33 @@ static const int64_t kNumNanosecsPerMicrosec = // TODO(honghaiz): Define a type for the time value specifically. +class ClockInterface { + public: + virtual ~ClockInterface() {} + virtual int64_t TimeNanos() const = 0; +}; + +// Sets the global source of time. This is useful mainly for unit tests. +// +// Returns the previously set ClockInterface, or nullptr if none is set. +// +// Does not transfer ownership of the clock. SetClockForTesting(nullptr) +// should be called before the ClockInterface is deleted. +// +// This method is not thread-safe; it should only be used when no other thread +// is running (for example, at the start/end of a unit test, or start/end of +// main()). +// +// TODO(deadbeef): Instead of having functions that access this global +// ClockInterface, we may want to pass the ClockInterface into everything +// that uses it, eliminating the need for a global variable and this function. +ClockInterface* SetClockForTesting(ClockInterface* clock); + +// Returns the actual system time, even if a clock is set for testing. +// Useful for timeouts while using a test clock, or for logging. +int64_t SystemTimeNanos(); +int64_t SystemTimeMillis(); + // Returns the current time in milliseconds in 32 bits. uint32_t Time32(); @@ -42,10 +69,11 @@ inline int64_t Time() { } // Returns the current time in microseconds. -uint64_t TimeMicros(); +int64_t TimeMicros(); // Returns the current time in nanoseconds. -uint64_t TimeNanos(); +int64_t TimeNanos(); + // Returns a future timestamp, 'elapsed' milliseconds from now. int64_t TimeAfter(int64_t elapsed); @@ -61,7 +89,7 @@ inline int64_t TimeSince(int64_t earlier) { } // The number of milliseconds that will elapse between now and 'later'. -inline int64_t TimeUntil(uint64_t later) { +inline int64_t TimeUntil(int64_t later) { return later - TimeMillis(); } @@ -81,6 +109,18 @@ class TimestampWrapAroundHandler { // is still 32 bits on many systems. int64_t TmToSeconds(const std::tm& tm); +// Return the number of microseconds since January 1, 1970, UTC. +// Useful mainly when producing logs to be correlated with other +// devices, and when the devices in question all have properly +// synchronized clocks. +// +// Note that this function obeys the system's idea about what the time +// is. It is not guaranteed to be monotonic; it will jump in case the +// system time is changed, e.g., by some other process calling +// settimeofday. Always use rtc::TimeMicros(), not this function, for +// measuring time intervals and timeouts. +int64_t TimeUTCMicros(); + } // namespace rtc #endif // WEBRTC_BASE_TIMEUTILS_H_ diff --git a/include/webrtc/base/timing.h b/include/webrtc/base/timing.h deleted file mode 100644 index e709f88..0000000 --- a/include/webrtc/base/timing.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_TIMING_H_ -#define WEBRTC_BASE_TIMING_H_ - -namespace rtc { - -class Timing { - public: - Timing(); - virtual ~Timing(); - - // WallTimeNow() returns the current wall-clock time in seconds, - // within 10 milliseconds resolution. - // WallTimeNow is static and does not require a timer_handle_ on Windows. - static double WallTimeNow(); - - // TimerNow() is like WallTimeNow(), but is monotonically - // increasing. It returns seconds in resolution of 10 microseconds - // or better. Although timer and wall-clock time have the same - // timing unit, they do not necessarily correlate because wall-clock - // time may be adjusted backwards, hence not monotonic. - // Made virtual so we can make a fake one. - // TODO(tommi): The only place we use this (virtual) is in - // rtpdata_engine_unittest.cc. See if it doesn't make more sense to change - // that contract or test than to modify this generic class. - virtual double TimerNow(); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_TIMING_H_ diff --git a/include/webrtc/base/trace_event.h b/include/webrtc/base/trace_event.h index 3916af4..3e99374 100644 --- a/include/webrtc/base/trace_event.h +++ b/include/webrtc/base/trace_event.h @@ -577,11 +577,8 @@ // Implementation detail: internal macro to create static category. #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ - static const unsigned char* INTERNAL_TRACE_EVENT_UID(catstatic) = 0; \ - if (!INTERNAL_TRACE_EVENT_UID(catstatic)) { \ - INTERNAL_TRACE_EVENT_UID(catstatic) = \ - TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); \ - } + static const unsigned char* INTERNAL_TRACE_EVENT_UID(catstatic) = \ + TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); // Implementation detail: internal macro to create static category and add // event if the category is enabled. @@ -820,10 +817,9 @@ static inline void AddTraceEvent(char phase, const char* name, unsigned long long id, unsigned char flags) { - TRACE_EVENT_API_ADD_TRACE_EVENT( - phase, category_enabled, name, id, - kZeroNumArgs, NULL, NULL, NULL, - flags); + TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_enabled, name, id, + kZeroNumArgs, nullptr, nullptr, nullptr, + flags); } template @@ -870,7 +866,7 @@ static inline void AddTraceEvent(char phase, class TraceEndOnScopeClose { public: // Note: members of data_ intentionally left uninitialized. See Initialize. - TraceEndOnScopeClose() : p_data_(NULL) {} + TraceEndOnScopeClose() : p_data_(nullptr) {} ~TraceEndOnScopeClose() { if (p_data_) AddEventIfEnabled(); @@ -888,12 +884,10 @@ class TraceEndOnScopeClose { void AddEventIfEnabled() { // Only called when p_data_ is non-null. if (*p_data_->category_enabled) { - TRACE_EVENT_API_ADD_TRACE_EVENT( - TRACE_EVENT_PHASE_END, - p_data_->category_enabled, - p_data_->name, kNoEventId, - kZeroNumArgs, NULL, NULL, NULL, - TRACE_EVENT_FLAG_NONE); + TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_END, + p_data_->category_enabled, p_data_->name, + kNoEventId, kZeroNumArgs, nullptr, + nullptr, nullptr, TRACE_EVENT_FLAG_NONE); } } diff --git a/include/webrtc/base/type_traits.h b/include/webrtc/base/type_traits.h new file mode 100644 index 0000000..d6a6c37 --- /dev/null +++ b/include/webrtc/base/type_traits.h @@ -0,0 +1,77 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_TYPE_TRAITS_H_ +#define WEBRTC_BASE_TYPE_TRAITS_H_ + +#include +#include + +namespace rtc { + +// Determines if the given class has zero-argument .data() and .size() methods +// whose return values are convertible to T* and size_t, respectively. +template +class HasDataAndSize { + private: + template < + typename C, + typename std::enable_if< + std::is_convertible().data()), T*>::value && + std::is_convertible().size()), + std::size_t>::value>::type* = nullptr> + static int Test(int); + + template + static char Test(...); + + public: + static constexpr bool value = std::is_same(0)), int>::value; +}; + +namespace test_has_data_and_size { + +template +struct Test1 { + DR data(); + SR size(); +}; +static_assert(HasDataAndSize, int>::value, ""); +static_assert(HasDataAndSize, const int>::value, ""); +static_assert(HasDataAndSize, const int>::value, ""); +static_assert(!HasDataAndSize, int>::value, + "implicit cast of const int* to int*"); +static_assert(!HasDataAndSize, int>::value, + "implicit cast of char* to int*"); + +struct Test2 { + int* data; + size_t size; +}; +static_assert(!HasDataAndSize::value, + ".data and .size aren't functions"); + +struct Test3 { + int* data(); +}; +static_assert(!HasDataAndSize::value, ".size() is missing"); + +class Test4 { + int* data(); + size_t size(); +}; +static_assert(!HasDataAndSize::value, + ".data() and .size() are private"); + +} // namespace test_has_data_and_size + +} // namespace rtc + +#endif // WEBRTC_BASE_TYPE_TRAITS_H_ diff --git a/include/webrtc/base/unixfilesystem.h b/include/webrtc/base/unixfilesystem.h index dbfbaf0..6f90959 100644 --- a/include/webrtc/base/unixfilesystem.h +++ b/include/webrtc/base/unixfilesystem.h @@ -22,7 +22,7 @@ class UnixFilesystem : public FilesystemInterface { UnixFilesystem(); ~UnixFilesystem() override; -#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) +#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC) // Android does not have a native code API to fetch the app data or temp // folders. That needs to be passed into this class from Java. Similarly, iOS // only supports an Objective-C API for fetching the folder locations, so that @@ -35,20 +35,16 @@ class UnixFilesystem : public FilesystemInterface { #endif // Opens a file. Returns an open StreamInterface if function succeeds. - // Otherwise, returns NULL. + // Otherwise, returns null. FileStream* OpenFile(const Pathname& filename, const std::string& mode) override; - // Atomically creates an empty file accessible only to the current user if one - // does not already exist at the given path, otherwise fails. - bool CreatePrivateFile(const Pathname& filename) override; - // This will attempt to delete the file located at filename. // It will fail with VERIY if you pass it a non-existant file, or a directory. bool DeleteFile(const Pathname& filename) override; // This will attempt to delete the folder located at 'folder' - // It ASSERTs and returns false if you pass it a non-existant folder or a + // It DCHECKs and returns false if you pass it a non-existant folder or a // plain file. bool DeleteEmptyFolder(const Pathname& folder) override; @@ -65,7 +61,6 @@ class UnixFilesystem : public FilesystemInterface { // file or directory, which will be moved recursively. // Returns true if function succeeds. bool MoveFile(const Pathname& old_path, const Pathname& new_path) override; - bool MoveFolder(const Pathname& old_path, const Pathname& new_path) override; // This copies a file from old_path to _new_path where "file" can be a plain // file or directory, which will be copied recursively. @@ -99,21 +94,11 @@ class UnixFilesystem : public FilesystemInterface { FileTimeType which, time_t* time) override; - // Returns the path to the running application. - bool GetAppPathname(Pathname* path) override; - - bool GetAppDataFolder(Pathname* path, bool per_user) override; - // Get a temporary folder that is unique to the current user and application. bool GetAppTempFolder(Pathname* path) override; - bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) override; - - // Returns the absolute path of the current directory. - Pathname GetCurrentDirectory() override; - private: -#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) +#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC) static char* provided_app_data_folder_; static char* provided_app_temp_folder_; #else diff --git a/include/webrtc/base/urlencode.h b/include/webrtc/base/urlencode.h deleted file mode 100644 index fc10f38..0000000 --- a/include/webrtc/base/urlencode.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2008 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef _URLENCODE_H_ -#define _URLENCODE_H_ - -#include - -namespace rtc { - -// Decode all encoded characters. Also decode + as space. -int UrlDecode(const char *source, char *dest); - -// Decode all encoded characters. -int UrlDecodeWithoutEncodingSpaceAsPlus(const char *source, char *dest); - -// Encode all characters except alphas, numbers, and -_.!~*'() -// Also encode space as +. -int UrlEncode(const char *source, char *dest, unsigned max); - -// Encode all characters except alphas, numbers, and -_.!~*'() -int UrlEncodeWithoutEncodingSpaceAsPlus(const char *source, char *dest, - unsigned max); - -// Encode only unsafe chars, including \ "^&`<>[]{} -// Also encode space as %20, instead of + -int UrlEncodeOnlyUnsafeChars(const char *source, char *dest, unsigned max); - -std::string UrlDecodeString(const std::string & encoded); -std::string UrlDecodeStringWithoutEncodingSpaceAsPlus( - const std::string & encoded); -std::string UrlEncodeString(const std::string & decoded); -std::string UrlEncodeStringWithoutEncodingSpaceAsPlus( - const std::string & decoded); -std::string UrlEncodeStringForOnlyUnsafeChars(const std::string & decoded); - -#endif - -} // namespace rtc diff --git a/include/webrtc/base/versionparsing.h b/include/webrtc/base/versionparsing.h deleted file mode 100644 index be2d332..0000000 --- a/include/webrtc/base/versionparsing.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_VERSIONPARSING_H_ -#define WEBRTC_BASE_VERSIONPARSING_H_ - -#include - -namespace rtc { - -// Parses a version string into an array. "num_expected_segments" must be the -// number of numerical segments that the version is expected to have (e.g., -// "1.1.2.0" has 4). "version" must be an array of that length to hold the -// parsed numbers. -// Returns "true" iff successful. -bool ParseVersionString(const std::string& version_str, - int num_expected_segments, - int version[]); - -// Computes the lexicographical order of two versions. The return value -// indicates the order in the standard way (e.g., see strcmp()). -int CompareVersions(const int version1[], - const int version2[], - int num_segments); - -} // namespace rtc - -#endif // WEBRTC_BASE_VERSIONPARSING_H_ diff --git a/include/webrtc/base/virtualsocketserver.h b/include/webrtc/base/virtualsocketserver.h index 897ba9e..3d4171b 100644 --- a/include/webrtc/base/virtualsocketserver.h +++ b/include/webrtc/base/virtualsocketserver.h @@ -11,11 +11,10 @@ #ifndef WEBRTC_BASE_VIRTUALSOCKETSERVER_H_ #define WEBRTC_BASE_VIRTUALSOCKETSERVER_H_ -#include - #include #include +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/messagequeue.h" #include "webrtc/base/socketserver.h" @@ -86,10 +85,21 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { // is separate from calculations to drop based on queue size. double drop_probability() { return drop_prob_; } void set_drop_probability(double drop_prob) { - assert((0 <= drop_prob) && (drop_prob <= 1)); + RTC_DCHECK_GE(drop_prob, 0.0); + RTC_DCHECK_LE(drop_prob, 1.0); drop_prob_ = drop_prob; } + // If |blocked| is true, subsequent attempts to send will result in -1 being + // returned, with the socket error set to EWOULDBLOCK. + // + // If this method is later called with |blocked| set to false, any sockets + // that previously failed to send with EWOULDBLOCK will emit SignalWriteEvent. + // + // This can be used to simulate the send buffer on a network interface being + // full, and test functionality related to EWOULDBLOCK/SignalWriteEvent. + void SetSendingBlocked(bool blocked); + // SocketFactory: Socket* CreateSocket(int type) override; Socket* CreateSocket(int family, int type) override; @@ -102,6 +112,10 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { bool Wait(int cms, bool process_io) override; void WakeUp() override; + void SetDelayOnAddress(const rtc::SocketAddress& address, int delay_ms) { + delay_by_ip_[address.ipaddr()] = delay_ms; + } + typedef std::pair Point; typedef std::vector Function; @@ -184,8 +198,10 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { // Computes the number of milliseconds required to send a packet of this size. uint32_t SendDelay(uint32_t size); - // Returns a random transit delay chosen from the appropriate distribution. - uint32_t GetRandomTransitDelay(); + // If the delay has been set for the address of the socket, returns the set + // delay. Otherwise, returns a random transit delay chosen from the + // appropriate distribution. + uint32_t GetTransitDelay(Socket* socket); // Basic operations on functions. Those that return a function also take // ownership of the function given (and hence, may modify or delete it). @@ -197,10 +213,10 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { uint32_t samples); static double Evaluate(Function* f, double x); - // NULL out our message queue if it goes away. Necessary in the case where + // Null out our message queue if it goes away. Necessary in the case where // our lifetime is greater than that of the thread we are using, since we // try to send Close messages for all connected sockets when we shutdown. - void OnMessageQueueDestroyed() { msg_queue_ = NULL; } + void OnMessageQueueDestroyed() { msg_queue_ = nullptr; } // Determine if two sockets should be able to communicate. // We don't (currently) specify an address family for sockets; instead, @@ -223,6 +239,9 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { private: friend class VirtualSocket; + // Sending was previously blocked, but now isn't. + sigslot::signal0<> SignalReadyToSend; + typedef std::map AddressMap; typedef std::map ConnectionMap; @@ -230,7 +249,6 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { bool server_owned_; MessageQueue* msg_queue_; bool stop_on_idle_; - int64_t network_delay_; in_addr next_ipv4_; in6_addr next_ipv6_; uint16_t next_port_; @@ -247,16 +265,22 @@ class VirtualSocketServer : public SocketServer, public sigslot::has_slots<> { uint32_t delay_mean_; uint32_t delay_stddev_; uint32_t delay_samples_; - Function* delay_dist_; + + std::map delay_by_ip_; + std::unique_ptr delay_dist_; + CriticalSection delay_crit_; double drop_prob_; + bool sending_blocked_ = false; RTC_DISALLOW_COPY_AND_ASSIGN(VirtualSocketServer); }; // Implements the socket interface using the virtual network. Packets are // passed as messages using the message queue of the socket server. -class VirtualSocket : public AsyncSocket, public MessageHandler { +class VirtualSocket : public AsyncSocket, + public MessageHandler, + public sigslot::has_slots<> { public: VirtualSocket(VirtualSocketServer* server, int family, int type, bool async); ~VirtualSocket() override; @@ -274,8 +298,11 @@ class VirtualSocket : public AsyncSocket, public MessageHandler { int Close() override; int Send(const void* pv, size_t cb) override; int SendTo(const void* pv, size_t cb, const SocketAddress& addr) override; - int Recv(void* pv, size_t cb) override; - int RecvFrom(void* pv, size_t cb, SocketAddress* paddr) override; + int Recv(void* pv, size_t cb, int64_t* timestamp) override; + int RecvFrom(void* pv, + size_t cb, + SocketAddress* paddr, + int64_t* timestamp) override; int Listen(int backlog) override; VirtualSocket* Accept(SocketAddress* paddr) override; @@ -313,6 +340,8 @@ class VirtualSocket : public AsyncSocket, public MessageHandler { // Used by server sockets to set the local address without binding. void SetLocalAddress(const SocketAddress& addr); + void OnSocketServerReadyToSend(); + VirtualSocketServer* server_; int type_; bool async_; @@ -327,7 +356,9 @@ class VirtualSocket : public AsyncSocket, public MessageHandler { // Data which tcp has buffered for sending SendBuffer send_buffer_; - bool write_enabled_; + // Set to false if the last attempt to send resulted in EWOULDBLOCK. + // Set back to true when the socket can send again. + bool ready_to_send_ = true; // Critical section to protect the recv_buffer and queue_ CriticalSection crit_; @@ -335,6 +366,9 @@ class VirtualSocket : public AsyncSocket, public MessageHandler { // Network model that enforces bandwidth and capacity constraints NetworkQueue network_; size_t network_size_; + // The scheduled delivery time of the last packet sent on this socket. + // It is used to ensure ordered delivery of packets sent on this socket. + int64_t last_delivery_time_ = 0; // Data which has been received from the network RecvBuffer recv_buffer_; diff --git a/include/webrtc/base/weak_ptr.h b/include/webrtc/base/weak_ptr.h new file mode 100644 index 0000000..28789d0 --- /dev/null +++ b/include/webrtc/base/weak_ptr.h @@ -0,0 +1,272 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_BASE_WEAK_PTR_H_ +#define WEBRTC_BASE_WEAK_PTR_H_ + +#include + +#include + +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/base/sequenced_task_checker.h" + +// The implementation is borrowed from chromium except that it does not +// implement SupportsWeakPtr. + +// Weak pointers are pointers to an object that do not affect its lifetime, +// and which may be invalidated (i.e. reset to nullptr) by the object, or its +// owner, at any time, most commonly when the object is about to be deleted. + +// Weak pointers are useful when an object needs to be accessed safely by one +// or more objects other than its owner, and those callers can cope with the +// object vanishing and e.g. tasks posted to it being silently dropped. +// Reference-counting such an object would complicate the ownership graph and +// make it harder to reason about the object's lifetime. + +// EXAMPLE: +// +// class Controller { +// public: +// Controller() : weak_factory_(this) {} +// void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); } +// void WorkComplete(const Result& result) { ... } +// private: +// // Member variables should appear before the WeakPtrFactory, to ensure +// // that any WeakPtrs to Controller are invalidated before its members +// // variable's destructors are executed, rendering them invalid. +// WeakPtrFactory weak_factory_; +// }; +// +// class Worker { +// public: +// static void StartNew(const WeakPtr& controller) { +// Worker* worker = new Worker(controller); +// // Kick off asynchronous processing... +// } +// private: +// Worker(const WeakPtr& controller) +// : controller_(controller) {} +// void DidCompleteAsynchronousProcessing(const Result& result) { +// if (controller_) +// controller_->WorkComplete(result); +// } +// WeakPtr controller_; +// }; +// +// With this implementation a caller may use SpawnWorker() to dispatch multiple +// Workers and subsequently delete the Controller, without waiting for all +// Workers to have completed. + +// ------------------------- IMPORTANT: Thread-safety ------------------------- + +// Weak pointers may be passed safely between threads, but must always be +// dereferenced and invalidated on the same TaskQueue or thread, otherwise +// checking the pointer would be racey. +// +// To ensure correct use, the first time a WeakPtr issued by a WeakPtrFactory +// is dereferenced, the factory and its WeakPtrs become bound to the calling +// TaskQueue/thread, and cannot be dereferenced or +// invalidated on any other TaskQueue/thread. Bound WeakPtrs can still be handed +// off to other TaskQueues, e.g. to use to post tasks back to object on the +// bound sequence. +// +// Thus, at least one WeakPtr object must exist and have been dereferenced on +// the correct thread to enforce that other WeakPtr objects will enforce they +// are used on the desired thread. + +namespace rtc { + +namespace internal { + +class WeakReference { + public: + // Although Flag is bound to a specific sequence, it may be + // deleted from another via base::WeakPtr::~WeakPtr(). + class Flag : public RefCountInterface { + public: + Flag(); + + void Invalidate(); + bool IsValid() const; + + private: + friend class RefCountedObject; + + ~Flag() override; + + SequencedTaskChecker checker_; + bool is_valid_; + }; + + WeakReference(); + explicit WeakReference(const Flag* flag); + ~WeakReference(); + + WeakReference(WeakReference&& other); + WeakReference(const WeakReference& other); + WeakReference& operator=(WeakReference&& other) = default; + WeakReference& operator=(const WeakReference& other) = default; + + bool is_valid() const; + + private: + scoped_refptr flag_; +}; + +class WeakReferenceOwner { + public: + WeakReferenceOwner(); + ~WeakReferenceOwner(); + + WeakReference GetRef() const; + + bool HasRefs() const { return flag_.get() && !flag_->HasOneRef(); } + + void Invalidate(); + + private: + SequencedTaskChecker checker_; + mutable scoped_refptr> flag_; +}; + +// This class simplifies the implementation of WeakPtr's type conversion +// constructor by avoiding the need for a public accessor for ref_. A +// WeakPtr cannot access the private members of WeakPtr, so this +// base class gives us a way to access ref_ in a protected fashion. +class WeakPtrBase { + public: + WeakPtrBase(); + ~WeakPtrBase(); + + WeakPtrBase(const WeakPtrBase& other) = default; + WeakPtrBase(WeakPtrBase&& other) = default; + WeakPtrBase& operator=(const WeakPtrBase& other) = default; + WeakPtrBase& operator=(WeakPtrBase&& other) = default; + + protected: + explicit WeakPtrBase(const WeakReference& ref); + + WeakReference ref_; +}; + +} // namespace internal + +template +class WeakPtrFactory; + +template +class WeakPtr : public internal::WeakPtrBase { + public: + WeakPtr() : ptr_(nullptr) {} + + // Allow conversion from U to T provided U "is a" T. Note that this + // is separate from the (implicit) copy and move constructors. + template + WeakPtr(const WeakPtr& other) + : internal::WeakPtrBase(other), ptr_(other.ptr_) {} + template + WeakPtr(WeakPtr&& other) + : internal::WeakPtrBase(std::move(other)), ptr_(other.ptr_) {} + + T* get() const { return ref_.is_valid() ? ptr_ : nullptr; } + + T& operator*() const { + RTC_DCHECK(get() != nullptr); + return *get(); + } + T* operator->() const { + RTC_DCHECK(get() != nullptr); + return get(); + } + + void reset() { + ref_ = internal::WeakReference(); + ptr_ = nullptr; + } + + // Allow conditionals to test validity, e.g. if (weak_ptr) {...}; + explicit operator bool() const { return get() != nullptr; } + + private: + template + friend class WeakPtr; + friend class WeakPtrFactory; + + WeakPtr(const internal::WeakReference& ref, T* ptr) + : internal::WeakPtrBase(ref), ptr_(ptr) {} + + // This pointer is only valid when ref_.is_valid() is true. Otherwise, its + // value is undefined (as opposed to nullptr). + T* ptr_; +}; + +// Allow callers to compare WeakPtrs against nullptr to test validity. +template +bool operator!=(const WeakPtr& weak_ptr, std::nullptr_t) { + return !(weak_ptr == nullptr); +} +template +bool operator!=(std::nullptr_t, const WeakPtr& weak_ptr) { + return weak_ptr != nullptr; +} +template +bool operator==(const WeakPtr& weak_ptr, std::nullptr_t) { + return weak_ptr.get() == nullptr; +} +template +bool operator==(std::nullptr_t, const WeakPtr& weak_ptr) { + return weak_ptr == nullptr; +} + +// A class may be composed of a WeakPtrFactory and thereby +// control how it exposes weak pointers to itself. This is helpful if you only +// need weak pointers within the implementation of a class. This class is also +// useful when working with primitive types. For example, you could have a +// WeakPtrFactory that is used to pass around a weak reference to a bool. + +// Note that GetWeakPtr must be called on one and only one TaskQueue or thread +// and the WeakPtr must only be dereferenced and invalidated on that same +// TaskQueue/thread. A WeakPtr instance can be copied and posted to other +// sequences though as long as it is not dereferenced (WeakPtr::get()). +template +class WeakPtrFactory { + public: + explicit WeakPtrFactory(T* ptr) : ptr_(ptr) {} + + ~WeakPtrFactory() { ptr_ = nullptr; } + + WeakPtr GetWeakPtr() { + RTC_DCHECK(ptr_); + return WeakPtr(weak_reference_owner_.GetRef(), ptr_); + } + + // Call this method to invalidate all existing weak pointers. + void InvalidateWeakPtrs() { + RTC_DCHECK(ptr_); + weak_reference_owner_.Invalidate(); + } + + // Call this method to determine if any weak pointers exist. + bool HasWeakPtrs() const { + RTC_DCHECK(ptr_); + return weak_reference_owner_.HasRefs(); + } + + private: + internal::WeakReferenceOwner weak_reference_owner_; + T* ptr_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WeakPtrFactory); +}; + +} // namespace rtc + +#endif // WEBRTC_BASE_WEAK_PTR_H_ diff --git a/include/webrtc/base/win32.h b/include/webrtc/base/win32.h index dba9b77..22a17c5 100644 --- a/include/webrtc/base/win32.h +++ b/include/webrtc/base/win32.h @@ -48,7 +48,7 @@ int win32_inet_pton(int af, const char* src, void *dst); inline std::wstring ToUtf16(const char* utf8, size_t len) { int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast(len), - NULL, 0); + nullptr, 0); wchar_t* ws = STACK_ARRAY(wchar_t, len16); ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast(len), ws, len16); return std::wstring(ws, len16); @@ -60,10 +60,10 @@ inline std::wstring ToUtf16(const std::string& str) { inline std::string ToUtf8(const wchar_t* wide, size_t len) { int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), - NULL, 0, NULL, NULL); + nullptr, 0, nullptr, nullptr); char* ns = STACK_ARRAY(char, len8); ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast(len), ns, len8, - NULL, NULL); + nullptr, nullptr); return std::string(ns, len8); } @@ -98,21 +98,19 @@ bool GetOsVersion(int* major, int* minor, int* build); inline bool IsWindowsVistaOrLater() { int major; - return (GetOsVersion(&major, NULL, NULL) && major >= kWindowsVista); + return (GetOsVersion(&major, nullptr, nullptr) && major >= kWindowsVista); } inline bool IsWindowsXpOrLater() { int major, minor; - return (GetOsVersion(&major, &minor, NULL) && - (major >= kWindowsVista || - (major == kWindows2000 && minor >= 1))); + return (GetOsVersion(&major, &minor, nullptr) && + (major >= kWindowsVista || (major == kWindows2000 && minor >= 1))); } inline bool IsWindows8OrLater() { int major, minor; - return (GetOsVersion(&major, &minor, NULL) && - (major > kWindowsVista || - (major == kWindowsVista && minor >= 2))); + return (GetOsVersion(&major, &minor, nullptr) && + (major > kWindowsVista || (major == kWindowsVista && minor >= 2))); } // Determine the current integrity level of the process. diff --git a/include/webrtc/base/win32filesystem.h b/include/webrtc/base/win32filesystem.h index 439b2c6..3ceaa20 100644 --- a/include/webrtc/base/win32filesystem.h +++ b/include/webrtc/base/win32filesystem.h @@ -17,15 +17,11 @@ namespace rtc { class Win32Filesystem : public FilesystemInterface { public: - // Opens a file. Returns an open StreamInterface if function succeeds. Otherwise, - // returns NULL. + // Opens a file. Returns an open StreamInterface if function succeeds. + // Otherwise, returns null. virtual FileStream *OpenFile(const Pathname &filename, const std::string &mode); - // Atomically creates an empty file accessible only to the current user if one - // does not already exist at the given path, otherwise fails. - virtual bool CreatePrivateFile(const Pathname &filename); - // This will attempt to delete the path located at filename. // If the path points to a folder, it will fail with VERIFY virtual bool DeleteFile(const Pathname &filename); @@ -45,11 +41,6 @@ class Win32Filesystem : public FilesystemInterface { // Returns true if the file is successfully moved virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path); - // Moves a folder from old_path to new_path. If the new path is on a different - // volume from the old, it will attempt to Copy and then Delete the folder - // Returns true if the folder is successfully moved - virtual bool MoveFolder(const Pathname &old_path, const Pathname &new_path); - // This copies a file from old_path to _new_path // Returns true if function succeeds virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path); @@ -70,30 +61,25 @@ class Win32Filesystem : public FilesystemInterface { // All of the following functions set pathname and return true if successful. // Returned paths always include a trailing backslash. // If create is true, the path will be recursively created. - // If append is non-NULL, it will be appended (and possibly created). + // If append is non-null, it will be appended (and possibly created). virtual std::string TempFilename(const Pathname &dir, const std::string &prefix); virtual bool GetFileSize(const Pathname& path, size_t* size); virtual bool GetFileTime(const Pathname& path, FileTimeType which, time_t* time); - + // A folder appropriate for storing temporary files (Contents are // automatically deleted when the program exists) virtual bool GetTemporaryFolder(Pathname &path, bool create, const std::string *append); - // Returns the path to the running application. - virtual bool GetAppPathname(Pathname* path); - - virtual bool GetAppDataFolder(Pathname* path, bool per_user); - // Get a temporary folder that is unique to the current user and application. virtual bool GetAppTempFolder(Pathname* path); - virtual bool GetDiskFreeSpace(const Pathname& path, int64_t* free_bytes); - - virtual Pathname GetCurrentDirectory(); + private: + // Returns the path to the running application. + bool GetAppPathname(Pathname* path); }; } // namespace rtc diff --git a/include/webrtc/base/win32regkey.h b/include/webrtc/base/win32regkey.h deleted file mode 100644 index d5c51b9..0000000 --- a/include/webrtc/base/win32regkey.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright 2003 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Registry configuration wrappers class -// -// Offers static functions for convenient -// fast access for individual values -// -// Also provides a wrapper class for efficient -// batch operations on values of a given registry key. -// - -#ifndef WEBRTC_BASE_WIN32REGKEY_H_ -#define WEBRTC_BASE_WIN32REGKEY_H_ - -#include -#include - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/win32.h" - -namespace rtc { - -// maximum sizes registry key and value names -const int kMaxKeyNameChars = 255 + 1; -const int kMaxValueNameChars = 16383 + 1; - -class RegKey { - public: - // constructor - RegKey(); - - // destructor - ~RegKey(); - - // create a reg key - HRESULT Create(HKEY parent_key, const wchar_t* key_name); - - HRESULT Create(HKEY parent_key, - const wchar_t* key_name, - wchar_t* reg_class, - DWORD options, - REGSAM sam_desired, - LPSECURITY_ATTRIBUTES lp_sec_attr, - LPDWORD lp_disposition); - - // open an existing reg key - HRESULT Open(HKEY parent_key, const wchar_t* key_name); - - HRESULT Open(HKEY parent_key, const wchar_t* key_name, REGSAM sam_desired); - - // close this reg key - HRESULT Close(); - - // check if the key has a specified value - bool HasValue(const wchar_t* value_name) const; - - // get the number of values for this key - uint32_t GetValueCount(); - - // Called to get the value name for the given value name index - // Use GetValueCount() to get the total value_name count for this key - // Returns failure if no key at the specified index - // If you modify the key while enumerating, the indexes will be out of order. - // Since the index order is not guaranteed, you need to reset your counting - // loop. - // 'type' refers to REG_DWORD, REG_QWORD, etc.. - // 'type' can be NULL if not interested in the value type - HRESULT GetValueNameAt(int index, std::wstring* value_name, DWORD* type); - - // check if the current key has the specified subkey - bool HasSubkey(const wchar_t* key_name) const; - - // get the number of subkeys for this key - uint32_t GetSubkeyCount(); - - // Called to get the key name for the given key index - // Use GetSubkeyCount() to get the total count for this key - // Returns failure if no key at the specified index - // If you modify the key while enumerating, the indexes will be out of order. - // Since the index order is not guaranteed, you need to reset your counting - // loop. - HRESULT GetSubkeyNameAt(int index, std::wstring* key_name); - - // SETTERS - - // set an int32_t value - use when reading multiple values from a key - HRESULT SetValue(const wchar_t* value_name, DWORD value) const; - - // set an int64_t value - HRESULT SetValue(const wchar_t* value_name, DWORD64 value) const; - - // set a string value - HRESULT SetValue(const wchar_t* value_name, const wchar_t* value) const; - - // set binary data - HRESULT SetValue(const wchar_t* value_name, - const uint8_t* value, - DWORD byte_count) const; - - // set raw data, including type - HRESULT SetValue(const wchar_t* value_name, - const uint8_t* value, - DWORD byte_count, - DWORD type) const; - - // GETTERS - - // get an int32_t value - HRESULT GetValue(const wchar_t* value_name, DWORD* value) const; - - // get an int64_t value - HRESULT GetValue(const wchar_t* value_name, DWORD64* value) const; - - // get a string value - the caller must free the return buffer - HRESULT GetValue(const wchar_t* value_name, wchar_t** value) const; - - // get a string value - HRESULT GetValue(const wchar_t* value_name, std::wstring* value) const; - - // get a std::vector value from REG_MULTI_SZ type - HRESULT GetValue(const wchar_t* value_name, - std::vector* value) const; - - // get binary data - the caller must free the return buffer - HRESULT GetValue(const wchar_t* value_name, - uint8_t** value, - DWORD* byte_count) const; - - // get raw data, including type - the caller must free the return buffer - HRESULT GetValue(const wchar_t* value_name, - uint8_t** value, - DWORD* byte_count, - DWORD* type) const; - - // STATIC VERSIONS - - // flush - static HRESULT FlushKey(const wchar_t* full_key_name); - - // check if a key exists - static bool HasKey(const wchar_t* full_key_name); - - // check if the key has a specified value - static bool HasValue(const wchar_t* full_key_name, const wchar_t* value_name); - - // SETTERS - - // STATIC int32_t set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD value); - - // STATIC int64_t set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD64 value); - - // STATIC float set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - float value); - - // STATIC double set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - double value); - - // STATIC string set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - const wchar_t* value); - - // STATIC binary data set - static HRESULT SetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - const uint8_t* value, - DWORD byte_count); - - // STATIC multi-string set - static HRESULT SetValueMultiSZ(const wchar_t* full_key_name, - const TCHAR* value_name, - const uint8_t* value, - DWORD byte_count); - - // GETTERS - - // STATIC int32_t get - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD* value); - - // STATIC int64_t get - // - // Note: if you are using time64 you should - // likely use GetLimitedTimeValue (util.h) instead of this method. - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD64* value); - - // STATIC float get - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - float* value); - - // STATIC double get - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - double* value); - - // STATIC string get - // Note: the caller must free the return buffer for wchar_t* version - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - wchar_t** value); - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - std::wstring* value); - - // STATIC REG_MULTI_SZ get - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - std::vector* value); - - // STATIC get binary data - the caller must free the return buffer - static HRESULT GetValue(const wchar_t* full_key_name, - const wchar_t* value_name, - uint8_t** value, - DWORD* byte_count); - - // Get type of a registry value - static HRESULT GetValueType(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD* value_type); - - // delete a subkey of the current key (with no subkeys) - HRESULT DeleteSubKey(const wchar_t* key_name); - - // recursively delete a sub key of the current key (and all its subkeys) - HRESULT RecurseDeleteSubKey(const wchar_t* key_name); - - // STATIC version of delete key - handles nested keys also - // delete a key and all its sub-keys recursively - // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, - // and failure otherwise. - static HRESULT DeleteKey(const wchar_t* full_key_name); - - // STATIC version of delete key - // delete a key recursively or non-recursively - // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, - // and failure otherwise. - static HRESULT DeleteKey(const wchar_t* full_key_name, bool recursive); - - // delete the specified value - HRESULT DeleteValue(const wchar_t* value_name); - - // STATIC version of delete value - // Returns S_FALSE if key didn't exist, S_OK if deletion was successful, - // and failure otherwise. - static HRESULT DeleteValue(const wchar_t* full_key_name, - const wchar_t* value_name); - - // Peek inside (use a RegKey as a smart wrapper around a registry handle) - HKEY key() { return h_key_; } - - // helper function to get the HKEY and the root key from a string - // modifies the argument in place and returns the key name - // e.g. HKLM\\Software\\Google\... returns HKLM, "Software\\Google\..." - // Necessary for the static versions that use the full name of the reg key - static HKEY GetRootKeyInfo(std::wstring* full_key_name); - - // Returns true if this key name is 'safe' for deletion (doesn't specify a key - // root) - static bool SafeKeyNameForDeletion(const wchar_t* key_name); - - // save the key and all of its subkeys and values to a file - static HRESULT Save(const wchar_t* full_key_name, const wchar_t* file_name); - - // restore the key and all of its subkeys and values which are saved into a - // file - static HRESULT Restore(const wchar_t* full_key_name, - const wchar_t* file_name); - - // Is the key empty: having no sub-keys and values - static bool IsKeyEmpty(const wchar_t* full_key_name); - - private: - - // helper function to get any value from the registry - // used when the size of the data is unknown - HRESULT GetValueHelper(const wchar_t* value_name, - DWORD* type, - uint8_t** value, - DWORD* byte_count) const; - - // helper function to get the parent key name and the subkey from a string - // modifies the argument in place and returns the key name - // Necessary for the static versions that use the full name of the reg key - static std::wstring GetParentKeyInfo(std::wstring* key_name); - - // common SET Helper for the static case - static HRESULT SetValueStaticHelper(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD type, - LPVOID value, - DWORD byte_count = 0); - - // common GET Helper for the static case - static HRESULT GetValueStaticHelper(const wchar_t* full_key_name, - const wchar_t* value_name, - DWORD type, - LPVOID value, - DWORD* byte_count = NULL); - - // convert REG_MULTI_SZ bytes to string array - static HRESULT MultiSZBytesToStringArray(const uint8_t* buffer, - DWORD byte_count, - std::vector* value); - - // the HKEY for the current key - HKEY h_key_; - - // for unittest - friend void RegKeyHelperFunctionsTest(); - - RTC_DISALLOW_COPY_AND_ASSIGN(RegKey); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_WIN32REGKEY_H_ diff --git a/include/webrtc/base/win32socketserver.h b/include/webrtc/base/win32socketserver.h index f47ed75..a9a53c3 100644 --- a/include/webrtc/base/win32socketserver.h +++ b/include/webrtc/base/win32socketserver.h @@ -44,8 +44,11 @@ class Win32Socket : public AsyncSocket { virtual int Connect(const SocketAddress& addr); virtual int Send(const void *buffer, size_t length); virtual int SendTo(const void *buffer, size_t length, const SocketAddress& addr); - virtual int Recv(void *buffer, size_t length); - virtual int RecvFrom(void *buffer, size_t length, SocketAddress *out_addr); + virtual int Recv(void* buffer, size_t length, int64_t* timestamp); + virtual int RecvFrom(void* buffer, + size_t length, + SocketAddress* out_addr, + int64_t* timestamp); virtual int Listen(int backlog); virtual Win32Socket *Accept(SocketAddress *out_addr); virtual int Close(); @@ -140,7 +143,7 @@ class Win32Thread : public Thread { } virtual ~Win32Thread() { Stop(); - set_socketserver(NULL); + set_socketserver(nullptr); } virtual void Run() { id_ = GetCurrentThreadId(); diff --git a/include/webrtc/base/win32windowpicker.h b/include/webrtc/base/win32windowpicker.h deleted file mode 100644 index 9c84bfd..0000000 --- a/include/webrtc/base/win32windowpicker.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ -#ifndef WEBRTC_BASE_WIN32WINDOWPICKER_H_ -#define WEBRTC_BASE_WIN32WINDOWPICKER_H_ - -#include "webrtc/base/win32.h" -#include "webrtc/base/windowpicker.h" - -namespace rtc { - -class Win32WindowPicker : public WindowPicker { - public: - Win32WindowPicker(); - virtual bool Init(); - virtual bool IsVisible(const WindowId& id); - virtual bool MoveToFront(const WindowId& id); - virtual bool GetWindowList(WindowDescriptionList* descriptions); - virtual bool GetDesktopList(DesktopDescriptionList* descriptions); - virtual bool GetDesktopDimensions(const DesktopId& id, int* width, - int* height); - - protected: - static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM l_param); - static BOOL CALLBACK MonitorEnumProc(HMONITOR h_monitor, - HDC hdc_monitor, - LPRECT lprc_monitor, - LPARAM l_param); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_WIN32WINDOWPICKER_H_ diff --git a/include/webrtc/base/window.h b/include/webrtc/base/window.h index b1f1724..a4a9aa4 100644 --- a/include/webrtc/base/window.h +++ b/include/webrtc/base/window.h @@ -11,7 +11,8 @@ #ifndef WEBRTC_BASE_WINDOW_H_ #define WEBRTC_BASE_WINDOW_H_ -#include "webrtc/base/basictypes.h" +#include + #include "webrtc/base/stringencode.h" // Define platform specific window types. @@ -68,54 +69,6 @@ class WindowId { WindowT id_; }; -class DesktopId { - public: - // Define DesktopT for each platform. -#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) - typedef Window DesktopT; -#elif defined(WEBRTC_WIN) - typedef HMONITOR DesktopT; -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) - typedef CGDirectDisplayID DesktopT; -#else - typedef unsigned int DesktopT; -#endif - - static DesktopId Cast(int id, int index) { -#if defined(WEBRTC_WIN) - return DesktopId(reinterpret_cast(id), index); -#else - return DesktopId(static_cast(id), index); -#endif - } - - DesktopId() : id_(0), index_(-1) {} - DesktopId(const DesktopT& id, int index) // NOLINT - : id_(id), index_(index) { - } - const DesktopT& id() const { return id_; } - int index() const { return index_; } - bool IsValid() const { return index_ != -1; } - bool Equals(const DesktopId& other) const { - return id_ == other.id() && index_ == other.index(); - } - - private: - // Id is the platform specific desktop identifier. - DesktopT id_; - // Index is the desktop index as enumerated by each platform. - // Desktop capturer typically takes the index instead of id. - int index_; -}; - -// Window event types. -enum WindowEvent { - WE_RESIZE = 0, - WE_CLOSE = 1, - WE_MINIMIZE = 2, - WE_RESTORE = 3, -}; - inline std::string ToString(const WindowId& window) { return ToString(window.id()); } diff --git a/include/webrtc/base/windowpicker.h b/include/webrtc/base/windowpicker.h deleted file mode 100644 index 3ae7b0e..0000000 --- a/include/webrtc/base/windowpicker.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_WINDOWPICKER_H_ -#define WEBRTC_BASE_WINDOWPICKER_H_ - -#include -#include - -#include "webrtc/base/window.h" - -namespace rtc { - -class WindowDescription { - public: - WindowDescription() : id_() {} - WindowDescription(const WindowId& id, const std::string& title) - : id_(id), title_(title) { - } - const WindowId& id() const { return id_; } - void set_id(const WindowId& id) { id_ = id; } - const std::string& title() const { return title_; } - void set_title(const std::string& title) { title_ = title; } - - private: - WindowId id_; - std::string title_; -}; - -class DesktopDescription { - public: - DesktopDescription() : id_() {} - DesktopDescription(const DesktopId& id, const std::string& title) - : id_(id), title_(title), primary_(false) { - } - const DesktopId& id() const { return id_; } - void set_id(const DesktopId& id) { id_ = id; } - const std::string& title() const { return title_; } - void set_title(const std::string& title) { title_ = title; } - // Indicates whether it is the primary desktop in the system. - bool primary() const { return primary_; } - void set_primary(bool primary) { primary_ = primary; } - - private: - DesktopId id_; - std::string title_; - bool primary_; -}; - -typedef std::vector WindowDescriptionList; -typedef std::vector DesktopDescriptionList; - -class WindowPicker { - public: - virtual ~WindowPicker() {} - virtual bool Init() = 0; - - // TODO: Move this two methods to window.h when we no longer need to load - // CoreGraphics dynamically. - virtual bool IsVisible(const WindowId& id) = 0; - virtual bool MoveToFront(const WindowId& id) = 0; - - // Gets a list of window description and appends to descriptions. - // Returns true if successful. - virtual bool GetWindowList(WindowDescriptionList* descriptions) = 0; - // Gets a list of desktop descriptions and appends to descriptions. - // Returns true if successful. - virtual bool GetDesktopList(DesktopDescriptionList* descriptions) = 0; - // Gets the width and height of a desktop. - // Returns true if successful. - virtual bool GetDesktopDimensions(const DesktopId& id, int* width, - int* height) = 0; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_WINDOWPICKER_H_ diff --git a/include/webrtc/base/windowpickerfactory.h b/include/webrtc/base/windowpickerfactory.h deleted file mode 100644 index dec3a33..0000000 --- a/include/webrtc/base/windowpickerfactory.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_WINDOWPICKERFACTORY_H_ -#define WEBRTC_BASE_WINDOWPICKERFACTORY_H_ - -#if defined(WEBRTC_WIN) -#include "webrtc/base/win32windowpicker.h" -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -#include "webrtc/base/macutils.h" -#include "webrtc/base/macwindowpicker.h" -#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(HAVE_X11) -#include "webrtc/base/x11windowpicker.h" -#endif - -#include "webrtc/base/windowpicker.h" - -namespace rtc { - -class WindowPickerFactory { - public: - virtual ~WindowPickerFactory() {} - - // Instance method for dependency injection. - virtual WindowPicker* Create() { - return CreateWindowPicker(); - } - - static WindowPicker* CreateWindowPicker() { -#if defined(WEBRTC_WIN) - return new Win32WindowPicker(); -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) - return new MacWindowPicker(); -#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) && defined(HAVE_X11) - return new X11WindowPicker(); -#else - return NULL; -#endif - } - - static bool IsSupported() { -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) - return GetOSVersionName() >= kMacOSLeopard; -#else - return true; -#endif - } -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_WINDOWPICKERFACTORY_H_ diff --git a/include/webrtc/base/winfirewall.h b/include/webrtc/base/winfirewall.h deleted file mode 100644 index a74631b..0000000 --- a/include/webrtc/base/winfirewall.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_WINFIREWALL_H_ -#define WEBRTC_BASE_WINFIREWALL_H_ - -#ifndef _HRESULT_DEFINED -#define _HRESULT_DEFINED -typedef long HRESULT; // Can't forward declare typedef, but don't need all win -#endif // !_HRESULT_DEFINED - -struct INetFwMgr; -struct INetFwPolicy; -struct INetFwProfile; - -namespace rtc { - -////////////////////////////////////////////////////////////////////// -// WinFirewall -////////////////////////////////////////////////////////////////////// - -class WinFirewall { - public: - WinFirewall(); - ~WinFirewall(); - - bool Initialize(HRESULT* result); - void Shutdown(); - - bool Enabled() const; - bool QueryAuthorized(const char* filename, bool* authorized) const; - bool QueryAuthorizedW(const wchar_t* filename, bool* authorized) const; - - bool AddApplication(const char* filename, const char* friendly_name, - bool authorized, HRESULT* result); - bool AddApplicationW(const wchar_t* filename, const wchar_t* friendly_name, - bool authorized, HRESULT* result); - - private: - INetFwMgr* mgr_; - INetFwPolicy* policy_; - INetFwProfile* profile_; -}; - -////////////////////////////////////////////////////////////////////// - -} // namespace rtc - -#endif // WEBRTC_BASE_WINFIREWALL_H_ diff --git a/include/webrtc/base/winping.h b/include/webrtc/base/winping.h index ddaefc5..de79b85 100644 --- a/include/webrtc/base/winping.h +++ b/include/webrtc/base/winping.h @@ -15,7 +15,7 @@ #include "webrtc/base/win32.h" #include "webrtc/base/basictypes.h" -#include "webrtc/base/IPAddress.h" +#include "webrtc/base/ipaddress.h" namespace rtc { diff --git a/include/webrtc/base/worker.h b/include/webrtc/base/worker.h deleted file mode 100644 index 17ae8cf..0000000 --- a/include/webrtc/base/worker.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_WORKER_H_ -#define WEBRTC_BASE_WORKER_H_ - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/messagehandler.h" - -namespace rtc { - -class Thread; - -// A worker is an object that performs some specific long-lived task in an -// event-driven manner. -// The only method that should be considered thread-safe is HaveWork(), which -// allows you to signal the availability of work from any thread. All other -// methods are thread-hostile. Specifically: -// StartWork()/StopWork() should not be called concurrently with themselves or -// each other, and it is an error to call them while the worker is running on -// a different thread. -// The destructor may not be called if the worker is currently running -// (regardless of the thread), but you can call StopWork() in a subclass's -// destructor. -class Worker : private MessageHandler { - public: - Worker(); - - // Destroys this Worker, but it must have already been stopped via StopWork(). - ~Worker() override; - - // Attaches the worker to the current thread and begins processing work if not - // already doing so. - bool StartWork(); - // Stops processing work if currently doing so and detaches from the current - // thread. - bool StopWork(); - - protected: - // Signal that work is available to be done. May only be called within the - // lifetime of a OnStart()/OnStop() pair. - void HaveWork(); - - // These must be implemented by a subclass. - // Called on the worker thread to start working. - virtual void OnStart() = 0; - // Called on the worker thread when work has been signalled via HaveWork(). - virtual void OnHaveWork() = 0; - // Called on the worker thread to stop working. Upon return, any pending - // OnHaveWork() calls are cancelled. - virtual void OnStop() = 0; - - private: - // Inherited from MessageHandler. - void OnMessage(Message* msg) override; - - // The thread that is currently doing the work. - Thread *worker_thread_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Worker); -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_WORKER_H_ diff --git a/include/webrtc/base/x11windowpicker.h b/include/webrtc/base/x11windowpicker.h deleted file mode 100644 index d741759..0000000 --- a/include/webrtc/base/x11windowpicker.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_BASE_LINUXWINDOWPICKER_H_ -#define WEBRTC_BASE_LINUXWINDOWPICKER_H_ - -#include - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/windowpicker.h" - -// Avoid include . -struct _XDisplay; -typedef unsigned long Window; - -namespace rtc { - -class XWindowEnumerator; - -class X11WindowPicker : public WindowPicker { - public: - X11WindowPicker(); - ~X11WindowPicker() override; - - static bool IsDesktopElement(_XDisplay* display, Window window); - - bool Init() override; - bool IsVisible(const WindowId& id) override; - bool MoveToFront(const WindowId& id) override; - bool GetWindowList(WindowDescriptionList* descriptions) override; - bool GetDesktopList(DesktopDescriptionList* descriptions) override; - bool GetDesktopDimensions(const DesktopId& id, - int* width, - int* height) override; - uint8_t* GetWindowIcon(const WindowId& id, int* width, int* height); - uint8_t* GetWindowThumbnail(const WindowId& id, int width, int height); - int GetNumDesktops(); - uint8_t* GetDesktopThumbnail(const DesktopId& id, int width, int height); - - private: - std::unique_ptr enumerator_; -}; - -} // namespace rtc - -#endif // WEBRTC_BASE_LINUXWINDOWPICKER_H_ diff --git a/include/webrtc/call.h b/include/webrtc/call.h index 80134fa..afea9dd 100644 --- a/include/webrtc/call.h +++ b/include/webrtc/call.h @@ -7,149 +7,7 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_CALL_H_ -#define WEBRTC_CALL_H_ -#include -#include - -#include "webrtc/common_types.h" -#include "webrtc/audio_receive_stream.h" -#include "webrtc/audio_send_stream.h" -#include "webrtc/audio_state.h" -#include "webrtc/base/networkroute.h" -#include "webrtc/base/socket.h" -#include "webrtc/video_receive_stream.h" -#include "webrtc/video_send_stream.h" - -namespace webrtc { - -class AudioProcessing; - -const char* Version(); - -enum class MediaType { - ANY, - AUDIO, - VIDEO, - DATA -}; - -class PacketReceiver { - public: - enum DeliveryStatus { - DELIVERY_OK, - DELIVERY_UNKNOWN_SSRC, - DELIVERY_PACKET_ERROR, - }; - - virtual DeliveryStatus DeliverPacket(MediaType media_type, - const uint8_t* packet, - size_t length, - const PacketTime& packet_time) = 0; - - protected: - virtual ~PacketReceiver() {} -}; - -// Callback interface for reporting when a system overuse is detected. -class LoadObserver { - public: - enum Load { kOveruse, kUnderuse }; - - // Triggered when overuse is detected or when we believe the system can take - // more load. - virtual void OnLoadUpdate(Load load) = 0; - - protected: - virtual ~LoadObserver() {} -}; - -// A Call instance can contain several send and/or receive streams. All streams -// are assumed to have the same remote endpoint and will share bitrate estimates -// etc. -class Call { - public: - struct Config { - static const int kDefaultStartBitrateBps; - - // Bitrate config used until valid bitrate estimates are calculated. Also - // used to cap total bitrate used. - struct BitrateConfig { - int min_bitrate_bps = 0; - int start_bitrate_bps = kDefaultStartBitrateBps; - int max_bitrate_bps = -1; - } bitrate_config; - - // AudioState which is possibly shared between multiple calls. - // TODO(solenberg): Change this to a shared_ptr once we can use C++11. - rtc::scoped_refptr audio_state; - - // Audio Processing Module to be used in this call. - // TODO(solenberg): Change this to a shared_ptr once we can use C++11. - AudioProcessing* audio_processing = nullptr; - }; - - struct Stats { - int send_bandwidth_bps = 0; - int recv_bandwidth_bps = 0; - int64_t pacer_delay_ms = 0; - int64_t rtt_ms = -1; - }; - - static Call* Create(const Call::Config& config); - - virtual AudioSendStream* CreateAudioSendStream( - const AudioSendStream::Config& config) = 0; - virtual void DestroyAudioSendStream(AudioSendStream* send_stream) = 0; - - virtual AudioReceiveStream* CreateAudioReceiveStream( - const AudioReceiveStream::Config& config) = 0; - virtual void DestroyAudioReceiveStream( - AudioReceiveStream* receive_stream) = 0; - - virtual VideoSendStream* CreateVideoSendStream( - const VideoSendStream::Config& config, - const VideoEncoderConfig& encoder_config) = 0; - virtual void DestroyVideoSendStream(VideoSendStream* send_stream) = 0; - - virtual VideoReceiveStream* CreateVideoReceiveStream( - const VideoReceiveStream::Config& config) = 0; - virtual void DestroyVideoReceiveStream( - VideoReceiveStream* receive_stream) = 0; - - // All received RTP and RTCP packets for the call should be inserted to this - // PacketReceiver. The PacketReceiver pointer is valid as long as the - // Call instance exists. - virtual PacketReceiver* Receiver() = 0; - - // Returns the call statistics, such as estimated send and receive bandwidth, - // pacing delay, etc. - virtual Stats GetStats() const = 0; - - // TODO(pbos): Like BitrateConfig above this is currently per-stream instead - // of maximum for entire Call. This should be fixed along with the above. - // Specifying a start bitrate (>0) will currently reset the current bitrate - // estimate. This is due to how the 'x-google-start-bitrate' flag is currently - // implemented. - virtual void SetBitrateConfig( - const Config::BitrateConfig& bitrate_config) = 0; - - // TODO(skvlad): When the unbundled case with multiple streams for the same - // media type going over different networks is supported, track the state - // for each stream separately. Right now it's global per media type. - virtual void SignalChannelNetworkState(MediaType media, - NetworkState state) = 0; - - virtual void OnNetworkRouteChanged( - const std::string& transport_name, - const rtc::NetworkRoute& network_route) = 0; - - virtual void OnSentPacket(const rtc::SentPacket& sent_packet) = 0; - - virtual ~Call() {} -}; - -} // namespace webrtc - -#endif // WEBRTC_CALL_H_ +// This file is deprecated. It has been moved to the location below. Please +// update your includes! See: http://bugs.webrtc.org/6716 +#include "webrtc/call/call.h" diff --git a/include/webrtc/common_types.h b/include/webrtc/common_types.h index 587b90d..faa875a 100644 --- a/include/webrtc/common_types.h +++ b/include/webrtc/common_types.h @@ -11,24 +11,27 @@ #ifndef WEBRTC_COMMON_TYPES_H_ #define WEBRTC_COMMON_TYPES_H_ -#include #include #include +#include #include #include +#include "webrtc/api/video/video_rotation.h" +#include "webrtc/base/checks.h" +#include "webrtc/base/optional.h" #include "webrtc/typedefs.h" #if defined(_MSC_VER) // Disable "new behavior: elements of array will be default initialized" // warning. Affects OverUseDetectorOptions. -#pragma warning(disable:4351) +#pragma warning(disable : 4351) #endif -#ifdef WEBRTC_EXPORT +#if defined(WEBRTC_EXPORT) #define WEBRTC_DLLEXPORT _declspec(dllexport) -#elif WEBRTC_DLL +#elif defined(WEBRTC_DLL) #define WEBRTC_DLLEXPORT _declspec(dllimport) #else #define WEBRTC_DLLEXPORT @@ -52,80 +55,72 @@ namespace webrtc { -class Config; - -class InStream -{ -public: - // Reads |length| bytes from file to |buf|. Returns the number of bytes read - // or -1 on error. - virtual int Read(void *buf, size_t len) = 0; - virtual int Rewind(); - virtual ~InStream() {} -protected: - InStream() {} -}; - -class OutStream -{ -public: - // Writes |length| bytes from |buf| to file. The actual writing may happen - // some time later. Call Flush() to force a write. - virtual bool Write(const void *buf, size_t len) = 0; - virtual int Rewind(); - virtual ~OutStream() {} -protected: - OutStream() {} -}; - -enum TraceModule -{ - kTraceUndefined = 0, - // not a module, triggered from the engine code - kTraceVoice = 0x0001, - // not a module, triggered from the engine code - kTraceVideo = 0x0002, - // not a module, triggered from the utility code - kTraceUtility = 0x0003, - kTraceRtpRtcp = 0x0004, - kTraceTransport = 0x0005, - kTraceSrtp = 0x0006, - kTraceAudioCoding = 0x0007, - kTraceAudioMixerServer = 0x0008, - kTraceAudioMixerClient = 0x0009, - kTraceFile = 0x000a, - kTraceAudioProcessing = 0x000b, - kTraceVideoCoding = 0x0010, - kTraceVideoMixer = 0x0011, - kTraceAudioDevice = 0x0012, - kTraceVideoRenderer = 0x0014, - kTraceVideoCapture = 0x0015, - kTraceRemoteBitrateEstimator = 0x0017, -}; - -enum TraceLevel -{ - kTraceNone = 0x0000, // no trace - kTraceStateInfo = 0x0001, - kTraceWarning = 0x0002, - kTraceError = 0x0004, - kTraceCritical = 0x0008, - kTraceApiCall = 0x0010, - kTraceDefault = 0x00ff, - - kTraceModuleCall = 0x0020, - kTraceMemory = 0x0100, // memory info - kTraceTimer = 0x0200, // timing info - kTraceStream = 0x0400, // "continuous" stream of data - - // used for debug purposes - kTraceDebug = 0x0800, // debug - kTraceInfo = 0x1000, // debug info - - // Non-verbose level used by LS_INFO of logging.h. Do not use directly. - kTraceTerseInfo = 0x2000, - - kTraceAll = 0xffff +class RewindableStream { + public: + virtual ~RewindableStream() {} + virtual int Rewind() = 0; +}; + +class InStream : public RewindableStream { + public: + // Reads |len| bytes from file to |buf|. Returns the number of bytes read + // or -1 on error. + virtual int Read(void* buf, size_t len) = 0; +}; + +class OutStream : public RewindableStream { + public: + // Writes |len| bytes from |buf| to file. The actual writing may happen + // some time later. Call Flush() to force a write. + virtual bool Write(const void* buf, size_t len) = 0; +}; + +enum TraceModule { + kTraceUndefined = 0, + // not a module, triggered from the engine code + kTraceVoice = 0x0001, + // not a module, triggered from the engine code + kTraceVideo = 0x0002, + // not a module, triggered from the utility code + kTraceUtility = 0x0003, + kTraceRtpRtcp = 0x0004, + kTraceTransport = 0x0005, + kTraceSrtp = 0x0006, + kTraceAudioCoding = 0x0007, + kTraceAudioMixerServer = 0x0008, + kTraceAudioMixerClient = 0x0009, + kTraceFile = 0x000a, + kTraceAudioProcessing = 0x000b, + kTraceVideoCoding = 0x0010, + kTraceVideoMixer = 0x0011, + kTraceAudioDevice = 0x0012, + kTraceVideoRenderer = 0x0014, + kTraceVideoCapture = 0x0015, + kTraceRemoteBitrateEstimator = 0x0017, +}; + +enum TraceLevel { + kTraceNone = 0x0000, // no trace + kTraceStateInfo = 0x0001, + kTraceWarning = 0x0002, + kTraceError = 0x0004, + kTraceCritical = 0x0008, + kTraceApiCall = 0x0010, + kTraceDefault = 0x00ff, + + kTraceModuleCall = 0x0020, + kTraceMemory = 0x0100, // memory info + kTraceTimer = 0x0200, // timing info + kTraceStream = 0x0400, // "continuous" stream of data + + // used for debug purposes + kTraceDebug = 0x0800, // debug + kTraceInfo = 0x1000, // debug info + + // Non-verbose level used by LS_INFO of logging.h. Do not use directly. + kTraceTerseInfo = 0x2000, + + kTraceAll = 0xffff }; // External Trace API @@ -138,23 +133,13 @@ class TraceCallback { TraceCallback() {} }; -enum FileFormats -{ - kFileFormatWavFile = 1, - kFileFormatCompressedFile = 2, - kFileFormatPreencodedFile = 4, - kFileFormatPcm16kHzFile = 7, - kFileFormatPcm8kHzFile = 8, - kFileFormatPcm32kHzFile = 9 -}; - -enum ProcessingTypes -{ - kPlaybackPerChannel = 0, - kPlaybackAllChannelsMixed, - kRecordingPerChannel, - kRecordingAllChannelsMixed, - kRecordingPreprocessing +enum FileFormats { + kFileFormatWavFile = 1, + kFileFormatCompressedFile = 2, + kFileFormatPreencodedFile = 4, + kFileFormatPcm16kHzFile = 7, + kFileFormatPcm8kHzFile = 8, + kFileFormatPcm32kHzFile = 9 }; enum FrameType { @@ -168,10 +153,10 @@ enum FrameType { // Statistics for an RTCP channel struct RtcpStatistics { RtcpStatistics() - : fraction_lost(0), - cumulative_lost(0), - extended_max_sequence_number(0), - jitter(0) {} + : fraction_lost(0), + cumulative_lost(0), + extended_max_sequence_number(0), + jitter(0) {} uint8_t fraction_lost; uint32_t cumulative_lost; @@ -191,12 +176,12 @@ class RtcpStatisticsCallback { // Statistics for RTCP packet types. struct RtcpPacketTypeCounter { RtcpPacketTypeCounter() - : first_packet_time_ms(-1), - nack_packets(0), - fir_packets(0), - pli_packets(0), - nack_requests(0), - unique_nack_requests(0) {} + : first_packet_time_ms(-1), + nack_packets(0), + fir_packets(0), + pli_packets(0), + nack_requests(0), + unique_nack_requests(0) {} void Add(const RtcpPacketTypeCounter& other) { nack_packets += other.nack_packets; @@ -205,8 +190,8 @@ struct RtcpPacketTypeCounter { nack_requests += other.nack_requests; unique_nack_requests += other.unique_nack_requests; if (other.first_packet_time_ms != -1 && - (other.first_packet_time_ms < first_packet_time_ms || - first_packet_time_ms == -1)) { + (other.first_packet_time_ms < first_packet_time_ms || + first_packet_time_ms == -1)) { // Use oldest time. first_packet_time_ms = other.first_packet_time_ms; } @@ -234,15 +219,15 @@ struct RtcpPacketTypeCounter { if (nack_requests == 0) { return 0; } - return static_cast( - (unique_nack_requests * 100.0f / nack_requests) + 0.5f); + return static_cast((unique_nack_requests * 100.0f / nack_requests) + + 0.5f); } - int64_t first_packet_time_ms; // Time when first packet is sent/received. - uint32_t nack_packets; // Number of RTCP NACK packets. - uint32_t fir_packets; // Number of RTCP FIR packets. - uint32_t pli_packets; // Number of RTCP PLI packets. - uint32_t nack_requests; // Number of NACKed RTP packets. + int64_t first_packet_time_ms; // Time when first packet is sent/received. + uint32_t nack_packets; // Number of RTCP NACK packets. + uint32_t fir_packets; // Number of RTCP FIR packets. + uint32_t pli_packets; // Number of RTCP PLI packets. + uint32_t nack_requests; // Number of NACKed RTP packets. uint32_t unique_nack_requests; // Number of unique NACKed RTP packets. }; @@ -256,11 +241,10 @@ class RtcpPacketTypeCounterObserver { // Rate statistics for a stream. struct BitrateStatistics { - BitrateStatistics() : bitrate_bps(0), packet_rate(0), timestamp_ms(0) {} + BitrateStatistics() : bitrate_bps(0), packet_rate(0) {} - uint32_t bitrate_bps; // Bitrate in bits per second. - uint32_t packet_rate; // Packet rate in packets per second. - uint64_t timestamp_ms; // Ntp timestamp in ms at time of rate estimation. + uint32_t bitrate_bps; // Bitrate in bits per second. + uint32_t packet_rate; // Packet rate in packets per second. }; // Callback, used to notify an observer whenever new rates have been estimated. @@ -268,8 +252,8 @@ class BitrateStatisticsObserver { public: virtual ~BitrateStatisticsObserver() {} - virtual void Notify(const BitrateStatistics& total_stats, - const BitrateStatistics& retransmit_stats, + virtual void Notify(uint32_t total_bitrate_bps, + uint32_t retransmit_bitrate_bps, uint32_t ssrc) = 0; }; @@ -308,6 +292,14 @@ class SendPacketObserver { uint32_t ssrc) = 0; }; +// Callback, used to notify an observer when the overhead per packet +// has changed. +class OverheadObserver { + public: + virtual ~OverheadObserver() = default; + virtual void OnOverheadChanged(size_t overhead_bytes_per_packet) = 0; +}; + // ================================================================== // Voice specific types // ================================================================== @@ -324,72 +316,77 @@ struct CodecInst { bool operator==(const CodecInst& other) const { return pltype == other.pltype && (STR_CASE_CMP(plname, other.plname) == 0) && - plfreq == other.plfreq && - pacsize == other.pacsize && - channels == other.channels && - rate == other.rate; + plfreq == other.plfreq && pacsize == other.pacsize && + channels == other.channels && rate == other.rate; } - bool operator!=(const CodecInst& other) const { - return !(*this == other); + bool operator!=(const CodecInst& other) const { return !(*this == other); } + + friend std::ostream& operator<<(std::ostream& os, const CodecInst& ci) { + os << "{pltype: " << ci.pltype; + os << ", plname: " << ci.plname; + os << ", plfreq: " << ci.plfreq; + os << ", pacsize: " << ci.pacsize; + os << ", channels: " << ci.channels; + os << ", rate: " << ci.rate << "}"; + return os; } }; // RTP -enum {kRtpCsrcSize = 15}; // RFC 3550 page 13 - -enum PayloadFrequencies -{ - kFreq8000Hz = 8000, - kFreq16000Hz = 16000, - kFreq32000Hz = 32000 -}; - -enum VadModes // degree of bandwidth reduction -{ - kVadConventional = 0, // lowest reduction - kVadAggressiveLow, - kVadAggressiveMid, - kVadAggressiveHigh // highest reduction -}; - -struct NetworkStatistics // NETEQ statistics -{ - // current jitter buffer size in ms - uint16_t currentBufferSize; - // preferred (optimal) buffer size in ms - uint16_t preferredBufferSize; - // adding extra delay due to "peaky jitter" - bool jitterPeaksFound; - // Loss rate (network + late); fraction between 0 and 1, scaled to Q14. - uint16_t currentPacketLossRate; - // Late loss rate; fraction between 0 and 1, scaled to Q14. - uint16_t currentDiscardRate; - // fraction (of original stream) of synthesized audio inserted through - // expansion (in Q14) - uint16_t currentExpandRate; - // fraction (of original stream) of synthesized speech inserted through - // expansion (in Q14) - uint16_t currentSpeechExpandRate; - // fraction of synthesized speech inserted through pre-emptive expansion - // (in Q14) - uint16_t currentPreemptiveRate; - // fraction of data removed through acceleration (in Q14) - uint16_t currentAccelerateRate; - // fraction of data coming from secondary decoding (in Q14) - uint16_t currentSecondaryDecodedRate; - // clock-drift in parts-per-million (negative or positive) - int32_t clockDriftPPM; - // average packet waiting time in the jitter buffer (ms) - int meanWaitingTimeMs; - // median packet waiting time in the jitter buffer (ms) - int medianWaitingTimeMs; - // min packet waiting time in the jitter buffer (ms) - int minWaitingTimeMs; - // max packet waiting time in the jitter buffer (ms) - int maxWaitingTimeMs; - // added samples in off mode due to packet loss - size_t addedSamples; +enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13 + +enum PayloadFrequencies { + kFreq8000Hz = 8000, + kFreq16000Hz = 16000, + kFreq32000Hz = 32000 +}; + +// Degree of bandwidth reduction. +enum VadModes { + kVadConventional = 0, // lowest reduction + kVadAggressiveLow, + kVadAggressiveMid, + kVadAggressiveHigh // highest reduction +}; + +// NETEQ statistics. +struct NetworkStatistics { + // current jitter buffer size in ms + uint16_t currentBufferSize; + // preferred (optimal) buffer size in ms + uint16_t preferredBufferSize; + // adding extra delay due to "peaky jitter" + bool jitterPeaksFound; + // Loss rate (network + late); fraction between 0 and 1, scaled to Q14. + uint16_t currentPacketLossRate; + // Late loss rate; fraction between 0 and 1, scaled to Q14. + uint16_t currentDiscardRate; + // fraction (of original stream) of synthesized audio inserted through + // expansion (in Q14) + uint16_t currentExpandRate; + // fraction (of original stream) of synthesized speech inserted through + // expansion (in Q14) + uint16_t currentSpeechExpandRate; + // fraction of synthesized speech inserted through pre-emptive expansion + // (in Q14) + uint16_t currentPreemptiveRate; + // fraction of data removed through acceleration (in Q14) + uint16_t currentAccelerateRate; + // fraction of data coming from secondary decoding (in Q14) + uint16_t currentSecondaryDecodedRate; + // clock-drift in parts-per-million (negative or positive) + int32_t clockDriftPPM; + // average packet waiting time in the jitter buffer (ms) + int meanWaitingTimeMs; + // median packet waiting time in the jitter buffer (ms) + int medianWaitingTimeMs; + // min packet waiting time in the jitter buffer (ms) + int minWaitingTimeMs; + // max packet waiting time in the jitter buffer (ms) + int maxWaitingTimeMs; + // added samples in off mode due to packet loss + size_t addedSamples; }; // Statistics for calls to AudioCodingModule::PlayoutData10Ms(). @@ -400,144 +397,79 @@ struct AudioDecodingCallStats { decoded_normal(0), decoded_plc(0), decoded_cng(0), - decoded_plc_cng(0) {} + decoded_plc_cng(0), + decoded_muted_output(0) {} int calls_to_silence_generator; // Number of calls where silence generated, // and NetEq was disengaged from decoding. - int calls_to_neteq; // Number of calls to NetEq. + int calls_to_neteq; // Number of calls to NetEq. int decoded_normal; // Number of calls where audio RTP packet decoded. - int decoded_plc; // Number of calls resulted in PLC. + int decoded_plc; // Number of calls resulted in PLC. int decoded_cng; // Number of calls where comfort noise generated due to DTX. int decoded_plc_cng; // Number of calls resulted where PLC faded to CNG. -}; - -typedef struct -{ - int min; // minumum - int max; // maximum - int average; // average -} StatVal; - -typedef struct // All levels are reported in dBm0 -{ - StatVal speech_rx; // long-term speech levels on receiving side - StatVal speech_tx; // long-term speech levels on transmitting side - StatVal noise_rx; // long-term noise/silence levels on receiving side - StatVal noise_tx; // long-term noise/silence levels on transmitting side -} LevelStatistics; - -typedef struct // All levels are reported in dB -{ - StatVal erl; // Echo Return Loss - StatVal erle; // Echo Return Loss Enhancement - StatVal rerl; // RERL = ERL + ERLE - // Echo suppression inside EC at the point just before its NLP - StatVal a_nlp; -} EchoStatistics; - -enum NsModes // type of Noise Suppression -{ - kNsUnchanged = 0, // previously set mode - kNsDefault, // platform default - kNsConference, // conferencing default - kNsLowSuppression, // lowest suppression - kNsModerateSuppression, - kNsHighSuppression, - kNsVeryHighSuppression, // highest suppression -}; - -enum AgcModes // type of Automatic Gain Control -{ - kAgcUnchanged = 0, // previously set mode - kAgcDefault, // platform default - // adaptive mode for use when analog volume control exists (e.g. for - // PC softphone) - kAgcAdaptiveAnalog, - // scaling takes place in the digital domain (e.g. for conference servers - // and embedded devices) - kAgcAdaptiveDigital, - // can be used on embedded devices where the capture signal level - // is predictable - kAgcFixedDigital -}; - -// EC modes -enum EcModes // type of Echo Control -{ - kEcUnchanged = 0, // previously set mode - kEcDefault, // platform default - kEcConference, // conferencing default (aggressive AEC) - kEcAec, // Acoustic Echo Cancellation - kEcAecm, // AEC mobile -}; - -// AECM modes -enum AecmModes // mode of AECM -{ - kAecmQuietEarpieceOrHeadset = 0, - // Quiet earpiece or headset use - kAecmEarpiece, // most earpiece use - kAecmLoudEarpiece, // Loud earpiece or quiet speakerphone use - kAecmSpeakerphone, // most speakerphone use (default) - kAecmLoudSpeakerphone // Loud speakerphone -}; - -// AGC configuration -typedef struct -{ - unsigned short targetLeveldBOv; - unsigned short digitalCompressionGaindB; - bool limiterEnable; -} AgcConfig; // AGC configuration parameters - -enum StereoChannel -{ - kStereoLeft = 0, - kStereoRight, - kStereoBoth -}; + int decoded_muted_output; // Number of calls returning a muted state output. +}; + +// Type of Noise Suppression. +enum NsModes { + kNsUnchanged = 0, // previously set mode + kNsDefault, // platform default + kNsConference, // conferencing default + kNsLowSuppression, // lowest suppression + kNsModerateSuppression, + kNsHighSuppression, + kNsVeryHighSuppression, // highest suppression +}; + +// Type of Automatic Gain Control. +enum AgcModes { + kAgcUnchanged = 0, // previously set mode + kAgcDefault, // platform default + // adaptive mode for use when analog volume control exists (e.g. for + // PC softphone) + kAgcAdaptiveAnalog, + // scaling takes place in the digital domain (e.g. for conference servers + // and embedded devices) + kAgcAdaptiveDigital, + // can be used on embedded devices where the capture signal level + // is predictable + kAgcFixedDigital +}; + +// Type of Echo Control. +enum EcModes { + kEcUnchanged = 0, // previously set mode + kEcDefault, // platform default + kEcConference, // conferencing default (aggressive AEC) + kEcAec, // Acoustic Echo Cancellation + kEcAecm, // AEC mobile +}; + +// Mode of AECM. +enum AecmModes { + kAecmQuietEarpieceOrHeadset = 0, + // Quiet earpiece or headset use + kAecmEarpiece, // most earpiece use + kAecmLoudEarpiece, // Loud earpiece or quiet speakerphone use + kAecmSpeakerphone, // most speakerphone use (default) + kAecmLoudSpeakerphone // Loud speakerphone +}; + +// AGC configuration parameters +struct AgcConfig { + unsigned short targetLeveldBOv; + unsigned short digitalCompressionGaindB; + bool limiterEnable; +}; + +enum StereoChannel { kStereoLeft = 0, kStereoRight, kStereoBoth }; // Audio device layers -enum AudioLayers -{ - kAudioPlatformDefault = 0, - kAudioWindowsWave = 1, - kAudioWindowsCore = 2, - kAudioLinuxAlsa = 3, - kAudioLinuxPulse = 4 -}; - -// TODO(henrika): to be removed. -enum NetEqModes // NetEQ playout configurations -{ - // Optimized trade-off between low delay and jitter robustness for two-way - // communication. - kNetEqDefault = 0, - // Improved jitter robustness at the cost of increased delay. Can be - // used in one-way communication. - kNetEqStreaming = 1, - // Optimzed for decodability of fax signals rather than for perceived audio - // quality. - kNetEqFax = 2, - // Minimal buffer management. Inserts zeros for lost packets and during - // buffer increases. - kNetEqOff = 3, -}; - -// TODO(henrika): to be removed. -enum OnHoldModes // On Hold direction -{ - kHoldSendAndPlay = 0, // Put both sending and playing in on-hold state. - kHoldSendOnly, // Put only sending in on-hold state. - kHoldPlayOnly // Put only playing in on-hold state. -}; - -// TODO(henrika): to be removed. -enum AmrMode -{ - kRfc3267BwEfficient = 0, - kRfc3267OctetAligned = 1, - kRfc3267FileStorage = 2, +enum AudioLayers { + kAudioPlatformDefault = 0, + kAudioWindowsCore = 2, + kAudioLinuxAlsa = 3, + kAudioLinuxPulse = 4 }; // ================================================================== @@ -545,44 +477,36 @@ enum AmrMode // ================================================================== // Raw video types -enum RawVideoType -{ - kVideoI420 = 0, - kVideoYV12 = 1, - kVideoYUY2 = 2, - kVideoUYVY = 3, - kVideoIYUV = 4, - kVideoARGB = 5, - kVideoRGB24 = 6, - kVideoRGB565 = 7, - kVideoARGB4444 = 8, - kVideoARGB1555 = 9, - kVideoMJPEG = 10, - kVideoNV12 = 11, - kVideoNV21 = 12, - kVideoBGRA = 13, - kVideoUnknown = 99 +enum RawVideoType { + kVideoI420 = 0, + kVideoYV12 = 1, + kVideoYUY2 = 2, + kVideoUYVY = 3, + kVideoIYUV = 4, + kVideoARGB = 5, + kVideoRGB24 = 6, + kVideoRGB565 = 7, + kVideoARGB4444 = 8, + kVideoARGB1555 = 9, + kVideoMJPEG = 10, + kVideoNV12 = 11, + kVideoNV21 = 12, + kVideoBGRA = 13, + kVideoUnknown = 99 }; // Video codec -enum { kConfigParameterSize = 128}; -enum { kPayloadNameSize = 32}; -enum { kMaxSimulcastStreams = 4}; +enum { kConfigParameterSize = 128 }; +enum { kPayloadNameSize = 32 }; +enum { kMaxSimulcastStreams = 4 }; enum { kMaxSpatialLayers = 5 }; -enum { kMaxTemporalStreams = 4}; +enum { kMaxTemporalStreams = 4 }; -enum VideoCodecComplexity -{ - kComplexityNormal = 0, - kComplexityHigh = 1, - kComplexityHigher = 2, - kComplexityMax = 3 -}; - -enum VideoCodecProfile -{ - kProfileBase = 0x00, - kProfileMain = 0x01 +enum VideoCodecComplexity { + kComplexityNormal = 0, + kComplexityHigh = 1, + kComplexityHigher = 2, + kComplexityMax = 3 }; enum VP8ResilienceMode { @@ -599,43 +523,56 @@ enum VP8ResilienceMode { class TemporalLayersFactory; // VP8 specific struct VideoCodecVP8 { - bool pictureLossIndicationOn; - bool feedbackModeOn; + bool pictureLossIndicationOn; + bool feedbackModeOn; VideoCodecComplexity complexity; - VP8ResilienceMode resilience; - unsigned char numberOfTemporalLayers; - bool denoisingOn; - bool errorConcealmentOn; - bool automaticResizeOn; - bool frameDroppingOn; - int keyFrameInterval; - const TemporalLayersFactory* tl_factory; + VP8ResilienceMode resilience; + unsigned char numberOfTemporalLayers; + bool denoisingOn; + bool errorConcealmentOn; + bool automaticResizeOn; + bool frameDroppingOn; + int keyFrameInterval; + TemporalLayersFactory* tl_factory; }; // VP9 specific. struct VideoCodecVP9 { VideoCodecComplexity complexity; - int resilience; - unsigned char numberOfTemporalLayers; - bool denoisingOn; - bool frameDroppingOn; - int keyFrameInterval; - bool adaptiveQpMode; - bool automaticResizeOn; - unsigned char numberOfSpatialLayers; - bool flexibleMode; + int resilience; + unsigned char numberOfTemporalLayers; + bool denoisingOn; + bool frameDroppingOn; + int keyFrameInterval; + bool adaptiveQpMode; + bool automaticResizeOn; + unsigned char numberOfSpatialLayers; + bool flexibleMode; +}; + +// TODO(magjed): Move this and other H264 related classes out to their own file. +namespace H264 { + +enum Profile { + kProfileConstrainedBaseline, + kProfileBaseline, + kProfileMain, + kProfileConstrainedHigh, + kProfileHigh, }; +} // namespace H264 + // H264 specific. struct VideoCodecH264 { - VideoCodecProfile profile; - bool frameDroppingOn; - int keyFrameInterval; + bool frameDroppingOn; + int keyFrameInterval; // These are NULL/0 if not externally negotiated. const uint8_t* spsData; - size_t spsLen; + size_t spsLen; const uint8_t* ppsData; - size_t ppsLen; + size_t ppsLen; + H264::Profile profile; }; // Video codec types @@ -646,27 +583,31 @@ enum VideoCodecType { kVideoCodecI420, kVideoCodecRED, kVideoCodecULPFEC, + kVideoCodecFlexfec, kVideoCodecGeneric, kVideoCodecUnknown }; +// Translates from name of codec to codec type and vice versa. +rtc::Optional CodecTypeToPayloadName(VideoCodecType type); +rtc::Optional PayloadNameToCodecType(const std::string& name); + union VideoCodecUnion { - VideoCodecVP8 VP8; - VideoCodecVP9 VP9; - VideoCodecH264 H264; + VideoCodecVP8 VP8; + VideoCodecVP9 VP9; + VideoCodecH264 H264; }; - // Simulcast is when the same stream is encoded multiple times with different // settings such as resolution. struct SimulcastStream { - unsigned short width; - unsigned short height; - unsigned char numberOfTemporalLayers; - unsigned int maxBitrate; // kilobits/sec. - unsigned int targetBitrate; // kilobits/sec. - unsigned int minBitrate; // kilobits/sec. - unsigned int qpMax; // minimum quality + unsigned short width; + unsigned short height; + unsigned char numberOfTemporalLayers; + unsigned int maxBitrate; // kilobits/sec. + unsigned int targetBitrate; // kilobits/sec. + unsigned int minBitrate; // kilobits/sec. + unsigned int qpMax; // minimum quality }; struct SpatialLayer { @@ -676,46 +617,94 @@ struct SpatialLayer { // TODO(ivica): Add max_quantizer and min_quantizer? }; -enum VideoCodecMode { - kRealtimeVideo, - kScreensharing -}; +enum VideoCodecMode { kRealtimeVideo, kScreensharing }; // Common video codec properties -struct VideoCodec { - VideoCodecType codecType; - char plName[kPayloadNameSize]; - unsigned char plType; +class VideoCodec { + public: + VideoCodec(); - unsigned short width; - unsigned short height; + // Public variables. TODO(hta): Make them private with accessors. + VideoCodecType codecType; + char plName[kPayloadNameSize]; + unsigned char plType; - unsigned int startBitrate; // kilobits/sec. - unsigned int maxBitrate; // kilobits/sec. - unsigned int minBitrate; // kilobits/sec. - unsigned int targetBitrate; // kilobits/sec. + unsigned short width; + unsigned short height; - unsigned char maxFramerate; + unsigned int startBitrate; // kilobits/sec. + unsigned int maxBitrate; // kilobits/sec. + unsigned int minBitrate; // kilobits/sec. + unsigned int targetBitrate; // kilobits/sec. - VideoCodecUnion codecSpecific; + unsigned char maxFramerate; - unsigned int qpMax; - unsigned char numberOfSimulcastStreams; - SimulcastStream simulcastStream[kMaxSimulcastStreams]; + unsigned int qpMax; + unsigned char numberOfSimulcastStreams; + SimulcastStream simulcastStream[kMaxSimulcastStreams]; SpatialLayer spatialLayers[kMaxSpatialLayers]; - VideoCodecMode mode; + VideoCodecMode mode; + bool expect_encode_from_texture; bool operator==(const VideoCodec& other) const = delete; bool operator!=(const VideoCodec& other) const = delete; + + // Accessors for codec specific information. + // There is a const version of each that returns a reference, + // and a non-const version that returns a pointer, in order + // to allow modification of the parameters. + VideoCodecVP8* VP8(); + const VideoCodecVP8& VP8() const; + VideoCodecVP9* VP9(); + const VideoCodecVP9& VP9() const; + VideoCodecH264* H264(); + const VideoCodecH264& H264() const; + + private: + // TODO(hta): Consider replacing the union with a pointer type. + // This will allow removing the VideoCodec* types from this file. + VideoCodecUnion codec_specific_; +}; + +class BitrateAllocation { + public: + static const uint32_t kMaxBitrateBps; + BitrateAllocation(); + + bool SetBitrate(size_t spatial_index, + size_t temporal_index, + uint32_t bitrate_bps); + + uint32_t GetBitrate(size_t spatial_index, size_t temporal_index) const; + + // Get the sum of all the temporal layer for a specific spatial layer. + uint32_t GetSpatialLayerSum(size_t spatial_index) const; + + uint32_t get_sum_bps() const { return sum_; } // Sum of all bitrates. + uint32_t get_sum_kbps() const { return (sum_ + 500) / 1000; } + + inline bool operator==(const BitrateAllocation& other) const { + return memcmp(bitrates_, other.bitrates_, sizeof(bitrates_)) == 0; + } + inline bool operator!=(const BitrateAllocation& other) const { + return !(*this == other); + } + + private: + uint32_t sum_; + uint32_t bitrates_[kMaxSpatialLayers][kMaxTemporalStreams]; }; // Bandwidth over-use detector options. These are used to drive // experimentation with bandwidth estimation parameters. // See modules/remote_bitrate_estimator/overuse_detector.h +// TODO(terelius): This is only used in overuse_estimator.cc, and only in the +// default constructed state. Can we move the relevant variables into that +// class and delete this? See also disabled warning at line 27 struct OverUseDetectorOptions { OverUseDetectorOptions() - : initial_slope(8.0/512.0), + : initial_slope(8.0 / 512.0), initial_offset(0), initial_e(), initial_process_noise(), @@ -740,8 +729,7 @@ struct OverUseDetectorOptions { struct PacketTime { PacketTime() : timestamp(-1), not_before(-1) {} PacketTime(int64_t timestamp, int64_t not_before) - : timestamp(timestamp), not_before(not_before) { - } + : timestamp(timestamp), not_before(not_before) {} int64_t timestamp; // Receive time after socket delivers the data. int64_t not_before; // Earliest possible time the data could have arrived, @@ -751,6 +739,24 @@ struct PacketTime { // If unknown, this value will be set to zero. }; +// Minimum and maximum playout delay values from capture to render. +// These are best effort values. +// +// A value < 0 indicates no change from previous valid value. +// +// min = max = 0 indicates that the receiver should try and render +// frame as soon as possible. +// +// min = x, max = y indicates that the receiver is free to adapt +// in the range (x, y) based on network jitter. +// +// Note: Given that this gets embedded in a union, it is up-to the owner to +// initialize these values. +struct PlayoutDelay { + int min_ms; + int max_ms; +}; + struct RTPHeaderExtension { RTPHeaderExtension(); @@ -771,7 +777,9 @@ struct RTPHeaderExtension { // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ // ts_126114v120700p.pdf bool hasVideoRotation; - uint8_t videoRotation; + VideoRotation videoRotation; + + PlayoutDelay playout_delay = {-1, -1}; }; struct RTPHeader { @@ -792,10 +800,7 @@ struct RTPHeader { struct RtpPacketCounter { RtpPacketCounter() - : header_bytes(0), - payload_bytes(0), - padding_bytes(0), - packets(0) {} + : header_bytes(0), payload_bytes(0), padding_bytes(0), packets(0) {} void Add(const RtpPacketCounter& other) { header_bytes += other.header_bytes; @@ -805,13 +810,13 @@ struct RtpPacketCounter { } void Subtract(const RtpPacketCounter& other) { - assert(header_bytes >= other.header_bytes); + RTC_DCHECK_GE(header_bytes, other.header_bytes); header_bytes -= other.header_bytes; - assert(payload_bytes >= other.payload_bytes); + RTC_DCHECK_GE(payload_bytes, other.payload_bytes); payload_bytes -= other.payload_bytes; - assert(padding_bytes >= other.padding_bytes); + RTC_DCHECK_GE(padding_bytes, other.padding_bytes); padding_bytes -= other.padding_bytes; - assert(packets >= other.packets); + RTC_DCHECK_GE(packets, other.packets); packets -= other.packets; } @@ -842,8 +847,8 @@ struct StreamDataCounters { retransmitted.Add(other.retransmitted); fec.Add(other.fec); if (other.first_packet_time_ms != -1 && - (other.first_packet_time_ms < first_packet_time_ms || - first_packet_time_ms == -1)) { + (other.first_packet_time_ms < first_packet_time_ms || + first_packet_time_ms == -1)) { // Use oldest time. first_packet_time_ms = other.first_packet_time_ms; } @@ -873,10 +878,10 @@ struct StreamDataCounters { fec.payload_bytes; } - int64_t first_packet_time_ms; // Time when first packet is sent/received. - RtpPacketCounter transmitted; // Number of transmitted packets/bytes. + int64_t first_packet_time_ms; // Time when first packet is sent/received. + RtpPacketCounter transmitted; // Number of transmitted packets/bytes. RtpPacketCounter retransmitted; // Number of retransmitted packets/bytes. - RtpPacketCounter fec; // Number of redundancy packets/bytes. + RtpPacketCounter fec; // Number of redundancy packets/bytes. }; // Callback, called whenever byte/packet counts have been updated. diff --git a/include/webrtc/common_video/h264/h264_bitstream_parser.h b/include/webrtc/common_video/h264/h264_bitstream_parser.h new file mode 100644 index 0000000..aa01552 --- /dev/null +++ b/include/webrtc/common_video/h264/h264_bitstream_parser.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_H264_BITSTREAM_PARSER_H_ +#define WEBRTC_COMMON_VIDEO_H264_H264_BITSTREAM_PARSER_H_ +#include +#include + +#include "webrtc/base/optional.h" +#include "webrtc/common_video/h264/pps_parser.h" +#include "webrtc/common_video/h264/sps_parser.h" + +namespace rtc { +class BitBufferWriter; +} + +namespace webrtc { + +// Stateful H264 bitstream parser (due to SPS/PPS). Used to parse out QP values +// from the bitstream. +// TODO(pbos): Unify with RTP SPS parsing and only use one H264 parser. +// TODO(pbos): If/when this gets used on the receiver side CHECKs must be +// removed and gracefully abort as we have no control over receive-side +// bitstreams. +class H264BitstreamParser { + public: + enum Result { + kOk, + kInvalidStream, + kUnsupportedStream, + }; + + H264BitstreamParser(); + virtual ~H264BitstreamParser(); + + // Parse an additional chunk of H264 bitstream. + void ParseBitstream(const uint8_t* bitstream, size_t length); + + // Get the last extracted QP value from the parsed bitstream. + bool GetLastSliceQp(int* qp) const; + + protected: + void ParseSlice(const uint8_t* slice, size_t length); + Result ParseNonParameterSetNalu(const uint8_t* source, + size_t source_length, + uint8_t nalu_type); + + // SPS/PPS state, updated when parsing new SPS/PPS, used to parse slices. + rtc::Optional sps_; + rtc::Optional pps_; + + // Last parsed slice QP. + rtc::Optional last_slice_qp_delta_; +}; + +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_H264_H264_BITSTREAM_PARSER_H_ diff --git a/include/webrtc/common_video/h264/h264_common.h b/include/webrtc/common_video/h264/h264_common.h new file mode 100644 index 0000000..99789ee --- /dev/null +++ b/include/webrtc/common_video/h264/h264_common.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_H264_COMMON_H_ +#define WEBRTC_COMMON_VIDEO_H264_H264_COMMON_H_ + +#include +#include + +#include "webrtc/base/buffer.h" + +namespace webrtc { + +namespace H264 { +// The size of a full NALU start sequence {0 0 0 1}, used for the first NALU +// of an access unit, and for SPS and PPS blocks. +const size_t kNaluLongStartSequenceSize = 4; + +// The size of a shortened NALU start sequence {0 0 1}, that may be used if +// not the first NALU of an access unit or an SPS or PPS block. +const size_t kNaluShortStartSequenceSize = 3; + +// The size of the NALU type byte (1). +const size_t kNaluTypeSize = 1; + +enum NaluType : uint8_t { + kSlice = 1, + kIdr = 5, + kSei = 6, + kSps = 7, + kPps = 8, + kAud = 9, + kEndOfSequence = 10, + kEndOfStream = 11, + kFiller = 12, + kStapA = 24, + kFuA = 28 +}; + +enum SliceType : uint8_t { kP = 0, kB = 1, kI = 2, kSp = 3, kSi = 4 }; + +struct NaluIndex { + // Start index of NALU, including start sequence. + size_t start_offset; + // Start index of NALU payload, typically type header. + size_t payload_start_offset; + // Length of NALU payload, in bytes, counting from payload_start_offset. + size_t payload_size; +}; + +// Returns a vector of the NALU indices in the given buffer. +std::vector FindNaluIndices(const uint8_t* buffer, + size_t buffer_size); + +// Get the NAL type from the header byte immediately following start sequence. +NaluType ParseNaluType(uint8_t data); + +// Methods for parsing and writing RBSP. See section 7.4.1 of the H264 spec. +// +// The following sequences are illegal, and need to be escaped when encoding: +// 00 00 00 -> 00 00 03 00 +// 00 00 01 -> 00 00 03 01 +// 00 00 02 -> 00 00 03 02 +// And things in the source that look like the emulation byte pattern (00 00 03) +// need to have an extra emulation byte added, so it's removed when decoding: +// 00 00 03 -> 00 00 03 03 +// +// Decoding is simply a matter of finding any 00 00 03 sequence and removing +// the 03 emulation byte. + +// Parse the given data and remove any emulation byte escaping. +std::unique_ptr ParseRbsp(const uint8_t* data, size_t length); + +// Write the given data to the destination buffer, inserting and emulation +// bytes in order to escape any data the could be interpreted as a start +// sequence. +void WriteRbsp(const uint8_t* bytes, size_t length, rtc::Buffer* destination); +} // namespace H264 +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_H264_H264_COMMON_H_ diff --git a/include/webrtc/common_video/h264/pps_parser.h b/include/webrtc/common_video/h264/pps_parser.h new file mode 100644 index 0000000..02167a8 --- /dev/null +++ b/include/webrtc/common_video/h264/pps_parser.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_PPS_PARSER_H_ +#define WEBRTC_COMMON_VIDEO_H264_PPS_PARSER_H_ + +#include "webrtc/base/optional.h" + +namespace rtc { +class BitBuffer; +} + +namespace webrtc { + +// A class for parsing out picture parameter set (PPS) data from a H264 NALU. +class PpsParser { + public: + // The parsed state of the PPS. Only some select values are stored. + // Add more as they are actually needed. + struct PpsState { + PpsState() = default; + + bool bottom_field_pic_order_in_frame_present_flag = false; + bool weighted_pred_flag = false; + bool entropy_coding_mode_flag = false; + uint32_t weighted_bipred_idc = false; + uint32_t redundant_pic_cnt_present_flag = 0; + int pic_init_qp_minus26 = 0; + uint32_t id = 0; + uint32_t sps_id = 0; + }; + + // Unpack RBSP and parse PPS state from the supplied buffer. + static rtc::Optional ParsePps(const uint8_t* data, size_t length); + + static bool ParsePpsIds(const uint8_t* data, + size_t length, + uint32_t* pps_id, + uint32_t* sps_id); + + static rtc::Optional ParsePpsIdFromSlice(const uint8_t* data, + size_t length); + + protected: + // Parse the PPS state, for a bit buffer where RBSP decoding has already been + // performed. + static rtc::Optional ParseInternal(rtc::BitBuffer* bit_buffer); + static bool ParsePpsIdsInternal(rtc::BitBuffer* bit_buffer, + uint32_t* pps_id, + uint32_t* sps_id); +}; + +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_H264_PPS_PARSER_H_ diff --git a/include/webrtc/common_video/h264/profile_level_id.h b/include/webrtc/common_video/h264/profile_level_id.h new file mode 100644 index 0000000..20147bb --- /dev/null +++ b/include/webrtc/common_video/h264/profile_level_id.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_ +#define WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_ + +#include +#include + +#include "webrtc/base/optional.h" +#include "webrtc/common_types.h" + +namespace webrtc { +namespace H264 { + +// Map containting SDP codec parameters. +typedef std::map CodecParameterMap; + +// All values are equal to ten times the level number, except level 1b which is +// special. +enum Level { + kLevel1_b = 0, + kLevel1 = 10, + kLevel1_1 = 11, + kLevel1_2 = 12, + kLevel1_3 = 13, + kLevel2 = 20, + kLevel2_1 = 21, + kLevel2_2 = 22, + kLevel3 = 30, + kLevel3_1 = 31, + kLevel3_2 = 32, + kLevel4 = 40, + kLevel4_1 = 41, + kLevel4_2 = 42, + kLevel5 = 50, + kLevel5_1 = 51, + kLevel5_2 = 52 +}; + +struct ProfileLevelId { + ProfileLevelId(Profile profile, Level level) + : profile(profile), level(level) {} + Profile profile; + Level level; +}; + +// Parse profile level id that is represented as a string of 3 hex bytes. +// Nothing will be returned if the string is not a recognized H264 +// profile level id. +rtc::Optional ParseProfileLevelId(const char* str); + +// Parse profile level id that is represented as a string of 3 hex bytes +// contained in an SDP key-value map. A default profile level id will be +// returned if the profile-level-id key is missing. Nothing will be returned if +// the key is present but the string is invalid. +rtc::Optional ParseSdpProfileLevelId( + const CodecParameterMap& params); + +// Given that a decoder supports up to a given frame size (in pixels) at up to a +// given number of frames per second, return the highest H.264 level where it +// can guarantee that it will be able to support all valid encoded streams that +// are within that level. +rtc::Optional SupportedLevel(int max_frame_pixel_count, float max_fps); + +// Returns canonical string representation as three hex bytes of the profile +// level id, or returns nothing for invalid profile level ids. +rtc::Optional ProfileLevelIdToString( + const ProfileLevelId& profile_level_id); + +// Generate codec parameters that will be used as answer in an SDP negotiation +// based on local supported parameters and remote offered parameters. Both +// |local_supported_params|, |remote_offered_params|, and |answer_params| +// represent sendrecv media descriptions, i.e they are a mix of both encode and +// decode capabilities. In theory, when the profile in |local_supported_params| +// represent a strict superset of the profile in |remote_offered_params|, we +// could limit the profile in |answer_params| to the profile in +// |remote_offered_params|. However, to simplify the code, each supported H264 +// profile should be listed explicitly in the list of local supported codecs, +// even if they are redundant. Then each local codec in the list should be +// tested one at a time against the remote codec, and only when the profiles are +// equal should this function be called. Therefore, this function does not need +// to handle profile intersection, and the profile of |local_supported_params| +// and |remote_offered_params| must be equal before calling this function. The +// parameters that are used when negotiating are the level part of +// profile-level-id and level-asymmetry-allowed. +void GenerateProfileLevelIdForAnswer( + const CodecParameterMap& local_supported_params, + const CodecParameterMap& remote_offered_params, + CodecParameterMap* answer_params); + +} // namespace H264 +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_H264_PROFILE_LEVEL_ID_H_ diff --git a/include/webrtc/common_video/h264/sps_parser.h b/include/webrtc/common_video/h264/sps_parser.h new file mode 100644 index 0000000..dfd4b6b --- /dev/null +++ b/include/webrtc/common_video/h264/sps_parser.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_SPS_PARSER_H_ +#define WEBRTC_COMMON_VIDEO_H264_SPS_PARSER_H_ + +#include "webrtc/base/optional.h" + +namespace rtc { +class BitBuffer; +} + +namespace webrtc { + +// A class for parsing out sequence parameter set (SPS) data from an H264 NALU. +class SpsParser { + public: + // The parsed state of the SPS. Only some select values are stored. + // Add more as they are actually needed. + struct SpsState { + SpsState() = default; + + uint32_t width = 0; + uint32_t height = 0; + uint32_t delta_pic_order_always_zero_flag = 0; + uint32_t separate_colour_plane_flag = 0; + uint32_t frame_mbs_only_flag = 0; + uint32_t log2_max_frame_num_minus4 = 0; + uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; + uint32_t pic_order_cnt_type = 0; + uint32_t max_num_ref_frames = 0; + uint32_t vui_params_present = 0; + uint32_t id = 0; + }; + + // Unpack RBSP and parse SPS state from the supplied buffer. + static rtc::Optional ParseSps(const uint8_t* data, size_t length); + + protected: + // Parse the SPS state, up till the VUI part, for a bit buffer where RBSP + // decoding has already been performed. + static rtc::Optional ParseSpsUpToVui(rtc::BitBuffer* buffer); +}; + +} // namespace webrtc +#endif // WEBRTC_COMMON_VIDEO_H264_SPS_PARSER_H_ diff --git a/include/webrtc/common_video/h264/sps_vui_rewriter.h b/include/webrtc/common_video/h264/sps_vui_rewriter.h new file mode 100644 index 0000000..bf052b3 --- /dev/null +++ b/include/webrtc/common_video/h264/sps_vui_rewriter.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#ifndef WEBRTC_COMMON_VIDEO_H264_SPS_VUI_REWRITER_H_ +#define WEBRTC_COMMON_VIDEO_H264_SPS_VUI_REWRITER_H_ + +#include "webrtc/base/buffer.h" +#include "webrtc/base/optional.h" +#include "webrtc/common_video/h264/sps_parser.h" + +namespace rtc { +class BitBuffer; +} + +namespace webrtc { + +// A class that can parse an SPS block of a NAL unit and if necessary +// creates a copy with updated settings to allow for faster decoding for streams +// that use picture order count type 0. Streams in that format incur additional +// delay because it allows decode order to differ from render order. +// The mechanism used is to rewrite (edit or add) the SPS's VUI to contain +// restrictions on the maximum number of reordered pictures. This reduces +// latency significantly, though it still adds about a frame of latency to +// decoding. +class SpsVuiRewriter : private SpsParser { + public: + enum class ParseResult { kFailure, kPocOk, kVuiOk, kVuiRewritten }; + + // Parses an SPS block and if necessary copies it and rewrites the VUI. + // Returns kFailure on failure, kParseOk if parsing succeeded and no update + // was necessary and kParsedAndModified if an updated copy of buffer was + // written to destination. destination may be populated with some data even if + // no rewrite was necessary, but the end offset should remain unchanged. + // Unless parsing fails, the sps parameter will be populated with the parsed + // SPS state. This function assumes that any previous headers + // (NALU start, type, Stap-A, etc) have already been parsed and that RBSP + // decoding has been performed. + static ParseResult ParseAndRewriteSps(const uint8_t* buffer, + size_t length, + rtc::Optional* sps, + rtc::Buffer* destination); +}; + +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_H264_SPS_VUI_REWRITER_H_ diff --git a/include/webrtc/common_video/include/bitrate_adjuster.h b/include/webrtc/common_video/include/bitrate_adjuster.h index 1f2474f..5fd1e38 100644 --- a/include/webrtc/common_video/include/bitrate_adjuster.h +++ b/include/webrtc/common_video/include/bitrate_adjuster.h @@ -47,7 +47,7 @@ class BitrateAdjuster { uint32_t GetAdjustedBitrateBps() const; // Returns what we think the current bitrate is. - uint32_t GetEstimatedBitrateBps(); + rtc::Optional GetEstimatedBitrateBps(); // This should be called after each frame is encoded. The timestamp at which // it is called is used to estimate the output bitrate of the encoder. diff --git a/include/webrtc/common_video/include/corevideo_frame_buffer.h b/include/webrtc/common_video/include/corevideo_frame_buffer.h index ed5361d..a00b677 100644 --- a/include/webrtc/common_video/include/corevideo_frame_buffer.h +++ b/include/webrtc/common_video/include/corevideo_frame_buffer.h @@ -13,6 +13,8 @@ #include +#include + #include "webrtc/common_video/include/video_frame_buffer.h" namespace webrtc { @@ -20,15 +22,38 @@ namespace webrtc { class CoreVideoFrameBuffer : public NativeHandleBuffer { public: explicit CoreVideoFrameBuffer(CVPixelBufferRef pixel_buffer); + CoreVideoFrameBuffer(CVPixelBufferRef pixel_buffer, + int adapted_width, + int adapted_height, + int crop_width, + int crop_height, + int crop_x, + int crop_y); ~CoreVideoFrameBuffer() override; rtc::scoped_refptr NativeToI420Buffer() override; + // Returns true if the internal pixel buffer needs to be cropped. + bool RequiresCropping() const; + // Crop and scales the internal pixel buffer to the output pixel buffer. The + // tmp buffer is used for intermediary splitting the UV channels. This + // function returns true if successful. + bool CropAndScaleTo(std::vector* tmp_buffer, + CVPixelBufferRef output_pixel_buffer) const; private: CVPixelBufferRef pixel_buffer_; + // buffer_width/height is the actual pixel buffer resolution. The width/height + // in NativeHandleBuffer, i.e. width()/height(), is the resolution we will + // scale to in NativeToI420Buffer(). Cropping happens before scaling, so: + // buffer_width >= crop_width >= width(). + const int buffer_width_; + const int buffer_height_; + const int crop_width_; + const int crop_height_; + const int crop_x_; + const int crop_y_; }; } // namespace webrtc #endif // WEBRTC_COMMON_VIDEO_INCLUDE_COREVIDEO_FRAME_BUFFER_H_ - diff --git a/include/webrtc/common_video/include/frame_callback.h b/include/webrtc/common_video/include/frame_callback.h index 81737c6..45624f1 100644 --- a/include/webrtc/common_video/include/frame_callback.h +++ b/include/webrtc/common_video/include/frame_callback.h @@ -22,23 +22,32 @@ class VideoFrame; struct EncodedFrame { public: - EncodedFrame() : data_(NULL), length_(0), frame_type_(kEmptyFrame) {} - EncodedFrame(const uint8_t* data, size_t length, FrameType frame_type) - : data_(data), length_(length), frame_type_(frame_type) {} + EncodedFrame() + : data_(nullptr), + length_(0), + frame_type_(kEmptyFrame), + encoded_width_(0), + encoded_height_(0), + timestamp_(0) {} + EncodedFrame(const uint8_t* data, + size_t length, + FrameType frame_type, + uint32_t encoded_width, + uint32_t encoded_height, + uint32_t timestamp) + : data_(data), + length_(length), + frame_type_(frame_type), + encoded_width_(encoded_width), + encoded_height_(encoded_height), + timestamp_(timestamp) {} const uint8_t* data_; const size_t length_; const FrameType frame_type_; -}; - -class I420FrameCallback { - public: - // This function is called with a I420 frame allowing the user to modify the - // frame content. - virtual void FrameCallback(VideoFrame* video_frame) = 0; - - protected: - virtual ~I420FrameCallback() {} + const uint32_t encoded_width_; + const uint32_t encoded_height_; + const uint32_t timestamp_; }; class EncodedFrameObserver { diff --git a/include/webrtc/common_video/include/i420_buffer_pool.h b/include/webrtc/common_video/include/i420_buffer_pool.h index 5c9ab06..454a8cd 100644 --- a/include/webrtc/common_video/include/i420_buffer_pool.h +++ b/include/webrtc/common_video/include/i420_buffer_pool.h @@ -12,9 +12,10 @@ #define WEBRTC_COMMON_VIDEO_INCLUDE_I420_BUFFER_POOL_H_ #include +#include -#include "webrtc/base/thread_checker.h" -#include "webrtc/common_video/include/video_frame_buffer.h" +#include "webrtc/api/video/i420_buffer.h" +#include "webrtc/base/race_checker.h" namespace webrtc { @@ -23,27 +24,39 @@ namespace webrtc { // When the I420Buffer is destructed, the memory is returned to the pool for use // by subsequent calls to CreateBuffer. If the resolution passed to CreateBuffer // changes, old buffers will be purged from the pool. +// Note that CreateBuffer will crash if more than kMaxNumberOfFramesBeforeCrash +// are created. This is to prevent memory leaks where frames are not returned. class I420BufferPool { public: - I420BufferPool() : I420BufferPool(false) {} - explicit I420BufferPool(bool zero_initialize); + I420BufferPool() + : I420BufferPool(false) {} + explicit I420BufferPool(bool zero_initialize) + : I420BufferPool(zero_initialize, std::numeric_limits::max()) {} + I420BufferPool(bool zero_initialze, size_t max_number_of_buffers); - // Returns a buffer from the pool, or creates a new buffer if no suitable - // buffer exists in the pool. - rtc::scoped_refptr CreateBuffer(int width, int height); + // Returns a buffer from the pool. If no suitable buffer exist in the pool + // and there are less than |max_number_of_buffers| pending, a buffer is + // created. Returns null otherwise. + rtc::scoped_refptr CreateBuffer(int width, int height); // Clears buffers_ and detaches the thread checker so that it can be reused // later from another thread. void Release(); private: - rtc::ThreadChecker thread_checker_; - std::list> buffers_; + // Explicitly use a RefCountedObject to get access to HasOneRef, + // needed by the pool to check exclusive access. + using PooledI420Buffer = rtc::RefCountedObject; + + rtc::RaceChecker race_checker_; + std::list> buffers_; // If true, newly allocated buffers are zero-initialized. Note that recycled // buffers are not zero'd before reuse. This is required of buffers used by // FFmpeg according to http://crbug.com/390941, which only requires it for the // initial allocation (as shown by FFmpeg's own buffer allocation code). It // has to do with "Use-of-uninitialized-value" on "Linux_msan_chrome". - bool zero_initialize_; + const bool zero_initialize_; + // Max number of buffers this pool can have pending. + const size_t max_number_of_buffers_; }; } // namespace webrtc diff --git a/include/webrtc/common_video/include/incoming_video_stream.h b/include/webrtc/common_video/include/incoming_video_stream.h index 32e3184..ff407c5 100644 --- a/include/webrtc/common_video/include/incoming_video_stream.h +++ b/include/webrtc/common_video/include/incoming_video_stream.h @@ -11,77 +11,32 @@ #ifndef WEBRTC_COMMON_VIDEO_INCLUDE_INCOMING_VIDEO_STREAM_H_ #define WEBRTC_COMMON_VIDEO_INCLUDE_INCOMING_VIDEO_STREAM_H_ -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/platform_thread.h" -#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/race_checker.h" +#include "webrtc/base/task_queue.h" #include "webrtc/common_video/video_render_frames.h" #include "webrtc/media/base/videosinkinterface.h" namespace webrtc { -class EventTimerWrapper; - class IncomingVideoStream : public rtc::VideoSinkInterface { public: - explicit IncomingVideoStream(bool disable_prerenderer_smoothing); - ~IncomingVideoStream(); - - // Overrides VideoSinkInterface - void OnFrame(const VideoFrame& video_frame) override; - - // Set callback to the platform dependent code. - void SetRenderCallback(rtc::VideoSinkInterface* render_callback); - - // Callback for file recording, snapshot, ... - void SetExternalCallback(rtc::VideoSinkInterface* render_object); - - // Start/Stop. - int32_t Start(); - int32_t Stop(); - - // Clear all buffers. - int32_t Reset(); - - // Properties. - uint32_t IncomingRate() const; - - int32_t SetExpectedRenderDelay(int32_t delay_ms); - - protected: - static bool IncomingVideoStreamThreadFun(void* obj); - bool IncomingVideoStreamProcess(); + IncomingVideoStream(int32_t delay_ms, + rtc::VideoSinkInterface* callback); + ~IncomingVideoStream() override; private: - enum { kEventStartupTimeMs = 10 }; - enum { kEventMaxWaitTimeMs = 100 }; - enum { kFrameRatePeriodMs = 1000 }; - - void DeliverFrame(const VideoFrame& video_frame); + void OnFrame(const VideoFrame& video_frame) override; + void Dequeue(); - const bool disable_prerenderer_smoothing_; - // Critsects in allowed to enter order. - rtc::CriticalSection stream_critsect_; - rtc::CriticalSection thread_critsect_; - rtc::CriticalSection buffer_critsect_; - // TODO(pbos): Make plain member and stop resetting this thread, just - // start/stoping it is enough. - std::unique_ptr incoming_render_thread_ - GUARDED_BY(thread_critsect_); - std::unique_ptr deliver_buffer_event_; + // Fwd decl of a QueuedTask implementation for carrying frames over to the TQ. + class NewFrameTask; - bool running_ GUARDED_BY(stream_critsect_); - rtc::VideoSinkInterface* external_callback_ - GUARDED_BY(thread_critsect_); - rtc::VideoSinkInterface* render_callback_ - GUARDED_BY(thread_critsect_); - const std::unique_ptr render_buffers_ - GUARDED_BY(buffer_critsect_); + rtc::ThreadChecker main_thread_checker_; + rtc::RaceChecker decoder_race_checker_; - uint32_t incoming_rate_ GUARDED_BY(stream_critsect_); - int64_t last_rate_calculation_time_ms_ GUARDED_BY(stream_critsect_); - uint16_t num_frames_since_last_calculation_ GUARDED_BY(stream_critsect_); + VideoRenderFrames render_buffers_; // Only touched on the TaskQueue. + rtc::VideoSinkInterface* const callback_; + rtc::TaskQueue incoming_render_queue_; }; } // namespace webrtc diff --git a/include/webrtc/common_video/include/video_bitrate_allocator.h b/include/webrtc/common_video/include/video_bitrate_allocator.h new file mode 100644 index 0000000..b85879d --- /dev/null +++ b/include/webrtc/common_video/include/video_bitrate_allocator.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_ +#define WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_ + +#include "webrtc/common_types.h" + +namespace webrtc { + +class VideoBitrateAllocator { + public: + VideoBitrateAllocator() {} + virtual ~VideoBitrateAllocator() {} + + virtual BitrateAllocation GetAllocation(uint32_t total_bitrate, + uint32_t framerate) = 0; + virtual uint32_t GetPreferredBitrateBps(uint32_t framerate) = 0; +}; + +class VideoBitrateAllocationObserver { + public: + VideoBitrateAllocationObserver() {} + virtual ~VideoBitrateAllocationObserver() {} + + virtual void OnBitrateAllocationUpdated( + const BitrateAllocation& allocation) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_BITRATE_ALLOCATOR_H_ diff --git a/include/webrtc/common_video/include/video_frame_buffer.h b/include/webrtc/common_video/include/video_frame_buffer.h index 6f082de..dfdd480 100644 --- a/include/webrtc/common_video/include/video_frame_buffer.h +++ b/include/webrtc/common_video/include/video_frame_buffer.h @@ -11,129 +11,17 @@ #ifndef WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_FRAME_BUFFER_H_ #define WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_FRAME_BUFFER_H_ -#include - #include +#include "webrtc/api/video/video_frame_buffer.h" +// TODO(nisse): For backwards compatibility, files including this file +// expect it to declare I420Buffer. Delete after callers are updated. +#include "webrtc/api/video/i420_buffer.h" #include "webrtc/base/callback.h" -#include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/system_wrappers/include/aligned_malloc.h" namespace webrtc { -enum PlaneType { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kNumOfPlanes = 3, -}; - -// Interface of a simple frame buffer containing pixel data. This interface does -// not contain any frame metadata such as rotation, timestamp, pixel_width, etc. -class VideoFrameBuffer : public rtc::RefCountInterface { - public: - // Returns true if the caller is exclusive owner, and allowed to - // call MutableData. - - // TODO(nisse): Delete default implementation when subclasses in - // Chrome are updated. - virtual bool IsMutable() { return false; } - - // Underlying refcount access, used to implement IsMutable. - // TODO(nisse): Demote to protected, as soon as Chrome is changed to - // use IsMutable. - virtual bool HasOneRef() const = 0; - - // The resolution of the frame in pixels. For formats where some planes are - // subsampled, this is the highest-resolution plane. - virtual int width() const = 0; - virtual int height() const = 0; - - // TODO(nisse): For the transition, we use default implementations - // of the stride and data methods where the new methods calls the - // old method, and the old method calls the new methods. Subclasses - // must override either the new methods or the old method, to break - // infinite recursion. And similarly for the strides. When - // applications, in particular Chrome, are updated, delete the old - // method and delete the default implementation of the new methods. - - // Returns pointer to the pixel data for a given plane. The memory is owned by - // the VideoFrameBuffer object and must not be freed by the caller. - virtual const uint8_t* DataY() const; - virtual const uint8_t* DataU() const; - virtual const uint8_t* DataV() const; - // Deprecated method. - // TODO(nisse): Delete after all users are updated. - virtual const uint8_t* data(PlaneType type) const; - - // Non-const data access is allowed only if HasOneRef() is true. - virtual uint8_t* MutableDataY(); - virtual uint8_t* MutableDataU(); - virtual uint8_t* MutableDataV(); - // Deprecated method. TODO(nisse): Delete after all users are updated. - virtual uint8_t* MutableData(PlaneType type); - - // Returns the number of bytes between successive rows for a given plane. - virtual int StrideY() const; - virtual int StrideU() const; - virtual int StrideV() const; - // Deprecated method. TODO(nisse): Delete after all users are updated. - virtual int stride(PlaneType type) const; - - // Return the handle of the underlying video frame. This is used when the - // frame is backed by a texture. - virtual void* native_handle() const = 0; - - // Returns a new memory-backed frame buffer converted from this buffer's - // native handle. - virtual rtc::scoped_refptr NativeToI420Buffer() = 0; - - protected: - virtual ~VideoFrameBuffer(); -}; - -// Plain I420 buffer in standard memory. -class I420Buffer : public VideoFrameBuffer { - public: - I420Buffer(int width, int height); - I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v); - void InitializeData(); - - int width() const override; - int height() const override; - const uint8_t* DataY() const override; - const uint8_t* DataU() const override; - const uint8_t* DataV() const override; - // Non-const data access is only allowed if IsMutable() is true, to protect - // against unexpected overwrites. - bool IsMutable() override; - uint8_t* MutableDataY() override; - uint8_t* MutableDataU() override; - uint8_t* MutableDataV() override; - int StrideY() const override; - int StrideU() const override; - int StrideV() const override; - - void* native_handle() const override; - rtc::scoped_refptr NativeToI420Buffer() override; - - // Create a new buffer and copy the pixel data. - static rtc::scoped_refptr Copy( - const rtc::scoped_refptr& buffer); - - protected: - ~I420Buffer() override; - - private: - const int width_; - const int height_; - const int stride_y_; - const int stride_u_; - const int stride_v_; - const std::unique_ptr data_; -}; - // Base class for native-handle buffer is a wrapper around a |native_handle|. // This is used for convenience as most native-handle implementations can share // many VideoFrame implementations, but need to implement a few others (such @@ -152,7 +40,6 @@ class NativeHandleBuffer : public VideoFrameBuffer { int StrideV() const override; void* native_handle() const override; - bool IsMutable() override; protected: void* native_handle_; @@ -174,8 +61,6 @@ class WrappedI420Buffer : public webrtc::VideoFrameBuffer { int width() const override; int height() const override; - bool IsMutable() override; - const uint8_t* DataY() const override; const uint8_t* DataU() const override; const uint8_t* DataV() const override; @@ -202,13 +87,6 @@ class WrappedI420Buffer : public webrtc::VideoFrameBuffer { rtc::Callback0 no_longer_used_cb_; }; -// Helper function to crop |buffer| without making a deep copy. May only be used -// for non-native frames. -rtc::scoped_refptr ShallowCenterCrop( - const rtc::scoped_refptr& buffer, - int cropped_width, - int cropped_height); - } // namespace webrtc #endif // WEBRTC_COMMON_VIDEO_INCLUDE_VIDEO_FRAME_BUFFER_H_ diff --git a/include/webrtc/common_video/libyuv/include/scaler.h b/include/webrtc/common_video/libyuv/include/scaler.h deleted file mode 100644 index 2b92f81..0000000 --- a/include/webrtc/common_video/libyuv/include/scaler.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -/* - * Interface to the LibYuv scaling functionality - */ - -#ifndef WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_SCALER_H_ -#define WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_SCALER_H_ - -#include "webrtc/common_video/include/i420_buffer_pool.h" -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" - -namespace webrtc { - -// Supported scaling types -enum ScaleMethod { - kScalePoint, // no interpolation - kScaleBilinear, - kScaleBox -}; - -class Scaler { - public: - Scaler(); - ~Scaler(); - - // Set interpolation properties: - // - // Return value: 0 - OK - // -1 - parameter error - int Set(int src_width, int src_height, - int dst_width, int dst_height, - VideoType src_video_type, VideoType dst_video_type, - ScaleMethod method); - - // Scale frame - // Memory is allocated by this object and recycled using |buffer_pool_|. - // Return value: 0 - OK, - // -1 - parameter error - // -2 - scaler not set - int Scale(const VideoFrame& src_frame, VideoFrame* dst_frame); - - private: - // Determine if the VideoTypes are currently supported. - bool SupportedVideoType(VideoType src_video_type, - VideoType dst_video_type); - - ScaleMethod method_; - int src_width_; - int src_height_; - int dst_width_; - int dst_height_; - bool set_; - I420BufferPool buffer_pool_; -}; - -} // namespace webrtc - -#endif // WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_SCALER_H_ diff --git a/include/webrtc/common_video/libyuv/include/webrtc_libyuv.h b/include/webrtc/common_video/libyuv/include/webrtc_libyuv.h index d66736f..6d7ed1f 100644 --- a/include/webrtc/common_video/libyuv/include/webrtc_libyuv.h +++ b/include/webrtc/common_video/libyuv/include/webrtc_libyuv.h @@ -16,14 +16,16 @@ #define WEBRTC_COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_ #include +#include +#include "webrtc/api/video/video_frame.h" #include "webrtc/common_types.h" // RawVideoTypes. -#include "webrtc/common_video/rotation.h" #include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" namespace webrtc { +class I420Buffer; + // Supported video types. enum VideoType { kUnknown, @@ -51,22 +53,6 @@ const double kPerfectPSNR = 48.0f; // TODO(wu): Consolidate types into one type throughout WebRtc. VideoType RawVideoTypeToCommonVideoVideoType(RawVideoType type); -// Align integer values. -// Input: -// - value : Input value to be aligned. -// - alignment : Alignment basis (power of 2). -// Return value: An aligned form of the input value. -int AlignInt(int value, int alignment); - -// Align stride values for I420 Video frames. -// Input: -// - width : Image width. -// - stride_y : Pointer to the stride of the y plane. -// - stride_uv: Pointer to the stride of the u and v planes (setting identical -// values for both). -// Setting 16 byte alignment. -void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv); - // Calculate the required buffer size. // Input: // - type :The type of the designated video frame. @@ -84,14 +70,19 @@ size_t CalcBufferSize(VideoType type, int width, int height); // already open for writing. // Return value: 0 if OK, < 0 otherwise. int PrintVideoFrame(const VideoFrame& frame, FILE* file); +int PrintVideoFrame(const VideoFrameBuffer& frame, FILE* file); -// Extract buffer from VideoFrame (consecutive planes, no stride) +// Extract buffer from VideoFrame or VideoFrameBuffer (consecutive +// planes, no stride) // Input: // - frame : Reference to video frame. // - size : pointer to the size of the allocated buffer. If size is // insufficient, an error will be returned. // - buffer : Pointer to buffer // Return value: length of buffer if OK, < 0 otherwise. +int ExtractBuffer(const rtc::scoped_refptr& input_frame, + size_t size, + uint8_t* buffer); int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer); // Convert To I420 // Input: @@ -103,9 +94,14 @@ int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer); // - sample_size : Required only for the parsing of MJPG (set to 0 else). // - rotate : Rotation mode of output image. // Output: -// - dst_frame : Reference to a destination frame. +// - dst_buffer : Reference to a destination frame buffer. // Return value: 0 if OK, < 0 otherwise. +// TODO(nisse): Delete this wrapper, and let users call libyuv directly. Most +// calls pass |src_video_type| == kI420, and should use libyuv::I420Copy. Also +// remember to delete the I420Buffer forward declaration above. The only +// exception at the time of this writing is VideoCaptureImpl::IncomingFrame, +// which still needs libyuv::ConvertToI420. int ConvertToI420(VideoType src_video_type, const uint8_t* src_frame, int crop_x, @@ -114,7 +110,7 @@ int ConvertToI420(VideoType src_video_type, int src_height, size_t sample_size, VideoRotation rotation, - VideoFrame* dst_frame); + I420Buffer* dst_buffer); // Convert From I420 // Input: @@ -128,30 +124,42 @@ int ConvertFromI420(const VideoFrame& src_frame, VideoType dst_video_type, int dst_sample_size, uint8_t* dst_frame); -// ConvertFrom YV12. -// Interface - same as above. -int ConvertFromYV12(const VideoFrame& src_frame, - VideoType dst_video_type, - int dst_sample_size, - uint8_t* dst_frame); - -// The following list describes designated conversion functions which -// are not covered by the previous general functions. -// Input and output descriptions mostly match the above descriptions, and are -// therefore omitted. -int ConvertRGB24ToARGB(const uint8_t* src_frame, - uint8_t* dst_frame, - int width, int height, - int dst_stride); -int ConvertNV12ToRGB565(const uint8_t* src_frame, - uint8_t* dst_frame, - int width, int height); // Compute PSNR for an I420 frame (all planes). // Returns the PSNR in decibel, to a maximum of kInfinitePSNR. double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame); +double I420PSNR(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer); + // Compute SSIM for an I420 frame (all planes). double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame); +double I420SSIM(const VideoFrameBuffer& ref_buffer, + const VideoFrameBuffer& test_buffer); + +// Helper function for scaling NV12 to NV12. +void NV12Scale(std::vector* tmp_buffer, + const uint8_t* src_y, int src_stride_y, + const uint8_t* src_uv, int src_stride_uv, + int src_width, int src_height, + uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_uv, int dst_stride_uv, + int dst_width, int dst_height); + +// Helper class for directly converting and scaling NV12 to I420. The Y-plane +// will be scaled directly to the I420 destination, which makes this faster +// than separate NV12->I420 + I420->I420 scaling. +class NV12ToI420Scaler { + public: + void NV12ToI420Scale(const uint8_t* src_y, int src_stride_y, + const uint8_t* src_uv, int src_stride_uv, + int src_width, int src_height, + uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_u, int dst_stride_u, + uint8_t* dst_v, int dst_stride_v, + int dst_width, int dst_height); + private: + std::vector tmp_uv_planes_; +}; } // namespace webrtc diff --git a/include/webrtc/common_video/rotation.h b/include/webrtc/common_video/rotation.h index 46a9ecc..f01c812 100644 --- a/include/webrtc/common_video/rotation.h +++ b/include/webrtc/common_video/rotation.h @@ -8,19 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ +// TODO(nisse): Delete this file, once downstream code is updated. + #ifndef WEBRTC_COMMON_VIDEO_ROTATION_H_ #define WEBRTC_COMMON_VIDEO_ROTATION_H_ -namespace webrtc { - -// enum for clockwise rotation. -enum VideoRotation { - kVideoRotation_0 = 0, - kVideoRotation_90 = 90, - kVideoRotation_180 = 180, - kVideoRotation_270 = 270 -}; - -} // namespace webrtc +#include "webrtc/api/video/video_rotation.h" #endif // WEBRTC_COMMON_VIDEO_ROTATION_H_ diff --git a/include/webrtc/common_video/video_render_frames.h b/include/webrtc/common_video/video_render_frames.h index 450c1f2..5ed0760 100644 --- a/include/webrtc/common_video/video_render_frames.h +++ b/include/webrtc/common_video/video_render_frames.h @@ -15,43 +15,36 @@ #include -#include "webrtc/video_frame.h" +#include "webrtc/api/video/video_frame.h" +#include "webrtc/base/optional.h" namespace webrtc { // Class definitions class VideoRenderFrames { public: - VideoRenderFrames(); + explicit VideoRenderFrames(uint32_t render_delay_ms); + VideoRenderFrames(const VideoRenderFrames&) = delete; // Add a frame to the render queue - int32_t AddFrame(const VideoFrame& new_frame); + int32_t AddFrame(VideoFrame&& new_frame); - // Get a frame for rendering, or a zero-size frame if it's not time to render. - VideoFrame FrameToRender(); - - // Releases all frames - int32_t ReleaseAllFrames(); + // Get a frame for rendering, or false if it's not time to render. + rtc::Optional FrameToRender(); // Returns the number of ms to next frame to render uint32_t TimeToNextFrameRelease(); - // Sets estimates delay in renderer - int32_t SetRenderDelay(const uint32_t render_delay); + bool HasPendingFrames() const; private: - // 10 seconds for 30 fps. - enum { KMaxNumberOfFrames = 300 }; - // Don't render frames with timestamp older than 500ms from now. - enum { KOldRenderTimestampMS = 500 }; - // Don't render frames with timestamp more than 10s into the future. - enum { KFutureRenderTimestampMS = 10000 }; - // Sorted list with framed to be rendered, oldest first. std::list incoming_frames_; // Estimated delay from a frame is released until it's rendered. - uint32_t render_delay_ms_; + const uint32_t render_delay_ms_; + + int64_t last_render_time_ms_ = 0; }; } // namespace webrtc diff --git a/include/webrtc/config.h b/include/webrtc/config.h index 06460ae..f8c9e8b 100644 --- a/include/webrtc/config.h +++ b/include/webrtc/config.h @@ -16,7 +16,10 @@ #include #include -#include "webrtc/common.h" +#include "webrtc/base/basictypes.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/common_types.h" #include "webrtc/typedefs.h" @@ -25,6 +28,7 @@ namespace webrtc { // Settings for NACK, see RFC 4585 for details. struct NackConfig { NackConfig() : rtp_history_ms(0) {} + std::string ToString() const; // Send side: the time RTP packets are stored for retransmissions. // Receive side: the time the receiver is prepared to wait for // retransmissions. @@ -32,14 +36,16 @@ struct NackConfig { int rtp_history_ms; }; -// Settings for forward error correction, see RFC 5109 for details. Set the -// payload types to '-1' to disable. -struct FecConfig { - FecConfig() +// Settings for ULPFEC forward error correction. +// Set the payload types to '-1' to disable. +struct UlpfecConfig { + UlpfecConfig() : ulpfec_payload_type(-1), red_payload_type(-1), red_rtx_payload_type(-1) {} std::string ToString() const; + bool operator==(const UlpfecConfig& other) const; + // Payload type used for ULPFEC packets. int ulpfec_payload_type; @@ -52,20 +58,49 @@ struct FecConfig { // RTP header extension, see RFC 5285. struct RtpExtension { - RtpExtension(const std::string& name, int id) : name(name), id(id) {} + RtpExtension() : id(0) {} + RtpExtension(const std::string& uri, int id) : uri(uri), id(id) {} std::string ToString() const; bool operator==(const RtpExtension& rhs) const { - return name == rhs.name && id == rhs.id; + return uri == rhs.uri && id == rhs.id; } - static bool IsSupportedForAudio(const std::string& name); - static bool IsSupportedForVideo(const std::string& name); - - static const char* kTOffset; - static const char* kAbsSendTime; - static const char* kVideoRotation; - static const char* kAudioLevel; - static const char* kTransportSequenceNumber; - std::string name; + static bool IsSupportedForAudio(const std::string& uri); + static bool IsSupportedForVideo(const std::string& uri); + + // Header extension for audio levels, as defined in: + // http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03 + static const char* kAudioLevelUri; + static const int kAudioLevelDefaultId; + + // Header extension for RTP timestamp offset, see RFC 5450 for details: + // http://tools.ietf.org/html/rfc5450 + static const char* kTimestampOffsetUri; + static const int kTimestampOffsetDefaultId; + + // Header extension for absolute send time, see url for details: + // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time + static const char* kAbsSendTimeUri; + static const int kAbsSendTimeDefaultId; + + // Header extension for coordination of video orientation, see url for + // details: + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf + static const char* kVideoRotationUri; + static const int kVideoRotationDefaultId; + + // Header extension for transport sequence number, see url for details: + // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions + static const char* kTransportSequenceNumberUri; + static const int kTransportSequenceNumberDefaultId; + + static const char* kPlayoutDelayUri; + static const int kPlayoutDelayDefaultId; + + // Inclusive min and max IDs for one-byte header extensions, per RFC5285. + static const int kMinId; + static const int kMaxId; + + std::string uri; int id; }; @@ -92,60 +127,109 @@ struct VideoStream { // bitrate threshold of 100k and an estimate of 105k does not imply that we // get 100k in one temporal layer and 5k in the other, just that the bitrate // in the first temporal layer should not exceed 100k. - // TODO(pbos): Apart from a special case for two-layer screencast these + // TODO(kthelgason): Apart from a special case for two-layer screencast these // thresholds are not propagated to the VideoEncoder. To be implemented. std::vector temporal_layer_thresholds_bps; }; -struct VideoEncoderConfig { +class VideoEncoderConfig { + public: + // These are reference counted to permit copying VideoEncoderConfig and be + // kept alive until all encoder_specific_settings go out of scope. + // TODO(kthelgason): Consider removing the need for copying VideoEncoderConfig + // and use rtc::Optional for encoder_specific_settings instead. + class EncoderSpecificSettings : public rtc::RefCountInterface { + public: + // TODO(pbos): Remove FillEncoderSpecificSettings as soon as VideoCodec is + // not in use and encoder implementations ask for codec-specific structs + // directly. + void FillEncoderSpecificSettings(VideoCodec* codec_struct) const; + + virtual void FillVideoCodecVp8(VideoCodecVP8* vp8_settings) const; + virtual void FillVideoCodecVp9(VideoCodecVP9* vp9_settings) const; + virtual void FillVideoCodecH264(VideoCodecH264* h264_settings) const; + private: + ~EncoderSpecificSettings() override {} + friend class VideoEncoderConfig; + }; + + class H264EncoderSpecificSettings : public EncoderSpecificSettings { + public: + explicit H264EncoderSpecificSettings(const VideoCodecH264& specifics); + void FillVideoCodecH264(VideoCodecH264* h264_settings) const override; + + private: + VideoCodecH264 specifics_; + }; + + class Vp8EncoderSpecificSettings : public EncoderSpecificSettings { + public: + explicit Vp8EncoderSpecificSettings(const VideoCodecVP8& specifics); + void FillVideoCodecVp8(VideoCodecVP8* vp8_settings) const override; + + private: + VideoCodecVP8 specifics_; + }; + + class Vp9EncoderSpecificSettings : public EncoderSpecificSettings { + public: + explicit Vp9EncoderSpecificSettings(const VideoCodecVP9& specifics); + void FillVideoCodecVp9(VideoCodecVP9* vp9_settings) const override; + + private: + VideoCodecVP9 specifics_; + }; + enum class ContentType { kRealtimeVideo, kScreen, }; + class VideoStreamFactoryInterface : public rtc::RefCountInterface { + public: + // An implementation should return a std::vector with the + // wanted VideoStream settings for the given video resolution. + // The size of the vector may not be larger than + // |encoder_config.number_of_streams|. + virtual std::vector CreateEncoderStreams( + int width, + int height, + const VideoEncoderConfig& encoder_config) = 0; + + protected: + ~VideoStreamFactoryInterface() override {} + }; + + VideoEncoderConfig& operator=(VideoEncoderConfig&&) = default; + VideoEncoderConfig& operator=(const VideoEncoderConfig&) = delete; + + // Mostly used by tests. Avoid creating copies if you can. + VideoEncoderConfig Copy() const { return VideoEncoderConfig(*this); } + VideoEncoderConfig(); + VideoEncoderConfig(VideoEncoderConfig&&); ~VideoEncoderConfig(); std::string ToString() const; - std::vector streams; + rtc::scoped_refptr video_stream_factory; std::vector spatial_layers; ContentType content_type; - void* encoder_specific_settings; + rtc::scoped_refptr encoder_specific_settings; // Padding will be used up to this bitrate regardless of the bitrate produced // by the encoder. Padding above what's actually produced by the encoder helps // maintaining a higher bitrate estimate. Padding will however not be sent // unless the estimated bandwidth indicates that the link can handle it. int min_transmit_bitrate_bps; -}; - -// Controls the capacity of the packet buffer in NetEq. The capacity is the -// maximum number of packets that the buffer can contain. If the limit is -// exceeded, the buffer will be flushed. The capacity does not affect the actual -// audio delay in the general case, since this is governed by the target buffer -// level (calculated from the jitter profile). It is only in the rare case of -// severe network freezes that a higher capacity will lead to a (transient) -// increase in audio delay. -struct NetEqCapacityConfig { - NetEqCapacityConfig() : enabled(false), capacity(0) {} - explicit NetEqCapacityConfig(int value) : enabled(true), capacity(value) {} - static const ConfigOptionID identifier = ConfigOptionID::kNetEqCapacityConfig; - bool enabled; - int capacity; -}; + int max_bitrate_bps; -struct NetEqFastAccelerate { - NetEqFastAccelerate() : enabled(false) {} - explicit NetEqFastAccelerate(bool value) : enabled(value) {} - static const ConfigOptionID identifier = ConfigOptionID::kNetEqFastAccelerate; - bool enabled; -}; + // Max number of encoded VideoStreams to produce. + size_t number_of_streams; -struct VoicePacing { - VoicePacing() : enabled(false) {} - explicit VoicePacing(bool value) : enabled(value) {} - static const ConfigOptionID identifier = ConfigOptionID::kVoicePacing; - bool enabled; + private: + // Access to the copy constructor is private to force use of the Copy() + // method for those exceptional cases where we do use it. + VideoEncoderConfig(const VideoEncoderConfig&); }; } // namespace webrtc diff --git a/include/webrtc/engine_configurations.h b/include/webrtc/engine_configurations.h deleted file mode 100644 index be993ed..0000000 --- a/include/webrtc/engine_configurations.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_ENGINE_CONFIGURATIONS_H_ -#define WEBRTC_ENGINE_CONFIGURATIONS_H_ - -#include "webrtc/typedefs.h" - -// ============================================================================ -// VoiceEngine -// ============================================================================ - -// ---------------------------------------------------------------------------- -// Settings for VoiceEngine -// ---------------------------------------------------------------------------- - -#define WEBRTC_VOICE_ENGINE_AGC // Near-end AGC -#define WEBRTC_VOICE_ENGINE_ECHO // Near-end AEC -#define WEBRTC_VOICE_ENGINE_NR // Near-end NS - -#if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS) -#define WEBRTC_VOICE_ENGINE_TYPING_DETECTION // Typing detection -#endif - -// ---------------------------------------------------------------------------- -// VoiceEngine sub-APIs -// ---------------------------------------------------------------------------- - -#define WEBRTC_VOICE_ENGINE_AUDIO_PROCESSING_API -#define WEBRTC_VOICE_ENGINE_CODEC_API -#define WEBRTC_VOICE_ENGINE_EXTERNAL_MEDIA_API -#define WEBRTC_VOICE_ENGINE_FILE_API -#define WEBRTC_VOICE_ENGINE_HARDWARE_API -#define WEBRTC_VOICE_ENGINE_NETEQ_STATS_API -#define WEBRTC_VOICE_ENGINE_RTP_RTCP_API -#define WEBRTC_VOICE_ENGINE_VIDEO_SYNC_API -#define WEBRTC_VOICE_ENGINE_VOLUME_CONTROL_API - -// ============================================================================ -// Platform specific configurations -// ============================================================================ - -// ---------------------------------------------------------------------------- -// VideoEngine Windows -// ---------------------------------------------------------------------------- - -#if defined(_WIN32) -#define DIRECT3D9_RENDERING // Requires DirectX 9. -#endif - -// ---------------------------------------------------------------------------- -// VideoEngine MAC -// ---------------------------------------------------------------------------- - -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -// #define CARBON_RENDERING -#define COCOA_RENDERING -#endif - -// ---------------------------------------------------------------------------- -// VideoEngine Mobile iPhone -// ---------------------------------------------------------------------------- - -#if defined(WEBRTC_IOS) -#define EAGL_RENDERING -#endif - -#endif // WEBRTC_ENGINE_CONFIGURATIONS_H_ diff --git a/include/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h b/include/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h new file mode 100644 index 0000000..fcc5700 --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_MOCK_MOCK_RTC_EVENT_LOG_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_MOCK_MOCK_RTC_EVENT_LOG_H_ + +#include + +#include "webrtc/logging/rtc_event_log/rtc_event_log.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRtcEventLog : public RtcEventLog { + public: + MOCK_METHOD2(StartLogging, + bool(const std::string& file_name, int64_t max_size_bytes)); + + MOCK_METHOD2(StartLogging, + bool(rtc::PlatformFile log_file, int64_t max_size_bytes)); + + MOCK_METHOD0(StopLogging, void()); + + MOCK_METHOD1(LogVideoReceiveStreamConfig, + void(const webrtc::VideoReceiveStream::Config& config)); + + MOCK_METHOD1(LogVideoSendStreamConfig, + void(const webrtc::VideoSendStream::Config& config)); + + MOCK_METHOD1(LogAudioReceiveStreamConfig, + void(const webrtc::AudioReceiveStream::Config& config)); + + MOCK_METHOD1(LogAudioSendStreamConfig, + void(const webrtc::AudioSendStream::Config& config)); + + MOCK_METHOD4(LogRtpHeader, + void(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length)); + + MOCK_METHOD5(LogRtpHeader, + void(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length, + int probe_cluster_id)); + + MOCK_METHOD4(LogRtcpPacket, + void(PacketDirection direction, + MediaType media_type, + const uint8_t* packet, + size_t length)); + + MOCK_METHOD1(LogAudioPlayout, void(uint32_t ssrc)); + + MOCK_METHOD3(LogLossBasedBweUpdate, + void(int32_t bitrate_bps, + uint8_t fraction_loss, + int32_t total_packets)); + + MOCK_METHOD2(LogDelayBasedBweUpdate, + void(int32_t bitrate_bps, BandwidthUsage detector_state)); + + MOCK_METHOD1(LogAudioNetworkAdaptation, + void(const AudioNetworkAdaptor::EncoderRuntimeConfig& config)); + + MOCK_METHOD4(LogProbeClusterCreated, + void(int id, int bitrate_bps, int min_probes, int min_bytes)); + + MOCK_METHOD2(LogProbeResultSuccess, void(int id, int bitrate_bps)); + MOCK_METHOD2(LogProbeResultFailure, + void(int id, ProbeFailureReason failure_reason)); +}; + +} // namespace webrtc + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_MOCK_MOCK_RTC_EVENT_LOG_H_ diff --git a/include/webrtc/logging/rtc_event_log/ringbuffer.h b/include/webrtc/logging/rtc_event_log/ringbuffer.h new file mode 100644 index 0000000..6c0ffda --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/ringbuffer.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RINGBUFFER_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_RINGBUFFER_H_ + +#include +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +// A RingBuffer works like a fixed size queue which starts discarding +// the oldest elements when it becomes full. +template +class RingBuffer { + public: + // Creates a RingBuffer with space for |capacity| elements. + explicit RingBuffer(size_t capacity) + : // We allocate space for one extra sentinel element. + data_(new T[capacity + 1]) { + RTC_DCHECK(capacity > 0); + end_ = data_.get() + (capacity + 1); + front_ = data_.get(); + back_ = data_.get(); + } + + ~RingBuffer() { + // The unique_ptr will free the memory. + } + + // Removes an element from the front of the queue. + void pop_front() { + RTC_DCHECK(!empty()); + ++front_; + if (front_ == end_) { + front_ = data_.get(); + } + } + + // Appends an element to the back of the queue (and removes an + // element from the front if there is no space at the back of the queue). + void push_back(const T& elem) { + *back_ = elem; + ++back_; + if (back_ == end_) { + back_ = data_.get(); + } + if (back_ == front_) { + ++front_; + } + if (front_ == end_) { + front_ = data_.get(); + } + } + + // Appends an element to the back of the queue (and removes an + // element from the front if there is no space at the back of the queue). + void push_back(T&& elem) { + *back_ = std::move(elem); + ++back_; + if (back_ == end_) { + back_ = data_.get(); + } + if (back_ == front_) { + ++front_; + } + if (front_ == end_) { + front_ = data_.get(); + } + } + + T& front() { return *front_; } + + const T& front() const { return *front_; } + + bool empty() const { return (front_ == back_); } + + private: + std::unique_ptr data_; + T* end_; + T* front_; + T* back_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer); +}; + +} // namespace webrtc + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_RINGBUFFER_H_ diff --git a/include/webrtc/logging/rtc_event_log/rtc_event_log.h b/include/webrtc/logging/rtc_event_log/rtc_event_log.h new file mode 100644 index 0000000..ccb37b3 --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/rtc_event_log.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ + +#include +#include + +#include "webrtc/base/platform_file.h" +#include "webrtc/call/audio_receive_stream.h" +#include "webrtc/call/audio_send_stream.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" +#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" +#include "webrtc/video_receive_stream.h" +#include "webrtc/video_send_stream.h" + +namespace webrtc { + +// Forward declaration of storage class that is automatically generated from +// the protobuf file. +namespace rtclog { +class EventStream; +} // namespace rtclog + +class Clock; +class RtcEventLogImpl; + +enum class MediaType; + +enum PacketDirection { kIncomingPacket = 0, kOutgoingPacket }; +enum ProbeFailureReason { + kInvalidSendReceiveInterval, + kInvalidSendReceiveRatio, + kTimeout +}; + +class RtcEventLog { + public: + virtual ~RtcEventLog() {} + + // Factory method to create an RtcEventLog object. + static std::unique_ptr Create(); + // TODO(nisse): webrtc::Clock is deprecated. Delete this method and + // above forward declaration of Clock when + // webrtc/system_wrappers/include/clock.h is deleted. + static std::unique_ptr Create(const Clock* clock) { + return Create(); + } + + // Create an RtcEventLog object that does nothing. + static std::unique_ptr CreateNull(); + + // Starts logging a maximum of max_size_bytes bytes to the specified file. + // If the file already exists it will be overwritten. + // If max_size_bytes <= 0, logging will be active until StopLogging is called. + // The function has no effect and returns false if we can't start a new log + // e.g. because we are already logging or the file cannot be opened. + virtual bool StartLogging(const std::string& file_name, + int64_t max_size_bytes) = 0; + + // Same as above. The RtcEventLog takes ownership of the file if the call + // is successful, i.e. if it returns true. + virtual bool StartLogging(rtc::PlatformFile platform_file, + int64_t max_size_bytes) = 0; + + // Deprecated. Pass an explicit file size limit. + bool StartLogging(const std::string& file_name) { + return StartLogging(file_name, 10000000); + } + + // Deprecated. Pass an explicit file size limit. + bool StartLogging(rtc::PlatformFile platform_file) { + return StartLogging(platform_file, 10000000); + } + + // Stops logging to file and waits until the thread has finished. + virtual void StopLogging() = 0; + + // Logs configuration information for webrtc::VideoReceiveStream. + virtual void LogVideoReceiveStreamConfig( + const webrtc::VideoReceiveStream::Config& config) = 0; + + // Logs configuration information for webrtc::VideoSendStream. + virtual void LogVideoSendStreamConfig( + const webrtc::VideoSendStream::Config& config) = 0; + + // Logs configuration information for webrtc::AudioReceiveStream. + virtual void LogAudioReceiveStreamConfig( + const webrtc::AudioReceiveStream::Config& config) = 0; + + // Logs configuration information for webrtc::AudioSendStream. + virtual void LogAudioSendStreamConfig( + const webrtc::AudioSendStream::Config& config) = 0; + + // Logs the header of an incoming or outgoing RTP packet. packet_length + // is the total length of the packet, including both header and payload. + virtual void LogRtpHeader(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length) = 0; + + // Same as above but used on the sender side to log packets that are part of + // a probe cluster. + virtual void LogRtpHeader(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length, + int probe_cluster_id) = 0; + + // Logs an incoming or outgoing RTCP packet. + virtual void LogRtcpPacket(PacketDirection direction, + MediaType media_type, + const uint8_t* packet, + size_t length) = 0; + + // Logs an audio playout event. + virtual void LogAudioPlayout(uint32_t ssrc) = 0; + + // Logs a bitrate update from the bandwidth estimator based on packet loss. + virtual void LogLossBasedBweUpdate(int32_t bitrate_bps, + uint8_t fraction_loss, + int32_t total_packets) = 0; + + // Logs a bitrate update from the bandwidth estimator based on delay changes. + virtual void LogDelayBasedBweUpdate(int32_t bitrate_bps, + BandwidthUsage detector_state) = 0; + + // Logs audio encoder re-configuration driven by audio network adaptor. + virtual void LogAudioNetworkAdaptation( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config) = 0; + + // Logs when a probe cluster is created. + virtual void LogProbeClusterCreated(int id, + int bitrate_bps, + int min_probes, + int min_bytes) = 0; + + // Logs the result of a successful probing attempt. + virtual void LogProbeResultSuccess(int id, int bitrate_bps) = 0; + + // Logs the result of an unsuccessful probing attempt. + virtual void LogProbeResultFailure(int id, + ProbeFailureReason failure_reason) = 0; + + // Reads an RtcEventLog file and returns true when reading was successful. + // The result is stored in the given EventStream object. + // The order of the events in the EventStream is implementation defined. + // The current implementation writes a LOG_START event, then the old + // configurations, then the remaining events in timestamp order and finally + // a LOG_END event. However, this might change without further notice. + // TODO(terelius): Change result type to a vector? + static bool ParseRtcEventLog(const std::string& file_name, + rtclog::EventStream* result); +}; + +// No-op implementation is used if flag is not set, or in tests. +class RtcEventLogNullImpl final : public RtcEventLog { + public: + bool StartLogging(const std::string& file_name, + int64_t max_size_bytes) override { + return false; + } + bool StartLogging(rtc::PlatformFile platform_file, + int64_t max_size_bytes) override; + void StopLogging() override {} + void LogVideoReceiveStreamConfig( + const VideoReceiveStream::Config& config) override {} + void LogVideoSendStreamConfig( + const VideoSendStream::Config& config) override {} + void LogAudioReceiveStreamConfig( + const AudioReceiveStream::Config& config) override {} + void LogAudioSendStreamConfig( + const AudioSendStream::Config& config) override {} + void LogRtpHeader(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length) override {} + void LogRtpHeader(PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t packet_length, + int probe_cluster_id) override {} + void LogRtcpPacket(PacketDirection direction, + MediaType media_type, + const uint8_t* packet, + size_t length) override {} + void LogAudioPlayout(uint32_t ssrc) override {} + void LogLossBasedBweUpdate(int32_t bitrate_bps, + uint8_t fraction_loss, + int32_t total_packets) override {} + void LogDelayBasedBweUpdate(int32_t bitrate_bps, + BandwidthUsage detector_state) override {} + void LogAudioNetworkAdaptation( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override {} + void LogProbeClusterCreated(int id, + int bitrate_bps, + int min_probes, + int min_bytes) override{}; + void LogProbeResultSuccess(int id, int bitrate_bps) override{}; + void LogProbeResultFailure(int id, + ProbeFailureReason failure_reason) override{}; +}; + +} // namespace webrtc + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_H_ diff --git a/include/webrtc/logging/rtc_event_log/rtc_event_log_helper_thread.h b/include/webrtc/logging/rtc_event_log/rtc_event_log_helper_thread.h new file mode 100644 index 0000000..420e5c5 --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/rtc_event_log_helper_thread.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_HELPER_THREAD_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_HELPER_THREAD_H_ + +#include +#include +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/event.h" +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/platform_thread.h" +#include "webrtc/base/swap_queue.h" +#include "webrtc/logging/rtc_event_log/ringbuffer.h" +#include "webrtc/system_wrappers/include/file_wrapper.h" + +#ifdef ENABLE_RTC_EVENT_LOG +// Files generated at build-time by the protobuf compiler. +RTC_PUSH_IGNORING_WUNDEF() +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h" +#else +#include "webrtc/logging/rtc_event_log/rtc_event_log.pb.h" +#endif +RTC_POP_IGNORING_WUNDEF() +#endif + +#ifdef ENABLE_RTC_EVENT_LOG + +namespace webrtc { + +class RtcEventLogHelperThread final { + public: + struct ControlMessage { + ControlMessage() + : message_type(STOP_FILE), + file(nullptr), + max_size_bytes(0), + start_time(0), + stop_time(0) {} + enum { START_FILE, STOP_FILE, TERMINATE_THREAD } message_type; + + std::unique_ptr file; // Only used with START_FILE. + int64_t max_size_bytes; // Only used with START_FILE. + int64_t start_time; // Only used with START_FILE. + int64_t stop_time; // Used with all 3 message types. + + friend void swap(ControlMessage& lhs, ControlMessage& rhs) { + using std::swap; + swap(lhs.message_type, rhs.message_type); + lhs.file.swap(rhs.file); + swap(lhs.max_size_bytes, rhs.max_size_bytes); + swap(lhs.start_time, rhs.start_time); + swap(lhs.stop_time, rhs.stop_time); + } + }; + + RtcEventLogHelperThread( + SwapQueue* message_queue, + SwapQueue>* event_queue); + ~RtcEventLogHelperThread(); + + // This function MUST be called once a STOP_FILE message is added to the + // signalling queue. The function will make sure that the output thread + // wakes up to read the message, and it blocks until the output thread has + // finished writing to the file. + void WaitForFileFinished(); + + // This fuction MUST be called once an event is added to the event queue. + void SignalNewEvent(); + + private: + static void ThreadOutputFunction(void* obj); + + bool AppendEventToString(rtclog::Event* event); + bool LogToMemory(); + void StartLogFile(); + bool LogToFile(); + void StopLogFile(); + void ProcessEvents(); + + // Message queues for passing events to the logging thread. + SwapQueue* message_queue_; + SwapQueue>* event_queue_; + + // History containing the most recent events (~ 10 s). + RingBuffer> history_; + + // History containing all past configuration events. + std::vector> config_history_; + + std::unique_ptr file_; + rtc::PlatformThread thread_; + + int64_t max_size_bytes_; + int64_t written_bytes_; + int64_t start_time_; + int64_t stop_time_; + + bool has_recent_event_; + std::unique_ptr most_recent_event_; + + // Temporary space for serializing profobuf data. + std::string output_string_; + + rtc::Event wake_periodically_; + rtc::Event wake_from_hibernation_; + rtc::Event file_finished_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtcEventLogHelperThread); +}; + +} // namespace webrtc + +#endif // ENABLE_RTC_EVENT_LOG + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_HELPER_THREAD_H_ diff --git a/include/webrtc/logging/rtc_event_log/rtc_event_log_parser.h b/include/webrtc/logging/rtc_event_log/rtc_event_log_parser.h new file mode 100644 index 0000000..1460a4c --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/rtc_event_log_parser.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ + +#include +#include + +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/logging/rtc_event_log/rtc_event_log.h" +#include "webrtc/video_receive_stream.h" +#include "webrtc/video_send_stream.h" + +// Files generated at build-time by the protobuf compiler. +RTC_PUSH_IGNORING_WUNDEF() +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/logging/rtc_event_log/rtc_event_log.pb.h" +#else +#include "webrtc/logging/rtc_event_log/rtc_event_log.pb.h" +#endif +RTC_POP_IGNORING_WUNDEF() + +namespace webrtc { + +enum class MediaType; + +class ParsedRtcEventLog { + friend class RtcEventLogTestHelper; + + public: + enum EventType { + UNKNOWN_EVENT = 0, + LOG_START = 1, + LOG_END = 2, + RTP_EVENT = 3, + RTCP_EVENT = 4, + AUDIO_PLAYOUT_EVENT = 5, + LOSS_BASED_BWE_UPDATE = 6, + DELAY_BASED_BWE_UPDATE = 7, + VIDEO_RECEIVER_CONFIG_EVENT = 8, + VIDEO_SENDER_CONFIG_EVENT = 9, + AUDIO_RECEIVER_CONFIG_EVENT = 10, + AUDIO_SENDER_CONFIG_EVENT = 11, + AUDIO_NETWORK_ADAPTATION_EVENT = 16, + BWE_PROBE_CLUSTER_CREATED_EVENT = 17, + BWE_PROBE_RESULT_EVENT = 18 + }; + + // Reads an RtcEventLog file and returns true if parsing was successful. + bool ParseFile(const std::string& file_name); + + // Reads an RtcEventLog from a string and returns true if successful. + bool ParseString(const std::string& s); + + // Reads an RtcEventLog from an istream and returns true if successful. + bool ParseStream(std::istream& stream); + + // Returns the number of events in an EventStream. + size_t GetNumberOfEvents() const; + + // Reads the arrival timestamp (in microseconds) from a rtclog::Event. + int64_t GetTimestamp(size_t index) const; + + // Reads the event type of the rtclog::Event at |index|. + EventType GetEventType(size_t index) const; + + // Reads the header, direction, media type, header length and packet length + // from the RTP event at |index|, and stores the values in the corresponding + // output parameters. Each output parameter can be set to nullptr if that + // value isn't needed. + // NB: The header must have space for at least IP_PACKET_SIZE bytes. + void GetRtpHeader(size_t index, + PacketDirection* incoming, + MediaType* media_type, + uint8_t* header, + size_t* header_length, + size_t* total_length) const; + + // Reads packet, direction, media type and packet length from the RTCP event + // at |index|, and stores the values in the corresponding output parameters. + // Each output parameter can be set to nullptr if that value isn't needed. + // NB: The packet must have space for at least IP_PACKET_SIZE bytes. + void GetRtcpPacket(size_t index, + PacketDirection* incoming, + MediaType* media_type, + uint8_t* packet, + size_t* length) const; + + // Reads a config event to a (non-NULL) VideoReceiveStream::Config struct. + // Only the fields that are stored in the protobuf will be written. + void GetVideoReceiveConfig(size_t index, + VideoReceiveStream::Config* config) const; + + // Reads a config event to a (non-NULL) VideoSendStream::Config struct. + // Only the fields that are stored in the protobuf will be written. + void GetVideoSendConfig(size_t index, VideoSendStream::Config* config) const; + + // Reads a config event to a (non-NULL) AudioReceiveStream::Config struct. + // Only the fields that are stored in the protobuf will be written. + void GetAudioReceiveConfig(size_t index, + AudioReceiveStream::Config* config) const; + + // Reads a config event to a (non-NULL) AudioSendStream::Config struct. + // Only the fields that are stored in the protobuf will be written. + void GetAudioSendConfig(size_t index, AudioSendStream::Config* config) const; + + // Reads the SSRC from the audio playout event at |index|. The SSRC is stored + // in the output parameter ssrc. The output parameter can be set to nullptr + // and in that case the function only asserts that the event is well formed. + void GetAudioPlayout(size_t index, uint32_t* ssrc) const; + + // Reads bitrate, fraction loss (as defined in RFC 1889) and total number of + // expected packets from the loss based BWE event at |index| and stores the + // values in + // the corresponding output parameters. Each output parameter can be set to + // nullptr if that + // value isn't needed. + void GetLossBasedBweUpdate(size_t index, + int32_t* bitrate_bps, + uint8_t* fraction_loss, + int32_t* total_packets) const; + + // Reads bitrate and detector_state from the delay based BWE event at |index| + // and stores the values in the corresponding output parameters. Each output + // parameter can be set to nullptr if that + // value isn't needed. + void GetDelayBasedBweUpdate(size_t index, + int32_t* bitrate_bps, + BandwidthUsage* detector_state) const; + + // Reads a audio network adaptation event to a (non-NULL) + // AudioNetworkAdaptor::EncoderRuntimeConfig struct. Only the fields that are + // stored in the protobuf will be written. + void GetAudioNetworkAdaptation( + size_t index, + AudioNetworkAdaptor::EncoderRuntimeConfig* config) const; + + private: + std::vector events_; +}; + +} // namespace webrtc + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_PARSER_H_ diff --git a/include/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/include/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h new file mode 100644 index 0000000..0ca2d62 --- /dev/null +++ b/include/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_UNITTEST_HELPER_H_ +#define WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_UNITTEST_HELPER_H_ + +#include "webrtc/call/call.h" +#include "webrtc/logging/rtc_event_log/rtc_event_log_parser.h" + +namespace webrtc { + +class RtcEventLogTestHelper { + public: + static void VerifyVideoReceiveStreamConfig( + const ParsedRtcEventLog& parsed_log, + size_t index, + const VideoReceiveStream::Config& config); + static void VerifyVideoSendStreamConfig( + const ParsedRtcEventLog& parsed_log, + size_t index, + const VideoSendStream::Config& config); + static void VerifyAudioReceiveStreamConfig( + const ParsedRtcEventLog& parsed_log, + size_t index, + const AudioReceiveStream::Config& config); + static void VerifyAudioSendStreamConfig( + const ParsedRtcEventLog& parsed_log, + size_t index, + const AudioSendStream::Config& config); + static void VerifyRtpEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + PacketDirection direction, + MediaType media_type, + const uint8_t* header, + size_t header_size, + size_t total_size); + static void VerifyRtcpEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + PacketDirection direction, + MediaType media_type, + const uint8_t* packet, + size_t total_size); + static void VerifyPlayoutEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + uint32_t ssrc); + static void VerifyBweLossEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + int32_t bitrate, + uint8_t fraction_loss, + int32_t total_packets); + static void VerifyBweDelayEvent(const ParsedRtcEventLog& parsed_log, + size_t index, + int32_t bitrate, + BandwidthUsage detector_state); + + static void VerifyAudioNetworkAdaptation( + const ParsedRtcEventLog& parsed_log, + size_t index, + const AudioNetworkAdaptor::EncoderRuntimeConfig& config); + + static void VerifyLogStartEvent(const ParsedRtcEventLog& parsed_log, + size_t index); + static void VerifyLogEndEvent(const ParsedRtcEventLog& parsed_log, + size_t index); + + static void VerifyBweProbeCluster(const ParsedRtcEventLog& parsed_log, + size_t index, + uint32_t id, + uint32_t bitrate_bps, + uint32_t min_probes, + uint32_t min_bytes); + + static void VerifyProbeResultSuccess(const ParsedRtcEventLog& parsed_log, + size_t index, + uint32_t id, + uint32_t bitrate_bps); + + static void VerifyProbeResultFailure(const ParsedRtcEventLog& parsed_log, + size_t index, + uint32_t id, + ProbeFailureReason failure_reason); +}; + +} // namespace webrtc + +#endif // WEBRTC_LOGGING_RTC_EVENT_LOG_RTC_EVENT_LOG_UNITTEST_HELPER_H_ diff --git a/include/webrtc/media/base/adaptedvideotracksource.h b/include/webrtc/media/base/adaptedvideotracksource.h new file mode 100644 index 0000000..9d51c69 --- /dev/null +++ b/include/webrtc/media/base/adaptedvideotracksource.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_BASE_ADAPTEDVIDEOTRACKSOURCE_H_ +#define WEBRTC_MEDIA_BASE_ADAPTEDVIDEOTRACKSOURCE_H_ + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/notifier.h" +#include "webrtc/media/base/videoadapter.h" +#include "webrtc/media/base/videobroadcaster.h" + +namespace rtc { + +// Base class for sources which needs video adaptation, e.g., video +// capture sources. Sinks must be added and removed on one and only +// one thread, while AdaptFrame and OnFrame may be called on any +// thread. +class AdaptedVideoTrackSource + : public webrtc::Notifier { + public: + AdaptedVideoTrackSource(); + + protected: + // Allows derived classes to initialize |video_adapter_| with a custom + // alignment. + AdaptedVideoTrackSource(int required_alignment); + // Checks the apply_rotation() flag. If the frame needs rotation, and it is a + // plain memory frame, it is rotated. Subclasses producing native frames must + // handle apply_rotation() themselves. + void OnFrame(const webrtc::VideoFrame& frame); + + // Reports the appropriate frame size after adaptation. Returns true + // if a frame is wanted. Returns false if there are no interested + // sinks, or if the VideoAdapter decides to drop the frame. + bool AdaptFrame(int width, + int height, + int64_t time_us, + int* out_width, + int* out_height, + int* crop_width, + int* crop_height, + int* crop_x, + int* crop_y); + + // Returns the current value of the apply_rotation flag, derived + // from the VideoSinkWants of registered sinks. The value is derived + // from sinks' wants, in AddOrUpdateSink and RemoveSink. Beware that + // when using this method from a different thread, the value may + // become stale before it is used. + bool apply_rotation(); + + cricket::VideoAdapter* video_adapter() { return &video_adapter_; } + + private: + // Implements rtc::VideoSourceInterface. + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; + + // Part of VideoTrackSourceInterface. + bool GetStats(Stats* stats) override; + + void OnSinkWantsChanged(const rtc::VideoSinkWants& wants); + + rtc::ThreadChecker thread_checker_; + + cricket::VideoAdapter video_adapter_; + + rtc::CriticalSection stats_crit_; + rtc::Optional stats_ GUARDED_BY(stats_crit_); + + VideoBroadcaster broadcaster_; +}; + +} // namespace rtc + +#endif // WEBRTC_MEDIA_BASE_ADAPTEDVIDEOTRACKSOURCE_H_ diff --git a/include/webrtc/media/base/audiorenderer.h b/include/webrtc/media/base/audiorenderer.h deleted file mode 100644 index b611bc4..0000000 --- a/include/webrtc/media/base/audiorenderer.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_AUDIORENDERER_H_ -#define WEBRTC_MEDIA_BASE_AUDIORENDERER_H_ - -// TODO(deadbeef): Remove this once not included by Chromium. - -#endif // WEBRTC_MEDIA_BASE_AUDIORENDERER_H_ diff --git a/include/webrtc/media/base/codec.h b/include/webrtc/media/base/codec.h index 76a623a..5e49785 100644 --- a/include/webrtc/media/base/codec.h +++ b/include/webrtc/media/base/codec.h @@ -17,16 +17,16 @@ #include #include "webrtc/api/rtpparameters.h" +#include "webrtc/common_types.h" #include "webrtc/media/base/mediaconstants.h" namespace cricket { typedef std::map CodecParameterMap; -extern const int kMaxPayloadId; - class FeedbackParam { public: + FeedbackParam() = default; FeedbackParam(const std::string& id, const std::string& param) : id_(id), param_(param) { @@ -68,11 +68,6 @@ struct Codec { CodecParameterMap params; FeedbackParams feedback_params; - // Creates a codec with the given parameters. - Codec(int id, const std::string& name, int clockrate); - // Creates an empty codec. - Codec(); - Codec(const Codec& c); virtual ~Codec(); // Indicates if this codec is compatible with the specified codec. @@ -99,12 +94,22 @@ struct Codec { virtual webrtc::RtpCodecParameters ToCodecParameters() const; Codec& operator=(const Codec& c); + Codec& operator=(Codec&& c); bool operator==(const Codec& c) const; bool operator!=(const Codec& c) const { return !(*this == c); } + + protected: + // A Codec can't be created without a subclass. + // Creates a codec with the given parameters. + Codec(int id, const std::string& name, int clockrate); + // Creates an empty codec. + Codec(); + Codec(const Codec& c); + Codec(Codec&& c); }; struct AudioCodec : public Codec { @@ -120,6 +125,7 @@ struct AudioCodec : public Codec { // Creates an empty codec. AudioCodec(); AudioCodec(const AudioCodec& c); + AudioCodec(AudioCodec&& c); virtual ~AudioCodec() = default; // Indicates if this codec is compatible with the specified codec. @@ -130,6 +136,7 @@ struct AudioCodec : public Codec { webrtc::RtpCodecParameters ToCodecParameters() const override; AudioCodec& operator=(const AudioCodec& c); + AudioCodec& operator=(AudioCodec&& c); bool operator==(const AudioCodec& c) const; @@ -138,26 +145,50 @@ struct AudioCodec : public Codec { } }; -struct VideoCodec : public Codec { - int width; - int height; - int framerate; +inline std::ostream& operator<<(std::ostream& os, const AudioCodec& ac) { + os << "{id: " << ac.id; + os << ", name: " << ac.name; + os << ", clockrate: " << ac.clockrate; + os << ", bitrate: " << ac.bitrate; + os << ", channels: " << ac.channels; + os << ", params: {"; + const char* sep = ""; + for (const auto& kv : ac.params) { + os << sep << kv.first << ": " << kv.second; + sep = ", "; + } + os << "}, feedback_params: {"; + sep = ""; + for (const FeedbackParam& fp : ac.feedback_params.params()) { + os << sep << fp.id() << ": " << fp.param(); + sep = ", "; + } + os << "}}"; + return os; +} +struct VideoCodec : public Codec { // Creates a codec with the given parameters. - VideoCodec(int id, - const std::string& name, - int width, - int height, - int framerate); VideoCodec(int id, const std::string& name); + // Creates a codec with the given name and empty id. + explicit VideoCodec(const std::string& name); // Creates an empty codec. VideoCodec(); VideoCodec(const VideoCodec& c); + VideoCodec(VideoCodec&& c); virtual ~VideoCodec() = default; + // Indicates if this video codec is the same as the other video codec, e.g. if + // they are both VP8 or VP9, or if they are both H264 with the same H264 + // profile. H264 levels however are not compared. + bool Matches(const VideoCodec& codec) const; + std::string ToString() const; + webrtc::RtpCodecParameters ToCodecParameters() const override; + VideoCodec& operator=(const VideoCodec& c); + VideoCodec& operator=(VideoCodec&& c); bool operator==(const VideoCodec& c) const; @@ -172,6 +203,7 @@ struct VideoCodec : public Codec { CODEC_VIDEO, CODEC_RED, CODEC_ULPFEC, + CODEC_FLEXFEC, CODEC_RTX, }; @@ -180,38 +212,45 @@ struct VideoCodec : public Codec { // don't make sense (such as max < min bitrate), and error is logged and // ValidateCodecFormat returns false. bool ValidateCodecFormat() const; + + private: + void SetDefaultParameters(); }; struct DataCodec : public Codec { DataCodec(int id, const std::string& name); DataCodec(); DataCodec(const DataCodec& c); + DataCodec(DataCodec&& c); virtual ~DataCodec() = default; DataCodec& operator=(const DataCodec& c); + DataCodec& operator=(DataCodec&& c); std::string ToString() const; }; // Get the codec setting associated with |payload_type|. If there -// is no codec associated with that payload type it returns false. +// is no codec associated with that payload type it returns nullptr. template -bool FindCodecById(const std::vector& codecs, - int payload_type, - Codec* codec_out) { +const Codec* FindCodecById(const std::vector& codecs, int payload_type) { for (const auto& codec : codecs) { - if (codec.id == payload_type) { - *codec_out = codec; - return true; - } + if (codec.id == payload_type) + return &codec; } - return false; + return nullptr; } bool CodecNamesEq(const std::string& name1, const std::string& name2); +bool CodecNamesEq(const char* name1, const char* name2); bool HasNack(const Codec& codec); bool HasRemb(const Codec& codec); bool HasTransportCc(const Codec& codec); +// Returns the first codec in |supported_codecs| that matches |codec|, or +// nullptr if no codec matches. +const VideoCodec* FindMatchingCodec( + const std::vector& supported_codecs, + const VideoCodec& codec); } // namespace cricket diff --git a/include/webrtc/media/base/cpuid.h b/include/webrtc/media/base/cpuid.h deleted file mode 100644 index 4cc0dcb..0000000 --- a/include/webrtc/media/base/cpuid.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_CPUID_H_ -#define WEBRTC_MEDIA_BASE_CPUID_H_ - -#include "webrtc/base/constructormagic.h" - -namespace cricket { - -class CpuInfo { - public: - // The following flags must match libyuv/cpu_id.h values. - // Internal flag to indicate cpuid requires initialization. - static const int kCpuInit = 0x1; - - // These flags are only valid on ARM processors. - static const int kCpuHasARM = 0x2; - static const int kCpuHasNEON = 0x4; - // 0x8 reserved for future ARM flag. - - // These flags are only valid on x86 processors. - static const int kCpuHasX86 = 0x10; - static const int kCpuHasSSE2 = 0x20; - static const int kCpuHasSSSE3 = 0x40; - static const int kCpuHasSSE41 = 0x80; - static const int kCpuHasSSE42 = 0x100; - static const int kCpuHasAVX = 0x200; - static const int kCpuHasAVX2 = 0x400; - static const int kCpuHasERMS = 0x800; - - // These flags are only valid on MIPS processors. - static const int kCpuHasMIPS = 0x1000; - static const int kCpuHasMIPS_DSP = 0x2000; - static const int kCpuHasMIPS_DSPR2 = 0x4000; - - // Detect CPU has SSE2 etc. - static bool TestCpuFlag(int flag); - - // For testing, allow CPU flags to be disabled. - static void MaskCpuFlagsForTest(int enable_flags); - - private: - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CpuInfo); -}; - -// Detect an Intel Core I5 or better such as 4th generation Macbook Air. -bool IsCoreIOrBetter(); - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_CPUID_H_ diff --git a/include/webrtc/media/base/executablehelpers.h b/include/webrtc/media/base/executablehelpers.h deleted file mode 100644 index 25ce41b..0000000 --- a/include/webrtc/media/base/executablehelpers.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ -#define WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ - -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -#include -#endif - -#include - -#include "webrtc/base/logging.h" -#include "webrtc/base/pathutils.h" - -namespace rtc { - -// Returns the path to the running executable or an empty path. -// TODO(thorcarpenter): Consolidate with FluteClient::get_executable_dir. -inline Pathname GetExecutablePath() { - const int32_t kMaxExePathSize = 255; -#ifdef WIN32 - TCHAR exe_path_buffer[kMaxExePathSize]; - DWORD copied_length = GetModuleFileName(NULL, // NULL = Current process - exe_path_buffer, kMaxExePathSize); - if (0 == copied_length) { - LOG(LS_ERROR) << "Copied length is zero"; - return rtc::Pathname(); - } - if (kMaxExePathSize == copied_length) { - LOG(LS_ERROR) << "Buffer too small"; - return rtc::Pathname(); - } -#ifdef UNICODE - std::wstring wdir(exe_path_buffer); - std::string dir_tmp(wdir.begin(), wdir.end()); - rtc::Pathname path(dir_tmp); -#else // UNICODE - rtc::Pathname path(exe_path_buffer); -#endif // UNICODE -#elif (defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)) || defined(WEBRTC_LINUX) - char exe_path_buffer[kMaxExePathSize]; -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) - uint32_t copied_length = kMaxExePathSize - 1; - if (_NSGetExecutablePath(exe_path_buffer, &copied_length) == -1) { - LOG(LS_ERROR) << "Buffer too small"; - return rtc::Pathname(); - } -#elif defined WEBRTC_LINUX - int32_t copied_length = kMaxExePathSize - 1; - const char* kProcExeFmt = "/proc/%d/exe"; - char proc_exe_link[40]; - snprintf(proc_exe_link, sizeof(proc_exe_link), kProcExeFmt, getpid()); - copied_length = readlink(proc_exe_link, exe_path_buffer, copied_length); - if (copied_length == -1) { - LOG_ERR(LS_ERROR) << "Error reading link " << proc_exe_link; - return rtc::Pathname(); - } - if (copied_length == kMaxExePathSize - 1) { - LOG(LS_ERROR) << "Probably truncated result when reading link " - << proc_exe_link; - return rtc::Pathname(); - } - exe_path_buffer[copied_length] = '\0'; -#endif // WEBRTC_LINUX - rtc::Pathname path(exe_path_buffer); -#else // Android || iOS - rtc::Pathname path; -#endif // Mac || Linux - return path; -} - -} // namespace rtc - -#endif // WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ - diff --git a/include/webrtc/media/base/fakemediaengine.h b/include/webrtc/media/base/fakemediaengine.h index bde5843..fc59fa7 100644 --- a/include/webrtc/media/base/fakemediaengine.h +++ b/include/webrtc/media/base/fakemediaengine.h @@ -18,7 +18,8 @@ #include #include -#include "webrtc/audio_sink.h" +#include "webrtc/api/call/audio_sink.h" +#include "webrtc/base/checks.h" #include "webrtc/base/copyonwritebuffer.h" #include "webrtc/base/networkroute.h" #include "webrtc/base/stringutils.h" @@ -28,6 +29,8 @@ #include "webrtc/media/base/streamparams.h" #include "webrtc/p2p/base/sessiondescription.h" +using webrtc::RtpExtension; + namespace cricket { class FakeMediaEngine; @@ -44,10 +47,10 @@ template class RtpHelper : public Base { fail_set_recv_codecs_(false), send_ssrc_(0), ready_to_send_(false) {} - const std::vector& recv_extensions() { + const std::vector& recv_extensions() { return recv_extensions_; } - const std::vector& send_extensions() { + const std::vector& send_extensions() { return send_extensions_; } bool sending() const { return sending_; } @@ -203,11 +206,17 @@ template class RtpHelper : public Base { return ""; return send_streams_[0].cname; } + const RtcpParameters& send_rtcp_parameters() { return send_rtcp_parameters_; } + const RtcpParameters& recv_rtcp_parameters() { return recv_rtcp_parameters_; } bool ready_to_send() const { return ready_to_send_; } + int transport_overhead_per_packet() const { + return transport_overhead_per_packet_; + } + rtc::NetworkRoute last_network_route() const { return last_network_route_; } int num_network_route_changes() const { return num_network_route_changes_; } void set_num_network_route_changes(int changes) { @@ -231,16 +240,20 @@ template class RtpHelper : public Base { return true; } void set_playout(bool playout) { playout_ = playout; } - bool SetRecvRtpHeaderExtensions( - const std::vector& extensions) { + bool SetRecvRtpHeaderExtensions(const std::vector& extensions) { recv_extensions_ = extensions; return true; } - bool SetSendRtpHeaderExtensions( - const std::vector& extensions) { + bool SetSendRtpHeaderExtensions(const std::vector& extensions) { send_extensions_ = extensions; return true; } + void set_send_rtcp_parameters(const RtcpParameters& params) { + send_rtcp_parameters_ = params; + } + void set_recv_rtcp_parameters(const RtcpParameters& params) { + recv_rtcp_parameters_ = params; + } virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) { rtp_packets_.push_back(std::string(packet->data(), packet->size())); @@ -252,6 +265,10 @@ template class RtpHelper : public Base { virtual void OnReadyToSend(bool ready) { ready_to_send_ = ready; } + virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) { + transport_overhead_per_packet_ = transport_overhead_per_packet; + } + virtual void OnNetworkRouteChanged(const std::string& transport_name, const rtc::NetworkRoute& network_route) { last_network_route_ = network_route; @@ -263,12 +280,14 @@ template class RtpHelper : public Base { private: bool sending_; bool playout_; - std::vector recv_extensions_; - std::vector send_extensions_; + std::vector recv_extensions_; + std::vector send_extensions_; std::list rtp_packets_; std::list rtcp_packets_; std::vector send_streams_; std::vector receive_streams_; + RtcpParameters send_rtcp_parameters_; + RtcpParameters recv_rtcp_parameters_; std::set muted_streams_; std::map rtp_send_parameters_; std::map rtp_receive_parameters_; @@ -277,6 +296,7 @@ template class RtpHelper : public Base { uint32_t send_ssrc_; std::string rtcp_cname_; bool ready_to_send_; + int transport_overhead_per_packet_; rtc::NetworkRoute last_network_route_; int num_network_route_changes_ = 0; }; @@ -294,7 +314,7 @@ class FakeVoiceMediaChannel : public RtpHelper { }; explicit FakeVoiceMediaChannel(FakeVoiceEngine* engine, const AudioOptions& options) - : engine_(engine), time_since_last_typing_(-1), max_bps_(-1) { + : engine_(engine), max_bps_(-1) { output_scalings_[0] = 1.0; // For default channel. SetOptions(options); } @@ -308,6 +328,7 @@ class FakeVoiceMediaChannel : public RtpHelper { const AudioOptions& options() const { return options_; } int max_bps() const { return max_bps_; } virtual bool SetSendParameters(const AudioSendParameters& params) { + set_send_rtcp_parameters(params.rtcp); return (SetSendCodecs(params.codecs) && SetSendRtpHeaderExtensions(params.extensions) && SetMaxSendBandwidth(params.max_bandwidth_bps) && @@ -315,14 +336,12 @@ class FakeVoiceMediaChannel : public RtpHelper { } virtual bool SetRecvParameters(const AudioRecvParameters& params) { + set_recv_rtcp_parameters(params.rtcp); return (SetRecvCodecs(params.codecs) && SetRecvRtpHeaderExtensions(params.extensions)); } - virtual bool SetPlayout(bool playout) { - set_playout(playout); - return true; - } + virtual void SetPlayout(bool playout) { set_playout(playout); } virtual void SetSend(bool send) { set_sending(send); } virtual bool SetAudioSend(uint32_t ssrc, bool enable, @@ -339,6 +358,11 @@ class FakeVoiceMediaChannel : public RtpHelper { } return true; } + + bool HasSource(uint32_t ssrc) const { + return local_sinks_.find(ssrc) != local_sinks_.end(); + } + virtual bool AddRecvStream(const StreamParams& sp) { if (!RtpHelper::AddRecvStream(sp)) return false; @@ -354,11 +378,6 @@ class FakeVoiceMediaChannel : public RtpHelper { virtual bool GetActiveStreams(AudioInfo::StreamList* streams) { return true; } virtual int GetOutputLevel() { return 0; } - void set_time_since_last_typing(int ms) { time_since_last_typing_ = ms; } - virtual int GetTimeSinceLastTyping() { return time_since_last_typing_; } - virtual void SetTypingDetectionParameters( - int time_window, int cost_per_typing, int reporting_threshold, - int penalty_decay, int type_event_delay) {} virtual bool CanInsertDtmf() { for (std::vector::const_iterator it = send_codecs_.begin(); @@ -457,7 +476,7 @@ class FakeVoiceMediaChannel : public RtpHelper { auto it = local_sinks_.find(ssrc); if (source) { if (it != local_sinks_.end()) { - ASSERT(it->second->source() == source); + RTC_CHECK(it->second->source() == source); } else { local_sinks_.insert( std::make_pair(ssrc, new VoiceChannelAudioSink(source))); @@ -476,7 +495,6 @@ class FakeVoiceMediaChannel : public RtpHelper { std::vector send_codecs_; std::map output_scalings_; std::vector dtmf_info_queue_; - int time_since_last_typing_; AudioOptions options_; std::map local_sinks_; std::unique_ptr sink_; @@ -507,17 +525,19 @@ class FakeVideoMediaChannel : public RtpHelper { const std::vector& codecs() const { return send_codecs(); } bool rendering() const { return playout(); } const VideoOptions& options() const { return options_; } - const std::map*>& sinks() - const { + const std::map*>& + sinks() const { return sinks_; } int max_bps() const { return max_bps_; } bool SetSendParameters(const VideoSendParameters& params) override { + set_send_rtcp_parameters(params.rtcp); return (SetSendCodecs(params.codecs) && SetSendRtpHeaderExtensions(params.extensions) && SetMaxSendBandwidth(params.max_bandwidth_bps)); } bool SetRecvParameters(const VideoRecvParameters& params) override { + set_recv_rtcp_parameters(params.rtcp); return (SetRecvCodecs(params.codecs) && SetRecvRtpHeaderExtensions(params.extensions)); } @@ -536,7 +556,7 @@ class FakeVideoMediaChannel : public RtpHelper { return true; } bool SetSink(uint32_t ssrc, - rtc::VideoSinkInterface* sink) override { + rtc::VideoSinkInterface* sink) override { if (ssrc != 0 && sinks_.find(ssrc) == sinks_.end()) { return false; } @@ -545,26 +565,31 @@ class FakeVideoMediaChannel : public RtpHelper { } return true; } + bool HasSink(uint32_t ssrc) const { + return sinks_.find(ssrc) != sinks_.end() && sinks_.at(ssrc) != nullptr; + } bool SetSend(bool send) override { return set_sending(send); } - bool SetVideoSend(uint32_t ssrc, bool enable, - const VideoOptions* options) override { + bool SetVideoSend( + uint32_t ssrc, + bool enable, + const VideoOptions* options, + rtc::VideoSourceInterface* source) override { if (!RtpHelper::MuteStream(ssrc, !enable)) { return false; } if (enable && options) { - return SetOptions(*options); + if (!SetOptions(*options)) { + return false; + } } - return true; - } - void SetSource( - uint32_t ssrc, - rtc::VideoSourceInterface* source) override { sources_[ssrc] = source; + return true; } bool HasSource(uint32_t ssrc) const { - return sources_.find(ssrc) != sources_.end(); + return sources_.find(ssrc) != sources_.end() && + sources_.at(ssrc) != nullptr; } bool AddRecvStream(const StreamParams& sp) override { if (!RtpHelper::AddRecvStream(sp)) @@ -611,8 +636,8 @@ class FakeVideoMediaChannel : public RtpHelper { FakeVideoEngine* engine_; std::vector recv_codecs_; std::vector send_codecs_; - std::map*> sinks_; - std::map*> sources_; + std::map*> sinks_; + std::map*> sources_; VideoOptions options_; int max_bps_; }; @@ -632,10 +657,12 @@ class FakeDataMediaChannel : public RtpHelper { int max_bps() const { return max_bps_; } virtual bool SetSendParameters(const DataSendParameters& params) { + set_send_rtcp_parameters(params.rtcp); return (SetSendCodecs(params.codecs) && SetMaxSendBandwidth(params.max_bandwidth_bps)); } virtual bool SetRecvParameters(const DataRecvParameters& params) { + set_recv_rtcp_parameters(params.rtcp); return SetRecvCodecs(params.codecs); } virtual bool SetSend(bool send) { return set_sending(send); } @@ -712,11 +739,20 @@ class FakeBaseEngine { void set_fail_create_channel(bool fail) { fail_create_channel_ = fail; } RtpCapabilities GetCapabilities() const { return capabilities_; } - void set_rtp_header_extensions( - const std::vector& extensions) { + void set_rtp_header_extensions(const std::vector& extensions) { capabilities_.header_extensions = extensions; } + void set_rtp_header_extensions( + const std::vector& extensions) { + for (const cricket::RtpHeaderExtension& ext : extensions) { + RtpExtension webrtc_ext; + webrtc_ext.uri = ext.uri; + webrtc_ext.id = ext.id; + capabilities_.header_extensions.push_back(webrtc_ext); + } + } + protected: // Flag used by optionsmessagehandler_unittest for checking whether any // relevant setting has been updated. @@ -728,8 +764,10 @@ class FakeBaseEngine { class FakeVoiceEngine : public FakeBaseEngine { public: - explicit FakeVoiceEngine(webrtc::AudioDeviceModule* adm) - : output_volume_(-1) { + FakeVoiceEngine(webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + rtc::scoped_refptr audio_mixer) { // Add a fake audio codec. Note that the name must not be "" as there are // sanity checks against that. codecs_.push_back(AudioCodec(101, "fake_audio_codec", 0, 0, 1)); @@ -756,17 +794,11 @@ class FakeVoiceEngine : public FakeBaseEngine { channels_.erase(std::find(channels_.begin(), channels_.end(), channel)); } - const std::vector& codecs() { return codecs_; } - void SetCodecs(const std::vector codecs) { codecs_ = codecs; } - - bool GetOutputVolume(int* level) { - *level = output_volume_; - return true; - } - bool SetOutputVolume(int level) { - output_volume_ = level; - return true; - } + // TODO(ossu): For proper testing, These should either individually settable + // or the voice engine should reference mockable factories. + const std::vector& send_codecs() { return codecs_; } + const std::vector& recv_codecs() { return codecs_; } + void SetCodecs(const std::vector& codecs) { codecs_ = codecs; } int GetInputLevel() { return 0; } @@ -785,7 +817,6 @@ class FakeVoiceEngine : public FakeBaseEngine { private: std::vector channels_; std::vector codecs_; - int output_volume_; friend class FakeMediaEngine; }; @@ -795,7 +826,7 @@ class FakeVideoEngine : public FakeBaseEngine { FakeVideoEngine() : capture_(false) { // Add a fake video codec. Note that the name must not be "" as there are // sanity checks against that. - codecs_.push_back(VideoCodec(0, "fake_video_codec", 0, 0, 0)); + codecs_.push_back(VideoCodec(0, "fake_video_codec")); } void Init() {} bool SetOptions(const VideoOptions& options) { @@ -842,8 +873,10 @@ class FakeVideoEngine : public FakeBaseEngine { class FakeMediaEngine : public CompositeMediaEngine { public: - FakeMediaEngine() : - CompositeMediaEngine(nullptr) {} + FakeMediaEngine() + : CompositeMediaEngine(nullptr, + nullptr, + nullptr) {} virtual ~FakeMediaEngine() {} void SetAudioCodecs(const std::vector& codecs) { @@ -854,11 +887,20 @@ class FakeMediaEngine : } void SetAudioRtpHeaderExtensions( - const std::vector& extensions) { + const std::vector& extensions) { + voice_.set_rtp_header_extensions(extensions); + } + void SetVideoRtpHeaderExtensions( + const std::vector& extensions) { + video_.set_rtp_header_extensions(extensions); + } + + void SetAudioRtpHeaderExtensions( + const std::vector& extensions) { voice_.set_rtp_header_extensions(extensions); } void SetVideoRtpHeaderExtensions( - const std::vector& extensions) { + const std::vector& extensions) { video_.set_rtp_header_extensions(extensions); } @@ -869,7 +911,6 @@ class FakeMediaEngine : return video_.GetChannel(index); } - int output_volume() const { return voice_.output_volume_; } bool capture() const { return video_.capture_; } bool options_changed() const { return video_.options_changed_; @@ -883,20 +924,6 @@ class FakeMediaEngine : } }; -// CompositeMediaEngine with FakeVoiceEngine to expose SetAudioCodecs to -// establish a media connectionwith minimum set of audio codes required -template -class CompositeMediaEngineWithFakeVoiceEngine : - public CompositeMediaEngine { - public: - CompositeMediaEngineWithFakeVoiceEngine() {} - virtual ~CompositeMediaEngineWithFakeVoiceEngine() {} - - virtual void SetAudioCodecs(const std::vector& codecs) { - CompositeMediaEngine::voice_.SetCodecs(codecs); - } -}; - // Have to come afterwards due to declaration order inline FakeVoiceMediaChannel::~FakeVoiceMediaChannel() { if (engine_) { @@ -912,10 +939,9 @@ inline FakeVideoMediaChannel::~FakeVideoMediaChannel() { class FakeDataEngine : public DataEngineInterface { public: - FakeDataEngine() : last_channel_type_(DCT_NONE) {} + FakeDataEngine(){}; - virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type) { - last_channel_type_ = data_channel_type; + virtual DataMediaChannel* CreateChannel(const MediaConfig& config) { FakeDataMediaChannel* ch = new FakeDataMediaChannel(this, DataOptions()); channels_.push_back(ch); return ch; @@ -935,12 +961,9 @@ class FakeDataEngine : public DataEngineInterface { virtual const std::vector& data_codecs() { return data_codecs_; } - DataChannelType last_channel_type() const { return last_channel_type_; } - private: std::vector channels_; std::vector data_codecs_; - DataChannelType last_channel_type_; }; } // namespace cricket diff --git a/include/webrtc/media/base/fakenetworkinterface.h b/include/webrtc/media/base/fakenetworkinterface.h index 65dac25..ed8b232 100644 --- a/include/webrtc/media/base/fakenetworkinterface.h +++ b/include/webrtc/media/base/fakenetworkinterface.h @@ -160,7 +160,7 @@ class FakeNetworkInterface : public MediaChannel::NetworkInterface, } void PostMessage(int id, const rtc::CopyOnWriteBuffer& packet) { - thread_->Post(this, id, rtc::WrapMessageData(packet)); + thread_->Post(RTC_FROM_HERE, this, id, rtc::WrapMessageData(packet)); } virtual void OnMessage(rtc::Message* msg) { diff --git a/include/webrtc/media/base/fakescreencapturerfactory.h b/include/webrtc/media/base/fakescreencapturerfactory.h deleted file mode 100644 index a196c26..0000000 --- a/include/webrtc/media/base/fakescreencapturerfactory.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_FAKESCREENCAPTURERFACTORY_H_ -#define WEBRTC_MEDIA_BASE_FAKESCREENCAPTURERFACTORY_H_ - -#include "webrtc/media/base/fakevideocapturer.h" -#include "webrtc/media/base/videocapturerfactory.h" - -namespace cricket { - -class FakeScreenCapturerFactory - : public cricket::ScreenCapturerFactory, - public sigslot::has_slots<> { - public: - FakeScreenCapturerFactory() - : window_capturer_(NULL), - capture_state_(cricket::CS_STOPPED) {} - - virtual cricket::VideoCapturer* Create(const ScreencastId& window) { - if (window_capturer_ != NULL) { - return NULL; - } - window_capturer_ = new cricket::FakeVideoCapturer; - window_capturer_->SignalDestroyed.connect( - this, - &FakeScreenCapturerFactory::OnWindowCapturerDestroyed); - window_capturer_->SignalStateChange.connect( - this, - &FakeScreenCapturerFactory::OnStateChange); - return window_capturer_; - } - - cricket::FakeVideoCapturer* window_capturer() { return window_capturer_; } - - cricket::CaptureState capture_state() { return capture_state_; } - - private: - void OnWindowCapturerDestroyed(cricket::FakeVideoCapturer* capturer) { - if (capturer == window_capturer_) { - window_capturer_ = NULL; - } - } - void OnStateChange(cricket::VideoCapturer*, cricket::CaptureState state) { - capture_state_ = state; - } - - cricket::FakeVideoCapturer* window_capturer_; - cricket::CaptureState capture_state_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_FAKESCREENCAPTURERFACTORY_H_ diff --git a/include/webrtc/media/base/fakevideocapturer.h b/include/webrtc/media/base/fakevideocapturer.h index 026bf80..b5bfd34 100644 --- a/include/webrtc/media/base/fakevideocapturer.h +++ b/include/webrtc/media/base/fakevideocapturer.h @@ -16,28 +16,23 @@ #include #include +#include "webrtc/api/video/i420_buffer.h" +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/timeutils.h" #include "webrtc/media/base/videocapturer.h" #include "webrtc/media/base/videocommon.h" -#include "webrtc/media/base/videoframe.h" -#ifdef HAVE_WEBRTC_VIDEO -#include "webrtc/media/engine/webrtcvideoframefactory.h" -#endif namespace cricket { // Fake video capturer that allows the test to manually pump in frames. class FakeVideoCapturer : public cricket::VideoCapturer { public: - FakeVideoCapturer(bool is_screencast) + explicit FakeVideoCapturer(bool is_screencast) : running_(false), initial_timestamp_(rtc::TimeNanos()), next_timestamp_(rtc::kNumNanosecsPerMillisec), is_screencast_(is_screencast), rotation_(webrtc::kVideoRotation_0) { -#ifdef HAVE_WEBRTC_VIDEO - set_frame_factory(new cricket::WebRtcVideoFrameFactory()); -#endif // Default supported formats. Use ResetSupportedFormats to over write. std::vector formats; formats.push_back(cricket::VideoFormat(1280, 720, @@ -81,65 +76,54 @@ class FakeVideoCapturer : public cricket::VideoCapturer { if (!running_) { return false; } - // Currently, |fourcc| is always I420 or ARGB. - uint32_t size = 0u; - if (fourcc == cricket::FOURCC_ARGB) { - size = width * 4 * height; - } else if (fourcc == cricket::FOURCC_I420) { - size = width * height + 2 * ((width + 1) / 2) * ((height + 1) / 2); - } else { - return false; // Unsupported FOURCC. + RTC_CHECK(fourcc == FOURCC_I420); + RTC_CHECK(width > 0); + RTC_CHECK(height > 0); + + int adapted_width; + int adapted_height; + int crop_width; + int crop_height; + int crop_x; + int crop_y; + + // TODO(nisse): It's a bit silly to have this logic in a fake + // class. Child classes of VideoCapturer are expected to call + // AdaptFrame, and the test case + // VideoCapturerTest.SinkWantsMaxPixelAndMaxPixelCountStepUp + // depends on this. + if (AdaptFrame(width, height, 0, 0, &adapted_width, &adapted_height, + &crop_width, &crop_height, &crop_x, &crop_y, nullptr)) { + rtc::scoped_refptr buffer( + webrtc::I420Buffer::Create(adapted_width, adapted_height)); + buffer->InitializeData(); + + OnFrame(webrtc::VideoFrame( + buffer, rotation_, + next_timestamp_ / rtc::kNumNanosecsPerMicrosec), + width, height); } - if (size == 0u) { - return false; // Width and/or Height were zero. - } - - cricket::CapturedFrame frame; - frame.width = width; - frame.height = height; - frame.fourcc = fourcc; - frame.data_size = size; - frame.time_stamp = initial_timestamp_ + next_timestamp_; next_timestamp_ += timestamp_interval; - std::unique_ptr data(new char[size]); - frame.data = data.get(); - // Copy something non-zero into the buffer so Validate wont complain that - // the frame is all duplicate. - memset(frame.data, 1, size / 2); - memset(reinterpret_cast(frame.data) + (size / 2), 2, - size - (size / 2)); - memcpy(frame.data, reinterpret_cast(&fourcc), 4); - frame.rotation = rotation_; - // TODO(zhurunz): SignalFrameCaptured carry returned value to be able to - // capture results from downstream. - SignalFrameCaptured(this, &frame); return true; } - void SignalCapturedFrame(cricket::CapturedFrame* frame) { - SignalFrameCaptured(this, frame); - } - sigslot::signal1 SignalDestroyed; - virtual cricket::CaptureState Start(const cricket::VideoFormat& format) { - cricket::VideoFormat supported; - if (GetBestCaptureFormat(format, &supported)) { - SetCaptureFormat(&supported); - } + cricket::CaptureState Start(const cricket::VideoFormat& format) override { + SetCaptureFormat(&format); running_ = true; SetCaptureState(cricket::CS_RUNNING); return cricket::CS_RUNNING; } - virtual void Stop() { + void Stop() override { running_ = false; SetCaptureFormat(NULL); SetCaptureState(cricket::CS_STOPPED); } - virtual bool IsRunning() { return running_; } - virtual bool IsScreencast() const { return is_screencast_; } - bool GetPreferredFourccs(std::vector* fourccs) { + bool IsRunning() override { return running_; } + bool IsScreencast() const override { return is_screencast_; } + bool GetPreferredFourccs(std::vector* fourccs) override { fourccs->push_back(cricket::FOURCC_I420); fourccs->push_back(cricket::FOURCC_MJPG); return true; diff --git a/include/webrtc/media/base/fakevideorenderer.h b/include/webrtc/media/base/fakevideorenderer.h index 7398bba..7255c05 100644 --- a/include/webrtc/media/base/fakevideorenderer.h +++ b/include/webrtc/media/base/fakevideorenderer.h @@ -11,37 +11,38 @@ #ifndef WEBRTC_MEDIA_BASE_FAKEVIDEORENDERER_H_ #define WEBRTC_MEDIA_BASE_FAKEVIDEORENDERER_H_ +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/logging.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/media/base/videoframe.h" #include "webrtc/media/base/videosinkinterface.h" namespace cricket { // Faked video renderer that has a callback for actions on rendering. -class FakeVideoRenderer : public rtc::VideoSinkInterface { +class FakeVideoRenderer : public rtc::VideoSinkInterface { public: FakeVideoRenderer() : errors_(0), width_(0), height_(0), rotation_(webrtc::kVideoRotation_0), - timestamp_(0), + timestamp_us_(0), num_rendered_frames_(0), black_frame_(false) {} - virtual void OnFrame(const VideoFrame& frame) { + virtual void OnFrame(const webrtc::VideoFrame& frame) { rtc::CritScope cs(&crit_); // TODO(zhurunz) Check with VP8 team to see if we can remove this - // tolerance on Y values. - black_frame_ = CheckFrameColorYuv(6, 48, 128, 128, 128, 128, &frame); + // tolerance on Y values. Some unit tests produce Y values close + // to 16 rather than close to zero, for supposedly black frames. + // Largest value observed is 34, e.g., running + // P2PTestConductor.LocalP2PTest16To9 (peerconnection_unittests). + black_frame_ = CheckFrameColorYuv(0, 48, 128, 128, 128, 128, &frame); // Treat unexpected frame size as error. ++num_rendered_frames_; width_ = frame.width(); height_ = frame.height(); rotation_ = frame.rotation(); - timestamp_ = frame.GetTimeStamp(); - SignalRenderFrame(&frame); + timestamp_us_ = frame.timestamp_us(); } int errors() const { return errors_; } @@ -58,9 +59,9 @@ class FakeVideoRenderer : public rtc::VideoSinkInterface { return rotation_; } - int64_t timestamp() const { + int64_t timestamp_us() const { rtc::CritScope cs(&crit_); - return timestamp_; + return timestamp_us_; } int num_rendered_frames() const { rtc::CritScope cs(&crit_); @@ -71,9 +72,6 @@ class FakeVideoRenderer : public rtc::VideoSinkInterface { return black_frame_; } - sigslot::signal3 SignalSetSize; - sigslot::signal1 SignalRenderFrame; - private: static bool CheckFrameColorYuv(uint8_t y_min, uint8_t y_max, @@ -81,7 +79,7 @@ class FakeVideoRenderer : public rtc::VideoSinkInterface { uint8_t u_max, uint8_t v_min, uint8_t v_max, - const cricket::VideoFrame* frame) { + const webrtc::VideoFrame* frame) { if (!frame || !frame->video_frame_buffer()) { return false; } @@ -130,7 +128,7 @@ class FakeVideoRenderer : public rtc::VideoSinkInterface { int width_; int height_; webrtc::VideoRotation rotation_; - int64_t timestamp_; + int64_t timestamp_us_; int num_rendered_frames_; bool black_frame_; rtc::CriticalSection crit_; diff --git a/include/webrtc/media/base/hybriddataengine.h b/include/webrtc/media/base/hybriddataengine.h deleted file mode 100644 index 508210b..0000000 --- a/include/webrtc/media/base/hybriddataengine.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_HYBRIDDATAENGINE_H_ -#define WEBRTC_MEDIA_BASE_HYBRIDDATAENGINE_H_ - -#include -#include -#include - -#include "webrtc/media/base/codec.h" -#include "webrtc/media/base/mediachannel.h" -#include "webrtc/media/base/mediaengine.h" - -namespace cricket { - -class HybridDataEngine : public DataEngineInterface { - public: - // Takes ownership. - HybridDataEngine(DataEngineInterface* first, - DataEngineInterface* second) - : first_(first), - second_(second) { - codecs_ = first_->data_codecs(); - codecs_.insert( - codecs_.end(), - second_->data_codecs().begin(), - second_->data_codecs().end()); - } - - virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type) { - DataMediaChannel* channel = NULL; - if (first_) { - channel = first_->CreateChannel(data_channel_type); - } - if (!channel && second_) { - channel = second_->CreateChannel(data_channel_type); - } - return channel; - } - - virtual const std::vector& data_codecs() { return codecs_; } - - private: - std::unique_ptr first_; - std::unique_ptr second_; - std::vector codecs_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_HYBRIDDATAENGINE_H_ diff --git a/include/webrtc/media/base/mediachannel.h b/include/webrtc/media/base/mediachannel.h index 5434709..ca02c72 100644 --- a/include/webrtc/media/base/mediachannel.h +++ b/include/webrtc/media/base/mediachannel.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MEDIA_BASE_MEDIACHANNEL_H_ #define WEBRTC_MEDIA_BASE_MEDIACHANNEL_H_ +#include #include #include #include @@ -26,6 +27,7 @@ #include "webrtc/base/sigslot.h" #include "webrtc/base/socket.h" #include "webrtc/base/window.h" +#include "webrtc/config.h" #include "webrtc/media/base/codec.h" #include "webrtc/media/base/mediaconstants.h" #include "webrtc/media/base/streamparams.h" @@ -41,19 +43,16 @@ class Timing; namespace webrtc { class AudioSinkInterface; +class VideoFrame; } namespace cricket { class AudioSource; -class ScreencastId; class VideoCapturer; -class VideoFrame; struct RtpHeader; struct VideoFormat; -const int kMinRtpHeaderExtensionId = 1; -const int kMaxRtpHeaderExtensionId = 255; const int kScreencastDefaultFps = 5; template @@ -104,9 +103,7 @@ struct MediaConfig { // Video-specific config. struct Video { // Enable WebRTC CPU Overuse Detection. This flag comes from the - // PeerConnection constraint 'googCpuOveruseDetection' and is - // checked in WebRtcVideoChannel2::OnLoadUpdate, where it's passed - // to VideoCapturer::video_adapter()->OnCpuResolutionRequest. + // PeerConnection constraint 'googCpuOveruseDetection'. bool enable_cpu_overuse_detection = true; // Enable WebRTC suspension of video. No video frames will be sent @@ -132,7 +129,24 @@ struct MediaConfig { // VideoReceiveStream, where the value is passed on to the // IncomingVideoStream constructor. bool disable_prerenderer_smoothing = false; + + // Enables periodic bandwidth probing in application-limited region. + bool periodic_alr_bandwidth_probing = false; } video; + + bool operator==(const MediaConfig& o) const { + return enable_dscp == o.enable_dscp && + video.enable_cpu_overuse_detection == + o.video.enable_cpu_overuse_detection && + video.suspend_below_min_bitrate == + o.video.suspend_below_min_bitrate && + video.disable_prerenderer_smoothing == + o.video.disable_prerenderer_smoothing && + video.periodic_alr_bandwidth_probing == + o.video.periodic_alr_bandwidth_probing; + } + + bool operator!=(const MediaConfig& o) const { return !(*this == o); } }; // Options that can be applied to a VoiceMediaChannel or a VoiceMediaEngine. @@ -158,6 +172,8 @@ struct AudioOptions { SetFrom(&delay_agnostic_aec, change.delay_agnostic_aec); SetFrom(&experimental_ns, change.experimental_ns); SetFrom(&intelligibility_enhancer, change.intelligibility_enhancer); + SetFrom(&level_control, change.level_control); + SetFrom(&residual_echo_detector, change.residual_echo_detector); SetFrom(&tx_agc_target_dbov, change.tx_agc_target_dbov); SetFrom(&tx_agc_digital_compression_gain, change.tx_agc_digital_compression_gain); @@ -165,31 +181,43 @@ struct AudioOptions { SetFrom(&recording_sample_rate, change.recording_sample_rate); SetFrom(&playout_sample_rate, change.playout_sample_rate); SetFrom(&combined_audio_video_bwe, change.combined_audio_video_bwe); + SetFrom(&audio_network_adaptor, change.audio_network_adaptor); + SetFrom(&audio_network_adaptor_config, change.audio_network_adaptor_config); + SetFrom(&level_control_initial_peak_level_dbfs, + change.level_control_initial_peak_level_dbfs); } bool operator==(const AudioOptions& o) const { return echo_cancellation == o.echo_cancellation && - auto_gain_control == o.auto_gain_control && - noise_suppression == o.noise_suppression && - highpass_filter == o.highpass_filter && - stereo_swapping == o.stereo_swapping && - audio_jitter_buffer_max_packets == o.audio_jitter_buffer_max_packets && - audio_jitter_buffer_fast_accelerate == - o.audio_jitter_buffer_fast_accelerate && - typing_detection == o.typing_detection && - aecm_generate_comfort_noise == o.aecm_generate_comfort_noise && - experimental_agc == o.experimental_agc && - extended_filter_aec == o.extended_filter_aec && - delay_agnostic_aec == o.delay_agnostic_aec && - experimental_ns == o.experimental_ns && - intelligibility_enhancer == o.intelligibility_enhancer && - adjust_agc_delta == o.adjust_agc_delta && - tx_agc_target_dbov == o.tx_agc_target_dbov && - tx_agc_digital_compression_gain == o.tx_agc_digital_compression_gain && - tx_agc_limiter == o.tx_agc_limiter && - recording_sample_rate == o.recording_sample_rate && - playout_sample_rate == o.playout_sample_rate && - combined_audio_video_bwe == o.combined_audio_video_bwe; + auto_gain_control == o.auto_gain_control && + noise_suppression == o.noise_suppression && + highpass_filter == o.highpass_filter && + stereo_swapping == o.stereo_swapping && + audio_jitter_buffer_max_packets == + o.audio_jitter_buffer_max_packets && + audio_jitter_buffer_fast_accelerate == + o.audio_jitter_buffer_fast_accelerate && + typing_detection == o.typing_detection && + aecm_generate_comfort_noise == o.aecm_generate_comfort_noise && + experimental_agc == o.experimental_agc && + extended_filter_aec == o.extended_filter_aec && + delay_agnostic_aec == o.delay_agnostic_aec && + experimental_ns == o.experimental_ns && + intelligibility_enhancer == o.intelligibility_enhancer && + level_control == o.level_control && + residual_echo_detector == o.residual_echo_detector && + adjust_agc_delta == o.adjust_agc_delta && + tx_agc_target_dbov == o.tx_agc_target_dbov && + tx_agc_digital_compression_gain == + o.tx_agc_digital_compression_gain && + tx_agc_limiter == o.tx_agc_limiter && + recording_sample_rate == o.recording_sample_rate && + playout_sample_rate == o.playout_sample_rate && + combined_audio_video_bwe == o.combined_audio_video_bwe && + audio_network_adaptor == o.audio_network_adaptor && + audio_network_adaptor_config == o.audio_network_adaptor_config && + level_control_initial_peak_level_dbfs == + o.level_control_initial_peak_level_dbfs; } bool operator!=(const AudioOptions& o) const { return !(*this == o); } @@ -213,6 +241,10 @@ struct AudioOptions { ost << ToStringIfSet("delay_agnostic_aec", delay_agnostic_aec); ost << ToStringIfSet("experimental_ns", experimental_ns); ost << ToStringIfSet("intelligibility_enhancer", intelligibility_enhancer); + ost << ToStringIfSet("level_control", level_control); + ost << ToStringIfSet("level_control_initial_peak_level_dbfs", + level_control_initial_peak_level_dbfs); + ost << ToStringIfSet("residual_echo_detector", residual_echo_detector); ost << ToStringIfSet("tx_agc_target_dbov", tx_agc_target_dbov); ost << ToStringIfSet("tx_agc_digital_compression_gain", tx_agc_digital_compression_gain); @@ -220,6 +252,11 @@ struct AudioOptions { ost << ToStringIfSet("recording_sample_rate", recording_sample_rate); ost << ToStringIfSet("playout_sample_rate", playout_sample_rate); ost << ToStringIfSet("combined_audio_video_bwe", combined_audio_video_bwe); + ost << ToStringIfSet("audio_network_adaptor", audio_network_adaptor); + // The adaptor config is a serialized proto buffer and therefore not human + // readable. So we comment out the following line. + // ost << ToStringIfSet("audio_network_adaptor_config", + // audio_network_adaptor_config); ost << "}"; return ost.str(); } @@ -248,7 +285,11 @@ struct AudioOptions { rtc::Optional delay_agnostic_aec; rtc::Optional experimental_ns; rtc::Optional intelligibility_enhancer; + rtc::Optional level_control; + // Specifies an optional initialization value for the level controller. + rtc::Optional level_control_initial_peak_level_dbfs; // Note that tx_agc_* only applies to non-experimental AGC. + rtc::Optional residual_echo_detector; rtc::Optional tx_agc_target_dbov; rtc::Optional tx_agc_digital_compression_gain; rtc::Optional tx_agc_limiter; @@ -259,6 +300,10 @@ struct AudioOptions { // "googCombinedAudioVideoBwe", but not used anywhere. So delete it, // and check if any other AudioOptions members are unused. rtc::Optional combined_audio_video_bwe; + // Enable audio network adaptor. + rtc::Optional audio_network_adaptor; + // Config string for audio network adaptor. + rtc::Optional audio_network_adaptor_config; private: template @@ -321,16 +366,10 @@ struct VideoOptions { } }; +// TODO(isheriff): Remove this once client usage is fixed to use RtpExtension. struct RtpHeaderExtension { RtpHeaderExtension() : id(0) {} - RtpHeaderExtension(const std::string& u, int i) : uri(u), id(i) {} - - bool operator==(const RtpHeaderExtension& ext) const { - // id is a reserved word in objective-c. Therefore the id attribute has to - // be a fully qualified name in order to compile on IOS. - return this->id == ext.id && - uri == ext.uri; - } + RtpHeaderExtension(const std::string& uri, int id) : uri(uri), id(id) {} std::string ToString() const { std::ostringstream ost; @@ -343,22 +382,8 @@ struct RtpHeaderExtension { std::string uri; int id; - // TODO(juberti): SendRecv direction; }; -// Returns the named header extension if found among all extensions, NULL -// otherwise. -inline const RtpHeaderExtension* FindHeaderExtension( - const std::vector& extensions, - const std::string& name) { - for (std::vector::const_iterator it = extensions.begin(); - it != extensions.end(); ++it) { - if (it->uri == name) - return &(*it); - } - return NULL; -} - class MediaChannel : public sigslot::has_slots<> { public: class NetworkInterface { @@ -373,7 +398,7 @@ class MediaChannel : public sigslot::has_slots<> { virtual ~NetworkInterface() {} }; - MediaChannel(const MediaConfig& config) + explicit MediaChannel(const MediaConfig& config) : enable_dscp_(config.enable_dscp), network_interface_(NULL) {} MediaChannel() : enable_dscp_(false), network_interface_(NULL) {} virtual ~MediaChannel() {} @@ -399,6 +424,9 @@ class MediaChannel : public sigslot::has_slots<> { virtual void OnNetworkRouteChanged( const std::string& transport_name, const rtc::NetworkRoute& network_route) = 0; + // Called when the rtp transport overhead changed. + virtual void OnTransportOverheadChanged( + int transport_overhead_per_packet) = 0; // Creates a new outgoing media stream with SSRCs and CNAME as described // by sp. virtual bool AddSendStream(const StreamParams& sp) = 0; @@ -542,6 +570,7 @@ struct MediaSenderInfo { float fraction_lost; int64_t rtt_ms; std::string codec_name; + rtc::Optional codec_payload_type; std::vector local_stats; std::vector remote_stats; }; @@ -587,6 +616,7 @@ struct MediaReceiverInfo { int packets_lost; float fraction_lost; std::string codec_name; + rtc::Optional codec_payload_type; std::vector local_stats; std::vector remote_stats; }; @@ -601,8 +631,9 @@ struct VoiceSenderInfo : public MediaSenderInfo { echo_delay_std_ms(0), echo_return_loss(0), echo_return_loss_enhancement(0), - typing_noise_detected(false) { - } + residual_echo_likelihood(0.0f), + residual_echo_likelihood_recent_max(0.0f), + typing_noise_detected(false) {} int ext_seqnum; int jitter_ms; @@ -612,6 +643,8 @@ struct VoiceSenderInfo : public MediaSenderInfo { int echo_delay_std_ms; int echo_return_loss; int echo_return_loss_enhancement; + float residual_echo_likelihood; + float residual_echo_likelihood_recent_max; bool typing_noise_detected; }; @@ -634,6 +667,7 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { decoding_plc(0), decoding_cng(0), decoding_plc_cng(0), + decoding_muted_output(0), capture_start_ntp_time_ms(-1) {} int ext_seqnum; @@ -658,6 +692,7 @@ struct VoiceReceiverInfo : public MediaReceiverInfo { int decoding_plc; int decoding_cng; int decoding_plc_cng; + int decoding_muted_output; // Estimated capture start time in NTP time in ms. int64_t capture_start_ntp_time_ms; }; @@ -677,10 +712,11 @@ struct VideoSenderInfo : public MediaSenderInfo { adapt_reason(0), adapt_changes(0), avg_encode_ms(0), - encode_usage_percent(0) { - } + encode_usage_percent(0), + frames_encoded(0) {} std::vector ssrc_groups; + // TODO(hbos): Move this to |VideoMediaInfo::send_codecs|? std::string encoder_implementation_name; int packets_cached; int firs_rcvd; @@ -696,6 +732,8 @@ struct VideoSenderInfo : public MediaSenderInfo { int adapt_changes; int avg_encode_ms; int encode_usage_percent; + uint32_t frames_encoded; + rtc::Optional qp_sum; }; struct VideoReceiverInfo : public MediaReceiverInfo { @@ -711,6 +749,9 @@ struct VideoReceiverInfo : public MediaReceiverInfo { framerate_output(0), framerate_render_input(0), framerate_render_output(0), + frames_received(0), + frames_decoded(0), + frames_rendered(0), decode_ms(0), max_decode_ms(0), jitter_buffer_ms(0), @@ -722,6 +763,7 @@ struct VideoReceiverInfo : public MediaReceiverInfo { } std::vector ssrc_groups; + // TODO(hbos): Move this to |VideoMediaInfo::receive_codecs|? std::string decoder_implementation_name; int packets_concealed; int firs_sent; @@ -736,6 +778,10 @@ struct VideoReceiverInfo : public MediaReceiverInfo { int framerate_render_input; // Framerate that the renderer reports. int framerate_render_output; + uint32_t frames_received; + uint32_t frames_decoded; + uint32_t frames_rendered; + rtc::Optional qp_sum; // All stats below are gathered per-VideoReceiver, but some will be correlated // across MediaStreamTracks. NOTE(hta): when sinking stats into per-SSRC @@ -797,13 +843,20 @@ struct BandwidthEstimationInfo { int64_t bucket_delay; }; +// Maps from payload type to |RtpCodecParameters|. +typedef std::map RtpCodecParametersMap; + struct VoiceMediaInfo { void Clear() { senders.clear(); receivers.clear(); + send_codecs.clear(); + receive_codecs.clear(); } std::vector senders; std::vector receivers; + RtpCodecParametersMap send_codecs; + RtpCodecParametersMap receive_codecs; }; struct VideoMediaInfo { @@ -811,10 +864,14 @@ struct VideoMediaInfo { senders.clear(); receivers.clear(); bw_estimations.clear(); + send_codecs.clear(); + receive_codecs.clear(); } std::vector senders; std::vector receivers; std::vector bw_estimations; + RtpCodecParametersMap send_codecs; + RtpCodecParametersMap receive_codecs; }; struct DataMediaInfo { @@ -842,7 +899,7 @@ struct RtpParameters { } std::vector codecs; - std::vector extensions; + std::vector extensions; // TODO(pthatcher): Add streams. RtcpParameters rtcp; virtual ~RtpParameters() = default; @@ -907,7 +964,8 @@ class VoiceMediaChannel : public MediaChannel { }; VoiceMediaChannel() {} - VoiceMediaChannel(const MediaConfig& config) : MediaChannel(config) {} + explicit VoiceMediaChannel(const MediaConfig& config) + : MediaChannel(config) {} virtual ~VoiceMediaChannel() {} virtual bool SetSendParameters(const AudioSendParameters& params) = 0; virtual bool SetRecvParameters(const AudioRecvParameters& params) = 0; @@ -921,7 +979,7 @@ class VoiceMediaChannel : public MediaChannel { uint32_t ssrc, const webrtc::RtpParameters& parameters) = 0; // Starts or stops playout of received audio. - virtual bool SetPlayout(bool playout) = 0; + virtual void SetPlayout(bool playout) = 0; // Starts or stops sending (and potentially capture) of local audio. virtual void SetSend(bool send) = 0; // Configure stream for sending. @@ -933,12 +991,6 @@ class VoiceMediaChannel : public MediaChannel { virtual bool GetActiveStreams(AudioInfo::StreamList* actives) = 0; // Get the current energy level of the stream sent to the speaker. virtual int GetOutputLevel() = 0; - // Get the time in milliseconds since last recorded keystroke, or negative. - virtual int GetTimeSinceLastTyping() = 0; - // Temporarily exposed field for tuning typing detect options. - virtual void SetTypingDetectionParameters(int time_window, - int cost_per_typing, int reporting_threshold, int penalty_decay, - int type_event_delay) = 0; // Set speaker output volume of the specified ssrc. virtual bool SetOutputVolume(uint32_t ssrc, double volume) = 0; // Returns if the telephone-event has been negotiated. @@ -991,7 +1043,8 @@ class VideoMediaChannel : public MediaChannel { }; VideoMediaChannel() {} - VideoMediaChannel(const MediaConfig& config) : MediaChannel(config) {} + explicit VideoMediaChannel(const MediaConfig& config) + : MediaChannel(config) {} virtual ~VideoMediaChannel() {} virtual bool SetSendParameters(const VideoSendParameters& params) = 0; @@ -1009,18 +1062,17 @@ class VideoMediaChannel : public MediaChannel { virtual bool GetSendCodec(VideoCodec* send_codec) = 0; // Starts or stops transmission (and potentially capture) of local video. virtual bool SetSend(bool send) = 0; - // Configure stream for sending. - virtual bool SetVideoSend(uint32_t ssrc, - bool enable, - const VideoOptions* options) = 0; + // Configure stream for sending and register a source. + // The |ssrc| must correspond to a registered send stream. + virtual bool SetVideoSend( + uint32_t ssrc, + bool enable, + const VideoOptions* options, + rtc::VideoSourceInterface* source) = 0; // Sets the sink object to be used for the specified stream. // If SSRC is 0, the renderer is used for the 'default' stream. virtual bool SetSink(uint32_t ssrc, - rtc::VideoSinkInterface* sink) = 0; - // Register a source. The |ssrc| must correspond to a registered send stream. - virtual void SetSource( - uint32_t ssrc, - rtc::VideoSourceInterface* source) = 0; + rtc::VideoSinkInterface* sink) = 0; // Gets quality stats for the channel. virtual bool GetStats(VideoMediaInfo* info) = 0; }; @@ -1039,8 +1091,11 @@ enum DataMessageType { // signal fires, on up the chain. struct ReceiveDataParams { // The in-packet stream indentifier. - // For SCTP, this is really SID, not SSRC. - uint32_t ssrc; + // RTP data channels use SSRCs, SCTP data channels use SIDs. + union { + uint32_t ssrc; + int sid; + }; // The type of message (binary, text, or control). DataMessageType type; // A per-stream value incremented per packet in the stream. @@ -1048,18 +1103,16 @@ struct ReceiveDataParams { // A per-stream value monotonically increasing with time. int timestamp; - ReceiveDataParams() : - ssrc(0), - type(DMT_TEXT), - seq_num(0), - timestamp(0) { - } + ReceiveDataParams() : sid(0), type(DMT_TEXT), seq_num(0), timestamp(0) {} }; struct SendDataParams { // The in-packet stream indentifier. - // For SCTP, this is really SID, not SSRC. - uint32_t ssrc; + // RTP data channels use SSRCs, SCTP data channels use SIDs. + union { + uint32_t ssrc; + int sid; + }; // The type of message (binary, text, or control). DataMessageType type; @@ -1078,15 +1131,14 @@ struct SendDataParams { // is supported, not both at the same time. int max_rtx_ms; - SendDataParams() : - ssrc(0), - type(DMT_TEXT), - // TODO(pthatcher): Make these true by default? - ordered(false), - reliable(false), - max_rtx_count(0), - max_rtx_ms(0) { - } + SendDataParams() + : sid(0), + type(DMT_TEXT), + // TODO(pthatcher): Make these true by default? + ordered(false), + reliable(false), + max_rtx_count(0), + max_rtx_ms(0) {} }; enum SendDataResult { SDR_SUCCESS, SDR_ERROR, SDR_BLOCK }; @@ -1118,6 +1170,8 @@ class DataMediaChannel : public MediaChannel { ERROR_RECV_SRTP_REPLAY, // Packet replay detected. }; + DataMediaChannel() {} + DataMediaChannel(const MediaConfig& config) : MediaChannel(config) {} virtual ~DataMediaChannel() {} virtual bool SetSendParameters(const DataSendParameters& params) = 0; @@ -1143,8 +1197,6 @@ class DataMediaChannel : public MediaChannel { // Signal when the media channel is ready to send the stream. Arguments are: // writable(bool) sigslot::signal1 SignalReadyToSend; - // Signal for notifying that the remote side has closed the DataChannel. - sigslot::signal1 SignalStreamClosedRemotely; }; } // namespace cricket diff --git a/include/webrtc/media/base/mediacommon.h b/include/webrtc/media/base/mediacommon.h deleted file mode 100644 index c760463..0000000 --- a/include/webrtc/media/base/mediacommon.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_MEDIACOMMON_H_ -#define WEBRTC_MEDIA_BASE_MEDIACOMMON_H_ - -#include "webrtc/base/stringencode.h" - -namespace cricket { - -enum MediaCapabilities { - AUDIO_RECV = 1 << 0, - AUDIO_SEND = 1 << 1, - VIDEO_RECV = 1 << 2, - VIDEO_SEND = 1 << 3, -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_MEDIACOMMON_H_ diff --git a/include/webrtc/media/base/mediaconstants.h b/include/webrtc/media/base/mediaconstants.h index 708ca5b..44d8c7e 100644 --- a/include/webrtc/media/base/mediaconstants.h +++ b/include/webrtc/media/base/mediaconstants.h @@ -29,6 +29,9 @@ extern const float kProcessCpuThreshold; extern const char kRtxCodecName[]; extern const char kRedCodecName[]; extern const char kUlpfecCodecName[]; +extern const char kFlexfecCodecName[]; + +extern const char kFlexfecFmtpRepairWindow[]; // Codec parameters extern const char kCodecParamAssociatedPayloadType[]; @@ -103,48 +106,20 @@ extern const char kCodecParamStartBitrate[]; extern const char kCodecParamMaxQuantization[]; extern const char kCodecParamPort[]; -// We put the data codec names here so callers of -// DataEngine::CreateChannel don't have to import rtpdataengine.h or -// sctpdataengine.h to get the codec names they want to pass in. -extern const int kGoogleRtpDataCodecId; +// We put the data codec names here so callers of DataEngine::CreateChannel +// don't have to import rtpdataengine.h to get the codec names they want to +// pass in. +extern const int kGoogleRtpDataCodecPlType; extern const char kGoogleRtpDataCodecName[]; // TODO(pthatcher): Find an id that won't conflict with anything. On // the other hand, it really shouldn't matter since the id won't be // used on the wire. -extern const int kGoogleSctpDataCodecId; +extern const int kGoogleSctpDataCodecPlType; extern const char kGoogleSctpDataCodecName[]; extern const char kComfortNoiseCodecName[]; -// Header extension for audio levels, as defined in -// http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03 -extern const int kRtpAudioLevelHeaderExtensionDefaultId; -extern const char kRtpAudioLevelHeaderExtension[]; - -// Header extension for RTP timestamp offset, see RFC 5450 for details: -// http://tools.ietf.org/html/rfc5450 -extern const int kRtpTimestampOffsetHeaderExtensionDefaultId; -extern const char kRtpTimestampOffsetHeaderExtension[]; - -// Header extension for absolute send time, see url for details: -// http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time -extern const int kRtpAbsoluteSenderTimeHeaderExtensionDefaultId; -extern const char kRtpAbsoluteSenderTimeHeaderExtension[]; - -// Header extension for coordination of video orientation, see url for details: -// http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ -// ts_126114v120700p.pdf -extern const int kRtpVideoRotationHeaderExtensionDefaultId; -extern const char kRtpVideoRotationHeaderExtension[]; -// We don't support 6 bit CVO. Added here for testing purpose. -extern const char kRtpVideoRotation6BitsHeaderExtensionForTesting[]; - -// Header extension for transport sequence number, see url for details: -// http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions -extern const int kRtpTransportSequenceNumberHeaderExtensionDefaultId; -extern const char kRtpTransportSequenceNumberHeaderExtension[]; - extern const char kVp8CodecName[]; extern const char kVp9CodecName[]; extern const char kH264CodecName[]; @@ -153,20 +128,9 @@ extern const char kH264CodecName[]; extern const char kH264FmtpProfileLevelId[]; extern const char kH264FmtpLevelAsymmetryAllowed[]; extern const char kH264FmtpPacketizationMode[]; +extern const char kH264FmtpSpropParameterSets[]; extern const char kH264ProfileLevelConstrainedBaseline[]; -extern const int kDefaultVp8PlType; -extern const int kDefaultVp9PlType; -extern const int kDefaultH264PlType; -extern const int kDefaultRedPlType; -extern const int kDefaultUlpfecType; -extern const int kDefaultRtxVp8PlType; -extern const int kDefaultRtxVp9PlType; -extern const int kDefaultRtxRedPlType; -extern const int kDefaultRtxH264PlType; - -extern const int kDefaultVideoMaxWidth; -extern const int kDefaultVideoMaxHeight; extern const int kDefaultVideoMaxFramerate; } // namespace cricket diff --git a/include/webrtc/media/base/mediaengine.h b/include/webrtc/media/base/mediaengine.h index 4446bd6..e5e64f7 100644 --- a/include/webrtc/media/base/mediaengine.h +++ b/include/webrtc/media/base/mediaengine.h @@ -18,14 +18,13 @@ #include #include -#include "webrtc/audio_state.h" +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" #include "webrtc/api/rtpparameters.h" #include "webrtc/base/fileutils.h" #include "webrtc/base/sigslotrepeater.h" +#include "webrtc/call/audio_state.h" #include "webrtc/media/base/codec.h" #include "webrtc/media/base/mediachannel.h" -#include "webrtc/media/base/mediacommon.h" -#include "webrtc/media/base/videocapturer.h" #include "webrtc/media/base/videocommon.h" #if defined(GOOGLE_CHROME_BUILD) || defined(CHROMIUM_BUILD) @@ -34,15 +33,14 @@ namespace webrtc { class AudioDeviceModule; +class AudioMixer; class Call; } namespace cricket { -class VideoCapturer; - struct RtpCapabilities { - std::vector header_extensions; + std::vector header_extensions; }; // MediaEngineInterface is an abstraction of a media engine which can be @@ -71,18 +69,13 @@ class MediaEngineInterface { const MediaConfig& config, const VideoOptions& options) = 0; - // Device configuration - // Gets the current speaker volume, as a value between 0 and 255. - virtual bool GetOutputVolume(int* level) = 0; - // Sets the current speaker volume, as a value between 0 and 255. - virtual bool SetOutputVolume(int level) = 0; - // Gets the current microphone level, as a value between 0 and 10. virtual int GetInputLevel() = 0; - virtual const std::vector& audio_codecs() = 0; + virtual const std::vector& audio_send_codecs() = 0; + virtual const std::vector& audio_recv_codecs() = 0; virtual RtpCapabilities GetAudioCapabilities() = 0; - virtual const std::vector& video_codecs() = 0; + virtual std::vector video_codecs() = 0; virtual RtpCapabilities GetVideoCapabilities() = 0; // Starts AEC dump using existing file, a maximum file size in bytes can be @@ -92,15 +85,6 @@ class MediaEngineInterface { // Stops recording AEC dump. virtual void StopAecDump() = 0; - - // Starts RtcEventLog using existing file. A maximum file size in bytes can be - // specified. Logging is stopped just before the size limit is exceeded. - // If max_size_bytes is set to a value <= 0, no limit will be used. - virtual bool StartRtcEventLog(rtc::PlatformFile file, - int64_t max_size_bytes) = 0; - - // Stops recording an RtcEventLog. - virtual void StopRtcEventLog() = 0; }; @@ -127,7 +111,11 @@ class MediaEngineFactory { template class CompositeMediaEngine : public MediaEngineInterface { public: - explicit CompositeMediaEngine(webrtc::AudioDeviceModule* adm) : voice_(adm) {} + CompositeMediaEngine(webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + rtc::scoped_refptr audio_mixer) + : voice_(adm, audio_decoder_factory, audio_mixer) {} virtual ~CompositeMediaEngine() {} virtual bool Init() { video_.Init(); @@ -148,25 +136,19 @@ class CompositeMediaEngine : public MediaEngineInterface { return video_.CreateChannel(call, config, options); } - virtual bool GetOutputVolume(int* level) { - return voice_.GetOutputVolume(level); - } - virtual bool SetOutputVolume(int level) { - return voice_.SetOutputVolume(level); - } - virtual int GetInputLevel() { return voice_.GetInputLevel(); } - virtual const std::vector& audio_codecs() { - return voice_.codecs(); + virtual const std::vector& audio_send_codecs() { + return voice_.send_codecs(); + } + virtual const std::vector& audio_recv_codecs() { + return voice_.recv_codecs(); } virtual RtpCapabilities GetAudioCapabilities() { return voice_.GetCapabilities(); } - virtual const std::vector& video_codecs() { - return video_.codecs(); - } + virtual std::vector video_codecs() { return video_.codecs(); } virtual RtpCapabilities GetVideoCapabilities() { return video_.GetCapabilities(); } @@ -179,28 +161,17 @@ class CompositeMediaEngine : public MediaEngineInterface { voice_.StopAecDump(); } - virtual bool StartRtcEventLog(rtc::PlatformFile file, - int64_t max_size_bytes) { - return voice_.StartRtcEventLog(file, max_size_bytes); - } - - virtual void StopRtcEventLog() { voice_.StopRtcEventLog(); } - protected: VOICE voice_; VIDEO video_; }; -enum DataChannelType { - DCT_NONE = 0, - DCT_RTP = 1, - DCT_SCTP = 2 -}; +enum DataChannelType { DCT_NONE = 0, DCT_RTP = 1, DCT_SCTP = 2, DCT_QUIC = 3 }; class DataEngineInterface { public: virtual ~DataEngineInterface() {} - virtual DataMediaChannel* CreateChannel(DataChannelType type) = 0; + virtual DataMediaChannel* CreateChannel(const MediaConfig& config) = 0; virtual const std::vector& data_codecs() = 0; }; diff --git a/include/webrtc/media/base/rtpdataengine.h b/include/webrtc/media/base/rtpdataengine.h index 0181e65..ca43494 100644 --- a/include/webrtc/media/base/rtpdataengine.h +++ b/include/webrtc/media/base/rtpdataengine.h @@ -15,7 +15,6 @@ #include #include -#include "webrtc/base/timing.h" #include "webrtc/media/base/mediachannel.h" #include "webrtc/media/base/mediaconstants.h" #include "webrtc/media/base/mediaengine.h" @@ -28,20 +27,14 @@ class RtpDataEngine : public DataEngineInterface { public: RtpDataEngine(); - virtual DataMediaChannel* CreateChannel(DataChannelType data_channel_type); + virtual DataMediaChannel* CreateChannel(const MediaConfig& config); virtual const std::vector& data_codecs() { return data_codecs_; } - // Mostly for testing with a fake clock. Ownership is passed in. - void SetTiming(rtc::Timing* timing) { - timing_.reset(timing); - } - private: std::vector data_codecs_; - std::unique_ptr timing_; }; // Keep track of sequence number and timestamp of an RTP stream. The @@ -68,17 +61,9 @@ class RtpClock { class RtpDataMediaChannel : public DataMediaChannel { public: - // Timing* Used for the RtpClock - explicit RtpDataMediaChannel(rtc::Timing* timing); - // Sets Timing == NULL, so you'll need to call set_timer() before - // using it. This is needed by FakeMediaEngine. - RtpDataMediaChannel(); + RtpDataMediaChannel(const MediaConfig& config); virtual ~RtpDataMediaChannel(); - void set_timing(rtc::Timing* timing) { - timing_ = timing; - } - virtual bool SetSendParameters(const DataSendParameters& params); virtual bool SetRecvParameters(const DataRecvParameters& params); virtual bool AddSendStream(const StreamParams& sp); @@ -98,20 +83,21 @@ class RtpDataMediaChannel : public DataMediaChannel { virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {} virtual void OnReadyToSend(bool ready) {} + virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) {} virtual bool SendData( const SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, SendDataResult* result); + virtual rtc::DiffServCodePoint PreferredDscp() const; private: - void Construct(rtc::Timing* timing); + void Construct(); bool SetMaxSendBandwidth(int bps); bool SetSendCodecs(const std::vector& codecs); bool SetRecvCodecs(const std::vector& codecs); bool sending_; bool receiving_; - rtc::Timing* timing_; std::vector send_codecs_; std::vector recv_codecs_; std::vector send_streams_; diff --git a/include/webrtc/media/base/rtpdump.h b/include/webrtc/media/base/rtpdump.h deleted file mode 100644 index 8ea7800..0000000 --- a/include/webrtc/media/base/rtpdump.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_RTPDUMP_H_ -#define WEBRTC_MEDIA_BASE_RTPDUMP_H_ - -#include - -#include -#include - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/bytebuffer.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/stream.h" - -namespace cricket { - -// We use the RTP dump file format compatible to the format used by rtptools -// (http://www.cs.columbia.edu/irt/software/rtptools/) and Wireshark -// (http://wiki.wireshark.org/rtpdump). In particular, the file starts with the -// first line "#!rtpplay1.0 address/port\n", followed by a 16 byte file header. -// For each packet, the file contains a 8 byte dump packet header, followed by -// the actual RTP or RTCP packet. - -enum RtpDumpPacketFilter { - PF_NONE = 0x0, - PF_RTPHEADER = 0x1, - PF_RTPPACKET = 0x3, // includes header - // PF_RTCPHEADER = 0x4, // TODO(juberti) - PF_RTCPPACKET = 0xC, // includes header - PF_ALL = 0xF -}; - -struct RtpDumpFileHeader { - RtpDumpFileHeader(int64_t start_ms, uint32_t s, uint16_t p); - void WriteToByteBuffer(rtc::ByteBufferWriter* buf); - - static const char kFirstLine[]; - static const size_t kHeaderLength = 16; - uint32_t start_sec; // start of recording, the seconds part. - uint32_t start_usec; // start of recording, the microseconds part. - uint32_t source; // network source (multicast address). - uint16_t port; // UDP port. - uint16_t padding; // 2 bytes padding. -}; - -struct RtpDumpPacket { - RtpDumpPacket() {} - - RtpDumpPacket(const void* d, size_t s, uint32_t elapsed, bool rtcp) - : elapsed_time(elapsed), original_data_len((rtcp) ? 0 : s) { - data.resize(s); - memcpy(&data[0], d, s); - } - - // In the rtpdump file format, RTCP packets have their data len set to zero, - // since RTCP has an internal length field. - bool is_rtcp() const { return original_data_len == 0; } - bool IsValidRtpPacket() const; - bool IsValidRtcpPacket() const; - // Get the payload type, sequence number, timestampe, and SSRC of the RTP - // packet. Return true and set the output parameter if successful. - bool GetRtpPayloadType(int* pt) const; - bool GetRtpSeqNum(int* seq_num) const; - bool GetRtpTimestamp(uint32_t* ts) const; - bool GetRtpSsrc(uint32_t* ssrc) const; - bool GetRtpHeaderLen(size_t* len) const; - // Get the type of the RTCP packet. Return true and set the output parameter - // if successful. - bool GetRtcpType(int* type) const; - - static const size_t kHeaderLength = 8; - uint32_t elapsed_time; // Milliseconds since the start of recording. - std::vector data; // The actual RTP or RTCP packet. - size_t original_data_len; // The original length of the packet; may be - // greater than data.size() if only part of the - // packet was recorded. -}; - -class RtpDumpReader { - public: - explicit RtpDumpReader(rtc::StreamInterface* stream) - : stream_(stream), - file_header_read_(false), - first_line_and_file_header_len_(0), - start_time_ms_(0), - ssrc_override_(0) { - } - virtual ~RtpDumpReader() {} - - // Use the specified ssrc, rather than the ssrc from dump, for RTP packets. - void SetSsrc(uint32_t ssrc); - virtual rtc::StreamResult ReadPacket(RtpDumpPacket* packet); - - protected: - rtc::StreamResult ReadFileHeader(); - bool RewindToFirstDumpPacket() { - return stream_->SetPosition(first_line_and_file_header_len_); - } - - private: - // Check if its matches "#!rtpplay1.0 address/port\n". - bool CheckFirstLine(const std::string& first_line); - - rtc::StreamInterface* stream_; - bool file_header_read_; - size_t first_line_and_file_header_len_; - int64_t start_time_ms_; - uint32_t ssrc_override_; - - RTC_DISALLOW_COPY_AND_ASSIGN(RtpDumpReader); -}; - -// RtpDumpLoopReader reads RTP dump packets from the input stream and rewinds -// the stream when it ends. RtpDumpLoopReader maintains the elapsed time, the -// RTP sequence number and the RTP timestamp properly. RtpDumpLoopReader can -// handle both RTP dump and RTCP dump. We assume that the dump does not mix -// RTP packets and RTCP packets. -class RtpDumpLoopReader : public RtpDumpReader { - public: - explicit RtpDumpLoopReader(rtc::StreamInterface* stream); - virtual rtc::StreamResult ReadPacket(RtpDumpPacket* packet); - - private: - // During the first loop, update the statistics, including packet count, frame - // count, timestamps, and sequence number, of the input stream. - void UpdateStreamStatistics(const RtpDumpPacket& packet); - - // At the end of first loop, calculate elapsed_time_increases_, - // rtp_seq_num_increase_, and rtp_timestamp_increase_. - void CalculateIncreases(); - - // During the second and later loops, update the elapsed time of the dump - // packet. If the dumped packet is a RTP packet, update its RTP sequence - // number and timestamp as well. - void UpdateDumpPacket(RtpDumpPacket* packet); - - int loop_count_; - // How much to increase the elapsed time, RTP sequence number, RTP timestampe - // for each loop. They are calcualted with the variables below during the - // first loop. - uint32_t elapsed_time_increases_; - int rtp_seq_num_increase_; - uint32_t rtp_timestamp_increase_; - // How many RTP packets and how many payload frames in the input stream. RTP - // packets belong to the same frame have the same RTP timestamp, different - // dump timestamp, and different RTP sequence number. - uint32_t packet_count_; - uint32_t frame_count_; - // The elapsed time, RTP sequence number, and RTP timestamp of the first and - // the previous dump packets in the input stream. - uint32_t first_elapsed_time_; - int first_rtp_seq_num_; - int64_t first_rtp_timestamp_; - uint32_t prev_elapsed_time_; - int prev_rtp_seq_num_; - int64_t prev_rtp_timestamp_; - - RTC_DISALLOW_COPY_AND_ASSIGN(RtpDumpLoopReader); -}; - -class RtpDumpWriter { - public: - explicit RtpDumpWriter(rtc::StreamInterface* stream); - - // Filter to control what packets we actually record. - void set_packet_filter(int filter); - // Write a RTP or RTCP packet. The parameters data points to the packet and - // data_len is its length. - rtc::StreamResult WriteRtpPacket(const void* data, size_t data_len) { - return WritePacket(data, data_len, GetElapsedTime(), false); - } - rtc::StreamResult WriteRtcpPacket(const void* data, size_t data_len) { - return WritePacket(data, data_len, GetElapsedTime(), true); - } - rtc::StreamResult WritePacket(const RtpDumpPacket& packet) { - return WritePacket(&packet.data[0], packet.data.size(), packet.elapsed_time, - packet.is_rtcp()); - } - uint32_t GetElapsedTime() const; - - bool GetDumpSize(size_t* size) { - // Note that we use GetPosition(), rather than GetSize(), to avoid flush the - // stream per write. - return stream_ && size && stream_->GetPosition(size); - } - - protected: - rtc::StreamResult WriteFileHeader(); - - private: - rtc::StreamResult WritePacket(const void* data, - size_t data_len, - uint32_t elapsed, - bool rtcp); - size_t FilterPacket(const void* data, size_t data_len, bool rtcp); - rtc::StreamResult WriteToStream(const void* data, size_t data_len); - - rtc::StreamInterface* stream_; - int packet_filter_; - bool file_header_written_; - int64_t start_time_ms_; // Time when the record starts. - // If writing to the stream takes longer than this many ms, log a warning. - int64_t warn_slow_writes_delay_; - RTC_DISALLOW_COPY_AND_ASSIGN(RtpDumpWriter); -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_RTPDUMP_H_ diff --git a/include/webrtc/media/base/screencastid.h b/include/webrtc/media/base/screencastid.h deleted file mode 100644 index fdcfbe6..0000000 --- a/include/webrtc/media/base/screencastid.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Author: thorcarpenter@google.com (Thor Carpenter) -// -// Defines variant class ScreencastId that combines WindowId and DesktopId. - -#ifndef WEBRTC_MEDIA_BASE_SCREENCASTID_H_ -#define WEBRTC_MEDIA_BASE_SCREENCASTID_H_ - -#include -#include - -#include "webrtc/base/window.h" -#include "webrtc/base/windowpicker.h" - -namespace cricket { - -class ScreencastId; -typedef std::vector ScreencastIdList; - -// Used for identifying a window or desktop to be screencast. -class ScreencastId { - public: - enum Type { INVALID, WINDOW, DESKTOP }; - - // Default constructor indicates invalid ScreencastId. - ScreencastId() : type_(INVALID) {} - explicit ScreencastId(const rtc::WindowId& id) - : type_(WINDOW), window_(id) { - } - explicit ScreencastId(const rtc::DesktopId& id) - : type_(DESKTOP), desktop_(id) { - } - - Type type() const { return type_; } - const rtc::WindowId& window() const { return window_; } - const rtc::DesktopId& desktop() const { return desktop_; } - - // Title is an optional parameter. - const std::string& title() const { return title_; } - void set_title(const std::string& desc) { title_ = desc; } - - bool IsValid() const { - if (type_ == INVALID) { - return false; - } else if (type_ == WINDOW) { - return window_.IsValid(); - } else { - return desktop_.IsValid(); - } - } - bool IsWindow() const { return type_ == WINDOW; } - bool IsDesktop() const { return type_ == DESKTOP; } - bool EqualsId(const ScreencastId& other) const { - if (type_ != other.type_) { - return false; - } - if (type_ == INVALID) { - return true; - } else if (type_ == WINDOW) { - return window_.Equals(other.window()); - } - return desktop_.Equals(other.desktop()); - } - - // T is assumed to be WindowDescription or DesktopDescription. - template - static cricket::ScreencastIdList Convert(const std::vector& list) { - ScreencastIdList screencast_list; - screencast_list.reserve(list.size()); - for (typename std::vector::const_iterator it = list.begin(); - it != list.end(); ++it) { - ScreencastId id(it->id()); - id.set_title(it->title()); - screencast_list.push_back(id); - } - return screencast_list; - } - - private: - Type type_; - rtc::WindowId window_; - rtc::DesktopId desktop_; - std::string title_; // Optional. -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_SCREENCASTID_H_ diff --git a/include/webrtc/media/base/streamparams.h b/include/webrtc/media/base/streamparams.h index 5b9d7bd..75d8280 100644 --- a/include/webrtc/media/base/streamparams.h +++ b/include/webrtc/media/base/streamparams.h @@ -26,17 +26,19 @@ #ifndef WEBRTC_MEDIA_BASE_STREAMPARAMS_H_ #define WEBRTC_MEDIA_BASE_STREAMPARAMS_H_ +#include + #include #include #include #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/constructormagic.h" namespace cricket { extern const char kFecSsrcGroupSemantics[]; +extern const char kFecFrSsrcGroupSemantics[]; extern const char kFidSsrcGroupSemantics[]; extern const char kSimSsrcGroupSemantics[]; @@ -112,16 +114,28 @@ struct StreamParams { // Convenience function to add an FID ssrc for a primary_ssrc // that's already been added. - inline bool AddFidSsrc(uint32_t primary_ssrc, uint32_t fid_ssrc) { + bool AddFidSsrc(uint32_t primary_ssrc, uint32_t fid_ssrc) { return AddSecondarySsrc(kFidSsrcGroupSemantics, primary_ssrc, fid_ssrc); } // Convenience function to lookup the FID ssrc for a primary_ssrc. // Returns false if primary_ssrc not found or FID not defined for it. - inline bool GetFidSsrc(uint32_t primary_ssrc, uint32_t* fid_ssrc) const { + bool GetFidSsrc(uint32_t primary_ssrc, uint32_t* fid_ssrc) const { return GetSecondarySsrc(kFidSsrcGroupSemantics, primary_ssrc, fid_ssrc); } + // Convenience function to add an FEC-FR ssrc for a primary_ssrc + // that's already been added. + bool AddFecFrSsrc(uint32_t primary_ssrc, uint32_t fecfr_ssrc) { + return AddSecondarySsrc(kFecFrSsrcGroupSemantics, primary_ssrc, fecfr_ssrc); + } + + // Convenience function to lookup the FEC-FR ssrc for a primary_ssrc. + // Returns false if primary_ssrc not found or FEC-FR not defined for it. + bool GetFecFrSsrc(uint32_t primary_ssrc, uint32_t* fecfr_ssrc) const { + return GetSecondarySsrc(kFecFrSsrcGroupSemantics, primary_ssrc, fecfr_ssrc); + } + // Convenience to get all the SIM SSRCs if there are SIM ssrcs, or // the first SSRC otherwise. void GetPrimarySsrcs(std::vector* ssrcs) const; @@ -289,8 +303,8 @@ inline bool RemoveStreamByIds(StreamParamsVec* streams, } // Checks if |sp| defines parameters for a single primary stream. There may -// be an RTX stream associated with the primary stream. Leaving as non-static so -// we can test this function. +// be an RTX stream or a FlexFEC stream (or both) associated with the primary +// stream. Leaving as non-static so we can test this function. bool IsOneSsrcStream(const StreamParams& sp); // Checks if |sp| defines parameters for one Simulcast stream. There may be RTX diff --git a/include/webrtc/media/base/test/mock_mediachannel.h b/include/webrtc/media/base/test/mock_mediachannel.h new file mode 100644 index 0000000..6f7e2e5 --- /dev/null +++ b/include/webrtc/media/base/test/mock_mediachannel.h @@ -0,0 +1,35 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_BASE_TEST_MOCK_MEDIACHANNEL_H_ +#define WEBRTC_MEDIA_BASE_TEST_MOCK_MEDIACHANNEL_H_ + +#include "webrtc/media/base/fakemediaengine.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockVideoMediaChannel : public cricket::FakeVideoMediaChannel { + public: + MockVideoMediaChannel() : + cricket::FakeVideoMediaChannel(NULL, cricket::VideoOptions()) {} + MOCK_METHOD1(GetStats, bool(cricket::VideoMediaInfo*)); +}; + +class MockVoiceMediaChannel : public cricket::FakeVoiceMediaChannel { + public: + MockVoiceMediaChannel() : + cricket::FakeVoiceMediaChannel(NULL, cricket::AudioOptions()) {} + MOCK_METHOD1(GetStats, bool(cricket::VoiceMediaInfo*)); +}; + +} // namespace webrtc + +#endif // WEBRTC_MEDIA_BASE_TEST_MOCK_MEDIACHANNEL_H_ diff --git a/include/webrtc/media/base/testutils.h b/include/webrtc/media/base/testutils.h index b73d8f6..5c3d1a7 100644 --- a/include/webrtc/media/base/testutils.h +++ b/include/webrtc/media/base/testutils.h @@ -29,6 +29,10 @@ class ByteBufferWriter; class StreamInterface; } +namespace webrtc { +class VideoFrame; +} + namespace cricket { // Returns size of 420 image with rounding on chroma for odd sizes. @@ -43,7 +47,6 @@ template inline std::vector MakeVector(const T a[], size_t s) { struct RtpDumpPacket; class RtpDumpWriter; -class VideoFrame; struct RawRtpPacket { void WriteToByteBuffer(uint32_t in_ssrc, rtc::ByteBufferWriter* buf) const; @@ -76,83 +79,32 @@ struct RawRtcpPacket { char payload[16]; }; -class RtpTestUtility { - public: - static size_t GetTestPacketCount(); - - // Write the first count number of kTestRawRtcpPackets or kTestRawRtpPackets, - // depending on the flag rtcp. If it is RTP, use the specified SSRC. Return - // true if successful. - static bool WriteTestPackets(size_t count, - bool rtcp, - uint32_t rtp_ssrc, - RtpDumpWriter* writer); - - // Loop read the first count number of packets from the specified stream. - // Verify the elapsed time of the dump packets increase monotonically. If the - // stream is a RTP stream, verify the RTP sequence number, timestamp, and - // payload. If the stream is a RTCP stream, verify the RTCP header and - // payload. - static bool VerifyTestPacketsFromStream(size_t count, - rtc::StreamInterface* stream, - uint32_t ssrc); - - // Verify the dump packet is the same as the raw RTP packet. - static bool VerifyPacket(const RtpDumpPacket* dump, - const RawRtpPacket* raw, - bool header_only); - - static const uint32_t kDefaultSsrc = 1; - static const uint32_t kRtpTimestampIncrease = 90; - static const uint32_t kDefaultTimeIncrease = 30; - static const uint32_t kElapsedTimeInterval = 10; - static const RawRtpPacket kTestRawRtpPackets[]; - static const RawRtcpPacket kTestRawRtcpPackets[]; - - private: - RtpTestUtility() {} -}; - // Test helper for testing VideoCapturer implementations. -class VideoCapturerListener : public sigslot::has_slots<> { +class VideoCapturerListener + : public sigslot::has_slots<>, + public rtc::VideoSinkInterface { public: explicit VideoCapturerListener(VideoCapturer* cap); + ~VideoCapturerListener(); CaptureState last_capture_state() const { return last_capture_state_; } int frame_count() const { return frame_count_; } - uint32_t frame_fourcc() const { return frame_fourcc_; } int frame_width() const { return frame_width_; } int frame_height() const { return frame_height_; } - uint32_t frame_size() const { return frame_size_; } bool resolution_changed() const { return resolution_changed_; } void OnStateChange(VideoCapturer* capturer, CaptureState state); - void OnFrameCaptured(VideoCapturer* capturer, const CapturedFrame* frame); + void OnFrame(const webrtc::VideoFrame& frame) override; private: + VideoCapturer* capturer_; CaptureState last_capture_state_; int frame_count_; - uint32_t frame_fourcc_; int frame_width_; int frame_height_; - uint32_t frame_size_; bool resolution_changed_; }; -class ScreencastEventCatcher : public sigslot::has_slots<> { - public: - ScreencastEventCatcher() : ssrc_(0), ev_(rtc::WE_RESIZE) { } - uint32_t ssrc() const { return ssrc_; } - rtc::WindowEvent event() const { return ev_; } - void OnEvent(uint32_t ssrc, rtc::WindowEvent ev) { - ssrc_ = ssrc; - ev_ = ev; - } - private: - uint32_t ssrc_; - rtc::WindowEvent ev_; -}; - class VideoMediaErrorCatcher : public sigslot::has_slots<> { public: VideoMediaErrorCatcher() : ssrc_(0), error_(VideoMediaChannel::ERROR_NONE) { } @@ -167,42 +119,6 @@ class VideoMediaErrorCatcher : public sigslot::has_slots<> { VideoMediaChannel::Error error_; }; -// Returns the absolute path to a file in the testdata/ directory. -std::string GetTestFilePath(const std::string& filename); - -// PSNR formula: psnr = 10 * log10 (Peak Signal^2 / mse) -// sse is set to a small number for identical frames or sse == 0 -static inline double ComputePSNR(double sse, double count) { - return libyuv::SumSquareErrorToPsnr(static_cast(sse), - static_cast(count)); -} - -static inline double ComputeSumSquareError(const uint8_t* org, - const uint8_t* rec, - int size) { - return static_cast(libyuv::ComputeSumSquareError(org, rec, size)); -} - -// Loads the image with the specified prefix and size into |out|. -bool LoadPlanarYuvTestImage(const std::string& prefix, - int width, - int height, - uint8_t* out); - -// Dumps the YUV image out to a file, for visual inspection. -// PYUV tool can be used to view dump files. -void DumpPlanarYuvTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h); - -// Dumps the ARGB image out to a file, for visual inspection. -// ffplay tool can be used to view dump files. -void DumpPlanarArgbTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h); - // Checks whether |codecs| contains |codec|; checks using Codec::Matches(). template bool ContainsMatchingCodec(const std::vector& codecs, const C& codec) { @@ -225,6 +141,12 @@ cricket::StreamParams CreateSimWithRtxStreamParams( const std::vector& ssrcs, const std::vector& rtx_ssrcs); +// Create StreamParams with single primary SSRC and corresponding FlexFEC SSRC. +cricket::StreamParams CreatePrimaryWithFecFrStreamParams( + const std::string& cname, + uint32_t primary_ssrc, + uint32_t flexfec_ssrc); + } // namespace cricket #endif // WEBRTC_MEDIA_BASE_TESTUTILS_H_ diff --git a/include/webrtc/media/base/videoadapter.h b/include/webrtc/media/base/videoadapter.h index 2db0ada..caaab3c 100644 --- a/include/webrtc/media/base/videoadapter.h +++ b/include/webrtc/media/base/videoadapter.h @@ -25,19 +25,16 @@ namespace cricket { class VideoAdapter { public: VideoAdapter(); + VideoAdapter(int required_resolution_alignment); virtual ~VideoAdapter(); - // Sets the expected frame interval. This controls how often frames should - // be dropped if |OnOutputFormatRequest| is called with a lower frame - // interval. - void SetExpectedInputFrameInterval(int64_t interval); - - // Return the adapted resolution given the input resolution. The input - // resolution should first be cropped to the specified resolution, and then - // scaled to the final output resolution. The output resolution will be 0x0 if - // the frame should be dropped. - void AdaptFrameResolution(int in_width, + // Return the adapted resolution and cropping parameters given the + // input resolution. The input frame should first be cropped, then + // scaled to the final output resolution. Returns true if the frame + // should be adapted, and false if it should be dropped. + bool AdaptFrameResolution(int in_width, int in_height, + int64_t in_timestamp_ns, int* cropped_width, int* cropped_height, int* out_width, @@ -51,28 +48,35 @@ class VideoAdapter { // 720x1280 is requested. void OnOutputFormatRequest(const VideoFormat& format); - // Requests the output frame size from |AdaptFrameResolution| to not have - // more than |max_pixel_count| pixels and have "one step" up more pixels than - // max_pixel_count_step_up. - void OnResolutionRequest(rtc::Optional max_pixel_count, - rtc::Optional max_pixel_count_step_up); + // Requests the output frame size from |AdaptFrameResolution| to have as close + // as possible to |target_pixel_count|, but no more than |max_pixel_count| + // pixels. If |target_pixel_count| is not set, treat it as being equal to + // |max_pixel_count|. If |max_pixel_count| is not set, treat is as being the + // highest resolution available. + void OnResolutionRequest(const rtc::Optional& target_pixel_count, + const rtc::Optional& max_pixel_count); private: + // Determine if frame should be dropped based on input fps and requested fps. + bool KeepFrame(int64_t in_timestamp_ns); + int frames_in_; // Number of input frames. int frames_out_; // Number of output frames. int frames_scaled_; // Number of frames scaled. int adaption_changes_; // Number of changes in scale factor. int previous_width_; // Previous adapter output width. int previous_height_; // Previous adapter output height. - int input_interval_ GUARDED_BY(critical_section_); - int64_t interval_next_frame_ GUARDED_BY(critical_section_); + // Resolution must be divisible by this factor. + const int required_resolution_alignment_; + // The target timestamp for the next frame based on requested format. + rtc::Optional next_frame_timestamp_ns_ GUARDED_BY(critical_section_); // Max number of pixels requested via calls to OnOutputFormatRequest, // OnResolutionRequest respectively. // The adapted output format is the minimum of these. rtc::Optional requested_format_ GUARDED_BY(critical_section_); + int resolution_request_target_pixel_count_ GUARDED_BY(critical_section_); int resolution_request_max_pixel_count_ GUARDED_BY(critical_section_); - int resolution_request_max_pixel_count_step_up_ GUARDED_BY(critical_section_); // The critical section to protect the above variables. rtc::CriticalSection critical_section_; diff --git a/include/webrtc/media/base/videobroadcaster.h b/include/webrtc/media/base/videobroadcaster.h index 764c749..ccf5b3d 100644 --- a/include/webrtc/media/base/videobroadcaster.h +++ b/include/webrtc/media/base/videobroadcaster.h @@ -15,12 +15,11 @@ #include #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_checker.h" -#include "webrtc/media/base/videoframe.h" #include "webrtc/media/base/videosinkinterface.h" #include "webrtc/media/base/videosourcebase.h" -#include "webrtc/media/engine/webrtcvideoframe.h" namespace rtc { @@ -31,12 +30,12 @@ namespace rtc { // Video frames can be broadcasted on any thread. I.e VideoBroadcaster::OnFrame // can be called on any thread. class VideoBroadcaster : public VideoSourceBase, - public VideoSinkInterface { + public VideoSinkInterface { public: VideoBroadcaster(); - void AddOrUpdateSink(VideoSinkInterface* sink, + void AddOrUpdateSink(VideoSinkInterface* sink, const VideoSinkWants& wants) override; - void RemoveSink(VideoSinkInterface* sink) override; + void RemoveSink(VideoSinkInterface* sink) override; // Returns true if the next frame will be delivered to at least one sink. bool frame_wanted() const; @@ -45,18 +44,23 @@ class VideoBroadcaster : public VideoSourceBase, // aggregated by all VideoSinkWants from all sinks. VideoSinkWants wants() const; - void OnFrame(const cricket::VideoFrame& frame) override; + // This method ensures that if a sink sets rotation_applied == true, + // it will never receive a frame with pending rotation. Our caller + // may pass in frames without precise synchronization with changes + // to the VideoSinkWants. + void OnFrame(const webrtc::VideoFrame& frame) override; protected: void UpdateWants() EXCLUSIVE_LOCKS_REQUIRED(sinks_and_wants_lock_); - const cricket::VideoFrame& GetBlackFrame(const cricket::VideoFrame& frame) + const rtc::scoped_refptr& GetBlackFrameBuffer( + int width, int height) EXCLUSIVE_LOCKS_REQUIRED(sinks_and_wants_lock_); ThreadChecker thread_checker_; rtc::CriticalSection sinks_and_wants_lock_; VideoSinkWants current_wants_ GUARDED_BY(sinks_and_wants_lock_); - std::unique_ptr black_frame_; + rtc::scoped_refptr black_frame_buffer_; }; } // namespace rtc diff --git a/include/webrtc/media/base/videocapturer.h b/include/webrtc/media/base/videocapturer.h index edc6cd3..510063b 100644 --- a/include/webrtc/media/base/videocapturer.h +++ b/include/webrtc/media/base/videocapturer.h @@ -13,22 +13,32 @@ #ifndef WEBRTC_MEDIA_BASE_VIDEOCAPTURER_H_ #define WEBRTC_MEDIA_BASE_VIDEOCAPTURER_H_ +#include + #include #include #include #include -#include "webrtc/base/basictypes.h" +// TODO(nisse): Transition hack, some downstream applications expect that +// including this file declares I420Buffer and NativeHandleBuffer. Delete after +// users of these classes are fixed to include the right headers. +#include "webrtc/api/video/i420_buffer.h" +#include "webrtc/common_video/include/video_frame_buffer.h" + #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/media/base/videosourceinterface.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread_checker.h" +#include "webrtc/base/timestampaligner.h" #include "webrtc/media/base/videoadapter.h" #include "webrtc/media/base/videobroadcaster.h" #include "webrtc/media/base/videocommon.h" -#include "webrtc/media/base/videoframefactory.h" +namespace webrtc { +class VideoFrame; +} namespace cricket { @@ -42,40 +52,6 @@ enum CaptureState { CS_FAILED, // The capturer failed to start. }; -class VideoFrame; - -struct CapturedFrame { - static const uint32_t kFrameHeaderSize = 40; // Size from width to data_size. - static const uint32_t kUnknownDataSize = 0xFFFFFFFF; - - CapturedFrame(); - - // Get the number of bytes of the frame data. If data_size is known, return - // it directly. Otherwise, calculate the size based on width, height, and - // fourcc. Return true if succeeded. - bool GetDataSize(uint32_t* size) const; - - // The width and height of the captured frame could be different from those - // of VideoFormat. Once the first frame is captured, the width, height, - // fourcc, pixel_width, and pixel_height should keep the same over frames. - int width; // in number of pixels - int height; // in number of pixels - uint32_t fourcc; // compression - uint32_t pixel_width; // width of a pixel, default is 1 - uint32_t pixel_height; // height of a pixel, default is 1 - int64_t time_stamp; // timestamp of when the frame was captured, in unix - // time with nanosecond units. - uint32_t data_size; // number of bytes of the frame data - - webrtc::VideoRotation rotation; // rotation in degrees of the frame. - - void* data; // pointer to the frame data. This object allocates the - // memory or points to an existing memory. - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(CapturedFrame); -}; - // VideoCapturer is an abstract class that defines the interfaces for video // capturing. The subclasses implement the video capturer for various types of // capturers and various platforms. @@ -103,7 +79,7 @@ struct CapturedFrame { // thread safe. // class VideoCapturer : public sigslot::has_slots<>, - public rtc::VideoSourceInterface { + public rtc::VideoSourceInterface { public: VideoCapturer(); @@ -168,7 +144,7 @@ class VideoCapturer : public sigslot::has_slots<>, return capture_state_; } - virtual bool GetApplyRotation() { return apply_rotation_; } + virtual bool apply_rotation() { return apply_rotation_; } // Returns true if the capturer is screencasting. This can be used to // implement screencast specific behavior. @@ -191,13 +167,6 @@ class VideoCapturer : public sigslot::has_slots<>, // Signal all capture state changes that are not a direct result of calling // Start(). sigslot::signal2 SignalStateChange; - // Frame callbacks are multithreaded to allow disconnect and connect to be - // called concurrently. It also ensures that it is safe to call disconnect - // at any time which is needed since the signal may be called from an - // unmarshalled thread owned by the VideoCapturer. - // Signal the captured frame to downstream. - sigslot::signal2 SignalFrameCaptured; // If true, run video adaptation. By default, video adaptation is enabled // and users must call video_adapter()->OnOutputFormatRequest() @@ -207,29 +176,53 @@ class VideoCapturer : public sigslot::has_slots<>, enable_video_adapter_ = enable_video_adapter; } - // Takes ownership. - void set_frame_factory(VideoFrameFactory* frame_factory); - bool GetInputSize(int* width, int* height); // Implements VideoSourceInterface - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; protected: // OnSinkWantsChanged can be overridden to change the default behavior // when a sink changes its VideoSinkWants by calling AddOrUpdateSink. virtual void OnSinkWantsChanged(const rtc::VideoSinkWants& wants); - // Callback attached to SignalFrameCaptured where SignalVideoFrames is called. - void OnFrameCaptured(VideoCapturer* video_capturer, - const CapturedFrame* captured_frame); - - // Called when a frame has been captured and converted to a VideoFrame. - // OnFrame can be called directly by an implementation that does not use - // SignalFrameCaptured or OnFrameCaptured. - void OnFrame(VideoCapturer* capturer, const VideoFrame* frame); + // Reports the appropriate frame size after adaptation. Returns true + // if a frame is wanted. Returns false if there are no interested + // sinks, or if the VideoAdapter decides to drop the frame. + + // This function also implements timestamp translation/filtering. + // |camera_time_ns| is the camera's timestamp for the captured + // frame; it is expected to have good accuracy, but it may use an + // arbitrary epoch and a small possibly free-running with a frequency + // slightly different from the system clock. |system_time_us| is the + // monotonic system time (in the same scale as rtc::TimeMicros) when + // the frame was captured; the application is expected to read the + // system time as soon as possible after frame capture, but it may + // suffer scheduling jitter or poor system clock resolution. The + // output |translated_camera_time_us| is a combined timestamp, + // taking advantage of the supposedly higher accuracy in the camera + // timestamp, but using the same epoch and frequency as system time. + bool AdaptFrame(int width, + int height, + int64_t camera_time_us, + int64_t system_time_us, + int* out_width, + int* out_height, + int* crop_width, + int* crop_height, + int* crop_x, + int* crop_y, + int64_t* translated_camera_time_us); + + // Called when a frame has been captured and converted to a + // VideoFrame. OnFrame can be called directly by an implementation + // that does not use SignalFrameCaptured or OnFrameCaptured. The + // orig_width and orig_height are used only to produce stats. + void OnFrame(const webrtc::VideoFrame& frame, + int orig_width, + int orig_height); VideoAdapter* video_adapter() { return &video_adapter_; } @@ -246,15 +239,9 @@ class VideoCapturer : public sigslot::has_slots<>, void SetCaptureFormat(const VideoFormat* format) { capture_format_.reset(format ? new VideoFormat(*format) : NULL); - if (capture_format_) { - ASSERT(capture_format_->interval > 0 && - "Capture format expected to have positive interval."); - video_adapter_.SetExpectedInputFrameInterval(capture_format_->interval); - } } void SetSupportedFormats(const std::vector& formats); - VideoFrameFactory* frame_factory() { return frame_factory_.get(); } private: void Construct(); @@ -264,21 +251,17 @@ class VideoCapturer : public sigslot::has_slots<>, int64_t GetFormatDistance(const VideoFormat& desired, const VideoFormat& supported); - // Convert captured frame to readable string for LOG messages. - std::string ToString(const CapturedFrame* frame) const; - // Updates filtered_supported_formats_ so that it contains the formats in // supported_formats_ that fulfill all applied restrictions. void UpdateFilteredSupportedFormats(); // Returns true if format doesn't fulfill all applied restrictions. bool ShouldFilterFormat(const VideoFormat& format) const; - void UpdateInputSize(const CapturedFrame* captured_frame); + void UpdateInputSize(int width, int height); rtc::ThreadChecker thread_checker_; std::string id_; CaptureState capture_state_; - std::unique_ptr frame_factory_; std::unique_ptr capture_format_; std::vector supported_formats_; std::unique_ptr max_format_; @@ -298,9 +281,12 @@ class VideoCapturer : public sigslot::has_slots<>, int input_width_ GUARDED_BY(frame_stats_crit_); int input_height_ GUARDED_BY(frame_stats_crit_); - // Whether capturer should apply rotation to the frame before signaling it. + // Whether capturer should apply rotation to the frame before + // passing it on to the registered sinks. bool apply_rotation_; + // State for the timestamp translation. + rtc::TimestampAligner timestamp_aligner_; RTC_DISALLOW_COPY_AND_ASSIGN(VideoCapturer); }; diff --git a/include/webrtc/media/base/videocapturerfactory.h b/include/webrtc/media/base/videocapturerfactory.h index 86f7042..b6f886b 100644 --- a/include/webrtc/media/base/videocapturerfactory.h +++ b/include/webrtc/media/base/videocapturerfactory.h @@ -11,8 +11,9 @@ #ifndef WEBRTC_MEDIA_BASE_VIDEOCAPTURERFACTORY_H_ #define WEBRTC_MEDIA_BASE_VIDEOCAPTURERFACTORY_H_ +#include + #include "webrtc/media/base/device.h" -#include "webrtc/media/base/screencastid.h" namespace cricket { @@ -23,15 +24,7 @@ class VideoDeviceCapturerFactory { VideoDeviceCapturerFactory() {} virtual ~VideoDeviceCapturerFactory() {} - virtual VideoCapturer* Create(const Device& device) = 0; -}; - -class ScreenCapturerFactory { - public: - ScreenCapturerFactory() {} - virtual ~ScreenCapturerFactory() {} - - virtual VideoCapturer* Create(const ScreencastId& screenid) = 0; + virtual std::unique_ptr Create(const Device& device) = 0; }; } // namespace cricket diff --git a/include/webrtc/media/base/videocommon.h b/include/webrtc/media/base/videocommon.h index 757100b..47cfb85 100644 --- a/include/webrtc/media/base/videocommon.h +++ b/include/webrtc/media/base/videocommon.h @@ -13,9 +13,10 @@ #ifndef WEBRTC_MEDIA_BASE_VIDEOCOMMON_H_ // NOLINT #define WEBRTC_MEDIA_BASE_VIDEOCOMMON_H_ +#include + #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/timeutils.h" namespace cricket { diff --git a/include/webrtc/media/base/videoengine_unittest.h b/include/webrtc/media/base/videoengine_unittest.h index 394b9c9..7758c1e 100644 --- a/include/webrtc/media/base/videoengine_unittest.h +++ b/include/webrtc/media/base/videoengine_unittest.h @@ -18,7 +18,8 @@ #include "webrtc/base/bytebuffer.h" #include "webrtc/base/gunit.h" #include "webrtc/base/timeutils.h" -#include "webrtc/call.h" +#include "webrtc/call/call.h" +#include "webrtc/logging/rtc_event_log/rtc_event_log.h" #include "webrtc/media/base/fakenetworkinterface.h" #include "webrtc/media/base/fakevideocapturer.h" #include "webrtc/media/base/fakevideorenderer.h" @@ -49,37 +50,29 @@ static const uint32_t kDefaultReceiveSsrc = 0; static const uint32_t kSsrc = 1234u; static const uint32_t kRtxSsrc = 4321u; static const uint32_t kSsrcs4[] = {1, 2, 3, 4}; - -inline bool IsEqualRes(const cricket::VideoCodec& a, int w, int h, int fps) { - return a.width == w && a.height == h && a.framerate == fps; -} +static const int kVideoWidth = 640; +static const int kVideoHeight = 360; +static const int kFramerate = 30; inline bool IsEqualCodec(const cricket::VideoCodec& a, const cricket::VideoCodec& b) { - return a.id == b.id && a.name == b.name && - IsEqualRes(a, b.width, b.height, b.framerate); + return a.id == b.id && a.name == b.name; } namespace std { inline std::ostream& operator<<(std::ostream& s, const cricket::VideoCodec& c) { - s << "{" << c.name << "(" << c.id << "), " - << c.width << "x" << c.height << "x" << c.framerate << "}"; + s << "{" << c.name << "(" << c.id << ")" + << "}"; return s; } } // namespace std -inline int TimeBetweenSend(const cricket::VideoCodec& codec) { - return static_cast( - cricket::VideoFormat::FpsToInterval(codec.framerate) / - rtc::kNumNanosecsPerMillisec); -} - template class VideoMediaChannelTest : public testing::Test, public sigslot::has_slots<> { protected: VideoMediaChannelTest() - : call_(webrtc::Call::Create(webrtc::Call::Config())) {} + : call_(webrtc::Call::Create(webrtc::Call::Config(&event_log_))) {} virtual cricket::VideoCodec DefaultCodec() = 0; @@ -89,8 +82,15 @@ class VideoMediaChannelTest : public testing::Test, virtual void SetUp() { engine_.Init(); - channel_.reset(engine_.CreateChannel(call_.get(), cricket::MediaConfig(), + cricket::MediaConfig media_config; + // Disabling cpu overuse detection actually disables quality scaling too; it + // implies DegradationPreference kMaintainResolution. Automatic scaling + // needs to be disabled, otherwise, tests which check the size of received + // frames become flaky. + media_config.video.enable_cpu_overuse_detection = false; + channel_.reset(engine_.CreateChannel(call_.get(), media_config, cricket::VideoOptions())); + channel_->OnReadyToSend(true); EXPECT_TRUE(channel_.get() != NULL); network_interface_.SetDestination(channel_.get()); channel_->SetInterface(&network_interface_); @@ -101,10 +101,11 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(channel_->AddSendStream(DefaultSendStreamParams())); video_capturer_.reset(CreateFakeVideoCapturer()); cricket::VideoFormat format(640, 480, - cricket::VideoFormat::FpsToInterval(30), + cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_I420); EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(format)); - channel_->SetSource(kSsrc, video_capturer_.get()); + EXPECT_TRUE( + channel_->SetVideoSend(kSsrc, true, nullptr, video_capturer_.get())); } virtual cricket::FakeVideoCapturer* CreateFakeVideoCapturer() { @@ -137,11 +138,12 @@ class VideoMediaChannelTest : public testing::Test, // Setup the receive and renderer for second stream after send. video_capturer_2_.reset(CreateFakeVideoCapturer()); cricket::VideoFormat format(640, 480, - cricket::VideoFormat::FpsToInterval(30), + cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_I420); EXPECT_EQ(cricket::CS_RUNNING, video_capturer_2_->Start(format)); - channel_->SetSource(kSsrc + 2, video_capturer_2_.get()); + EXPECT_TRUE(channel_->SetVideoSend(kSsrc + 2, true, nullptr, + video_capturer_2_.get())); } virtual void TearDown() { channel_.reset(); @@ -150,13 +152,13 @@ class VideoMediaChannelTest : public testing::Test, return SetOneCodec(DefaultCodec()); } - bool SetOneCodec(int pt, const char* name, int w, int h, int fr) { - return SetOneCodec(cricket::VideoCodec(pt, name, w, h, fr)); + bool SetOneCodec(int pt, const char* name) { + return SetOneCodec(cricket::VideoCodec(pt, name)); } bool SetOneCodec(const cricket::VideoCodec& codec) { - cricket::VideoFormat capture_format(codec.width, codec.height, - cricket::VideoFormat::FpsToInterval(codec.framerate), - cricket::FOURCC_I420); + cricket::VideoFormat capture_format( + kVideoWidth, kVideoHeight, + cricket::VideoFormat::FpsToInterval(kFramerate), cricket::FOURCC_I420); if (video_capturer_) { EXPECT_EQ(cricket::CS_RUNNING, video_capturer_->Start(capture_format)); @@ -352,7 +354,8 @@ class VideoMediaChannelTest : public testing::Test, // Test that SetSend works. void SetSend() { EXPECT_FALSE(channel_->sending()); - channel_->SetSource(kSsrc, video_capturer_.get()); + EXPECT_TRUE( + channel_->SetVideoSend(kSsrc, true, nullptr, video_capturer_.get())); EXPECT_TRUE(SetOneCodec(DefaultCodec())); EXPECT_FALSE(channel_->sending()); EXPECT_TRUE(SetSend(true)); @@ -392,7 +395,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); EXPECT_EQ(0, renderer_.num_rendered_frames()); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); std::unique_ptr p(GetRtpPacket(0)); EXPECT_EQ(codec.id, GetPayloadType(p.get())); } @@ -405,7 +408,7 @@ class VideoMediaChannelTest : public testing::Test, for (int i = 0; i < duration_sec; ++i) { for (int frame = 1; frame <= fps; ++frame) { EXPECT_TRUE(WaitAndSendFrame(1000 / fps)); - EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout); + EXPECT_FRAME_WAIT(frame + i * fps, kVideoWidth, kVideoHeight, kTimeout); } } std::unique_ptr p(GetRtpPacket(0)); @@ -427,18 +430,26 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_GT(info.senders[0].bytes_sent, 0); EXPECT_EQ(NumRtpPackets(), info.senders[0].packets_sent); EXPECT_EQ(0.0, info.senders[0].fraction_lost); + ASSERT_TRUE(info.senders[0].codec_payload_type); + EXPECT_EQ(DefaultCodec().id, *info.senders[0].codec_payload_type); EXPECT_EQ(0, info.senders[0].firs_rcvd); EXPECT_EQ(0, info.senders[0].plis_rcvd); EXPECT_EQ(0, info.senders[0].nacks_rcvd); - EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width); - EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height); + EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width); + EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height); EXPECT_GT(info.senders[0].framerate_input, 0); EXPECT_GT(info.senders[0].framerate_sent, 0); + EXPECT_EQ(1U, info.send_codecs.count(DefaultCodec().id)); + EXPECT_EQ(DefaultCodec().ToCodecParameters(), + info.send_codecs[DefaultCodec().id]); + ASSERT_EQ(1U, info.receivers.size()); EXPECT_EQ(1U, info.senders[0].ssrcs().size()); EXPECT_EQ(1U, info.receivers[0].ssrcs().size()); EXPECT_EQ(info.senders[0].ssrcs()[0], info.receivers[0].ssrcs()[0]); + ASSERT_TRUE(info.receivers[0].codec_payload_type); + EXPECT_EQ(DefaultCodec().id, *info.receivers[0].codec_payload_type); EXPECT_EQ(NumRtpBytes(), info.receivers[0].bytes_rcvd); EXPECT_EQ(NumRtpPackets(), info.receivers[0].packets_rcvd); EXPECT_EQ(0.0, info.receivers[0].fraction_lost); @@ -448,11 +459,15 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ(0, info.receivers[0].firs_sent); EXPECT_EQ(0, info.receivers[0].plis_sent); EXPECT_EQ(0, info.receivers[0].nacks_sent); - EXPECT_EQ(DefaultCodec().width, info.receivers[0].frame_width); - EXPECT_EQ(DefaultCodec().height, info.receivers[0].frame_height); + EXPECT_EQ(kVideoWidth, info.receivers[0].frame_width); + EXPECT_EQ(kVideoHeight, info.receivers[0].frame_height); EXPECT_GT(info.receivers[0].framerate_rcvd, 0); EXPECT_GT(info.receivers[0].framerate_decoded, 0); EXPECT_GT(info.receivers[0].framerate_output, 0); + + EXPECT_EQ(1U, info.receive_codecs.count(DefaultCodec().id)); + EXPECT_EQ(DefaultCodec().ToCodecParameters(), + info.receive_codecs[DefaultCodec().id]); } cricket::VideoSenderInfo GetSenderStats(size_t i) { @@ -489,10 +504,10 @@ class VideoMediaChannelTest : public testing::Test, ssrcs.push_back(2); network_interface_.SetConferenceMode(true, ssrcs); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_ON_RENDERER_WAIT( - renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); - EXPECT_FRAME_ON_RENDERER_WAIT( - renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); + EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, kVideoWidth, kVideoHeight, + kTimeout); + EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, kVideoWidth, kVideoHeight, + kTimeout); EXPECT_TRUE(channel_->SetSend(false)); @@ -503,8 +518,8 @@ class VideoMediaChannelTest : public testing::Test, // For webrtc, bytes_sent does not include the RTP header length. EXPECT_GT(GetSenderStats(0).bytes_sent, 0); EXPECT_EQ_WAIT(NumRtpPackets(), GetSenderStats(0).packets_sent, kTimeout); - EXPECT_EQ(DefaultCodec().width, GetSenderStats(0).send_frame_width); - EXPECT_EQ(DefaultCodec().height, GetSenderStats(0).send_frame_height); + EXPECT_EQ(kVideoWidth, GetSenderStats(0).send_frame_width); + EXPECT_EQ(kVideoHeight, GetSenderStats(0).send_frame_height); ASSERT_EQ(2U, info.receivers.size()); for (size_t i = 0; i < info.receivers.size(); ++i) { @@ -513,8 +528,8 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ_WAIT(NumRtpBytes(), GetReceiverStats(i).bytes_rcvd, kTimeout); EXPECT_EQ_WAIT(NumRtpPackets(), GetReceiverStats(i).packets_rcvd, kTimeout); - EXPECT_EQ(DefaultCodec().width, GetReceiverStats(i).frame_width); - EXPECT_EQ(DefaultCodec().height, GetReceiverStats(i).frame_height); + EXPECT_EQ_WAIT(kVideoWidth, GetReceiverStats(i).frame_width, kTimeout); + EXPECT_EQ_WAIT(kVideoHeight, GetReceiverStats(i).frame_height, kTimeout); } } // Test that stats work properly for a conf call with multiple send streams. @@ -532,7 +547,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(SendFrame()); EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); - EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); // Add an additional capturer, and hook up a renderer to receive it. cricket::FakeVideoRenderer renderer2; @@ -546,7 +561,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format)); EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(5678))); - channel_->SetSource(5678, capturer.get()); + EXPECT_TRUE(channel_->SetVideoSend(5678, true, nullptr, capturer.get())); EXPECT_TRUE(channel_->AddRecvStream( cricket::StreamParams::CreateLegacy(5678))); EXPECT_TRUE(channel_->SetSink(5678, &renderer2)); @@ -575,14 +590,14 @@ class VideoMediaChannelTest : public testing::Test, << "Timed out while waiting for packet counts for all sent packets."; EXPECT_EQ(1U, info.senders[0].ssrcs().size()); EXPECT_EQ(1234U, info.senders[0].ssrcs()[0]); - EXPECT_EQ(DefaultCodec().width, info.senders[0].send_frame_width); - EXPECT_EQ(DefaultCodec().height, info.senders[0].send_frame_height); + EXPECT_EQ(kVideoWidth, info.senders[0].send_frame_width); + EXPECT_EQ(kVideoHeight, info.senders[0].send_frame_height); EXPECT_EQ(1U, info.senders[1].ssrcs().size()); EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]); EXPECT_EQ(kTestWidth, info.senders[1].send_frame_width); EXPECT_EQ(kTestHeight, info.senders[1].send_frame_height); // The capturer must be unregistered here as it runs out of it's scope next. - channel_->SetSource(5678, NULL); + channel_->SetVideoSend(5678, true, nullptr, nullptr); } // Test that we can set the bandwidth. @@ -619,7 +634,8 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(SetDefaultCodec()); EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(999))); - channel_->SetSource(999u, video_capturer_.get()); + EXPECT_TRUE( + channel_->SetVideoSend(999u, true, nullptr, video_capturer_.get())); EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(WaitAndSendFrame(0)); EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout); @@ -650,7 +666,7 @@ class VideoMediaChannelTest : public testing::Test, channel_->OnPacketReceived(&packet1, rtc::PacketTime()); EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); } // Tests empty StreamParams is rejected. @@ -670,7 +686,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, DefaultCodec().width, DefaultCodec().height, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); EXPECT_GT(NumRtpPackets(), 0); uint32_t ssrc = 0; size_t last_packet = NumRtpPackets() - 1; @@ -685,7 +701,8 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(789u))); - channel_->SetSource(789u, video_capturer_.get()); + EXPECT_TRUE( + channel_->SetVideoSend(789u, true, nullptr, video_capturer_.get())); EXPECT_EQ(rtp_packets, NumRtpPackets()); // Wait 30ms to guarantee the engine does not drop the frame. EXPECT_TRUE(WaitAndSendFrame(30)); @@ -719,17 +736,17 @@ class VideoMediaChannelTest : public testing::Test, ssrcs.push_back(2); network_interface_.SetConferenceMode(true, ssrcs); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_ON_RENDERER_WAIT( - renderer1, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); - EXPECT_FRAME_ON_RENDERER_WAIT( - renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout); + EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, kVideoWidth, kVideoHeight, + kTimeout); + EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, kVideoWidth, kVideoHeight, + kTimeout); std::unique_ptr p(GetRtpPacket(0)); EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get())); - EXPECT_EQ(DefaultCodec().width, renderer1.width()); - EXPECT_EQ(DefaultCodec().height, renderer1.height()); - EXPECT_EQ(DefaultCodec().width, renderer2.width()); - EXPECT_EQ(DefaultCodec().height, renderer2.height()); + EXPECT_EQ(kVideoWidth, renderer1.width()); + EXPECT_EQ(kVideoHeight, renderer1.height()); + EXPECT_EQ(kVideoWidth, renderer2.width()); + EXPECT_EQ(kVideoHeight, renderer2.height()); EXPECT_TRUE(channel_->RemoveRecvStream(2)); EXPECT_TRUE(channel_->RemoveRecvStream(1)); } @@ -737,15 +754,14 @@ class VideoMediaChannelTest : public testing::Test, // Tests that we can add and remove capturers and frames are sent out properly void AddRemoveCapturer() { cricket::VideoCodec codec = DefaultCodec(); - codec.width = 320; - codec.height = 240; - const int time_between_send = TimeBetweenSend(codec); + const int time_between_send_ms = + cricket::VideoFormat::FpsToInterval(kFramerate); EXPECT_TRUE(SetOneCodec(codec)); EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); EXPECT_EQ(0, renderer_.num_rendered_frames()); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); std::unique_ptr capturer( CreateFakeVideoCapturer()); @@ -754,7 +770,7 @@ class VideoMediaChannelTest : public testing::Test, // test which is related to screencast logic. cricket::VideoOptions video_options; video_options.is_screencast = rtc::Optional(true); - channel_->SetVideoSend(kSsrc, true, &video_options); + channel_->SetVideoSend(kSsrc, true, &video_options, nullptr); cricket::VideoFormat format(480, 360, cricket::VideoFormat::FpsToInterval(30), @@ -768,8 +784,8 @@ class VideoMediaChannelTest : public testing::Test, int captured_frames = 1; for (int iterations = 0; iterations < 2; ++iterations) { - channel_->SetSource(kSsrc, capturer.get()); - rtc::Thread::Current()->ProcessMessages(time_between_send); + EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, capturer.get())); + rtc::Thread::Current()->ProcessMessages(time_between_send_ms); EXPECT_TRUE(capturer->CaptureCustomFrame(format.width, format.height, cricket::FOURCC_I420)); ++captured_frames; @@ -783,7 +799,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ(format.height, renderer_.height()); captured_frames = renderer_.num_rendered_frames() + 1; EXPECT_FALSE(renderer_.black_frame()); - channel_->SetSource(kSsrc, NULL); + EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr)); // Make sure a black frame is generated within the specified timeout. // The black frame should be the resolution of the previous frame to // prevent expensive encoder reconfigurations. @@ -805,28 +821,27 @@ class VideoMediaChannelTest : public testing::Test, } } - // Tests that if RemoveCapturer is called without a capturer ever being - // added, the plugin shouldn't crash (and no black frame should be sent). + // Tests that if SetVideoSend is called with a NULL capturer after the + // capturer was already removed, the application doesn't crash (and no black + // frame is sent). void RemoveCapturerWithoutAdd() { EXPECT_TRUE(SetOneCodec(DefaultCodec())); EXPECT_TRUE(SetSend(true)); EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); EXPECT_EQ(0, renderer_.num_rendered_frames()); EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, 640, 400, kTimeout); + EXPECT_FRAME_WAIT(1, kVideoWidth, kVideoHeight, kTimeout); // Wait for one frame so they don't get dropped because we send frames too // tightly. rtc::Thread::Current()->ProcessMessages(30); // Remove the capturer. - channel_->SetSource(kSsrc, NULL); - // Wait for one black frame for removing the capturer. - EXPECT_FRAME_WAIT(2, 640, 400, kTimeout); + EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr)); - // No capturer was added, so this SetSource should be a NOP. - channel_->SetSource(kSsrc, NULL); + // No capturer was added, so this SetVideoSend shouldn't do anything. + EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr)); rtc::Thread::Current()->ProcessMessages(300); // Verify no more frames were sent. - EXPECT_EQ(2, renderer_.num_rendered_frames()); + EXPECT_EQ(1, renderer_.num_rendered_frames()); } // Tests that we can add and remove capturer as unique sources. @@ -840,7 +855,7 @@ class VideoMediaChannelTest : public testing::Test, cricket::StreamParams::CreateLegacy(kSsrc))); EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer_)); cricket::VideoFormat capture_format; // default format - capture_format.interval = cricket::VideoFormat::FpsToInterval(30); + capture_format.interval = cricket::VideoFormat::FpsToInterval(kFramerate); // Set up additional stream 1. cricket::FakeVideoRenderer renderer1; EXPECT_FALSE(channel_->SetSink(1, &renderer1)); @@ -865,11 +880,11 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ(cricket::CS_RUNNING, capturer2->Start(capture_format)); // State for all the streams. EXPECT_TRUE(SetOneCodec(DefaultCodec())); - // A limitation in the lmi implementation requires that SetSource() is + // A limitation in the lmi implementation requires that SetVideoSend() is // called after SetOneCodec(). // TODO(hellner): this seems like an unnecessary constraint, fix it. - channel_->SetSource(1, capturer1.get()); - channel_->SetSource(2, capturer2.get()); + EXPECT_TRUE(channel_->SetVideoSend(1, true, nullptr, capturer1.get())); + EXPECT_TRUE(channel_->SetVideoSend(2, true, nullptr, capturer2.get())); EXPECT_TRUE(SetSend(true)); // Test capturer associated with engine. const int kTestWidth = 160; @@ -884,160 +899,11 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_FRAME_ON_RENDERER_WAIT( renderer2, 1, kTestWidth, kTestHeight, kTimeout); // Successfully remove the capturer. - channel_->SetSource(kSsrc, NULL); - // Fail to re-remove the capturer. - channel_->SetSource(kSsrc, NULL); + EXPECT_TRUE(channel_->SetVideoSend(kSsrc, true, nullptr, nullptr)); // The capturers must be unregistered here as it runs out of it's scope // next. - channel_->SetSource(1, NULL); - channel_->SetSource(2, NULL); - } - - void HighAspectHighHeightCapturer() { - const int kWidth = 80; - const int kHeight = 10000; - const int kScaledWidth = 20; - const int kScaledHeight = 2500; - - cricket::VideoCodec codec(DefaultCodec()); - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - - cricket::FakeVideoRenderer renderer; - EXPECT_TRUE(channel_->AddRecvStream( - cricket::StreamParams::CreateLegacy(kSsrc))); - EXPECT_TRUE(channel_->SetSink(kSsrc, &renderer)); - EXPECT_EQ(0, renderer.num_rendered_frames()); - - EXPECT_TRUE(SendFrame()); - EXPECT_GT_FRAME_ON_RENDERER_WAIT( - renderer, 1, codec.width, codec.height, kTimeout); - - // Registering an external capturer is currently the same as screen casting - // (update the test when this changes). - std::unique_ptr capturer( - CreateFakeVideoCapturer()); - const std::vector* formats = - capturer->GetSupportedFormats(); - cricket::VideoFormat capture_format = (*formats)[0]; - EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(capture_format)); - // Capture frame to not get same frame timestamps as previous capturer. - capturer->CaptureFrame(); - channel_->SetSource(kSsrc, capturer.get()); - EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(30)); - EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight, - cricket::FOURCC_ARGB)); - EXPECT_GT_FRAME_ON_RENDERER_WAIT( - renderer, 2, kScaledWidth, kScaledHeight, kTimeout); - channel_->SetSource(kSsrc, NULL); - } - - // Tests that we can adapt video resolution with 16:10 aspect ratio properly. - void AdaptResolution16x10() { - EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); - cricket::VideoCodec codec(DefaultCodec()); - codec.width = 640; - codec.height = 400; - SendAndReceive(codec); - codec.width /= 2; - codec.height /= 2; - // Adapt the resolution. - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(WaitAndSendFrame(30)); - EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout); - } - // Tests that we can adapt video resolution with 4:3 aspect ratio properly. - void AdaptResolution4x3() { - EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); - cricket::VideoCodec codec(DefaultCodec()); - codec.width = 640; - codec.height = 400; - SendAndReceive(codec); - codec.width /= 2; - codec.height /= 2; - // Adapt the resolution. - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(WaitAndSendFrame(30)); - EXPECT_FRAME_WAIT(2, codec.width, codec.height, kTimeout); - } - // Tests that we can drop all frames properly. - void AdaptDropAllFrames() { - // Set the channel codec's resolution to 0, which will require the adapter - // to drop all frames. - cricket::VideoCodec codec(DefaultCodec()); - codec.width = codec.height = codec.framerate = 0; - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); - EXPECT_EQ(0, renderer_.num_rendered_frames()); - EXPECT_TRUE(SendFrame()); - EXPECT_TRUE(SendFrame()); - rtc::Thread::Current()->ProcessMessages(500); - EXPECT_EQ(0, renderer_.num_rendered_frames()); - } - // Tests that we can reduce the frame rate on demand properly. - // TODO(fbarchard): This test is flakey on pulse. Fix and re-enable - void AdaptFramerate() { - cricket::VideoCodec codec(DefaultCodec()); - int frame_count = 0; - // The capturer runs at 30 fps. The channel requires 30 fps. - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - EXPECT_EQ(frame_count, renderer_.num_rendered_frames()); - EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. - frame_count += 2; - EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout); - std::unique_ptr p(GetRtpPacket(0)); - EXPECT_EQ(codec.id, GetPayloadType(p.get())); - - // The channel requires 15 fps. - codec.framerate = 15; - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. - frame_count += 2; - EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); - - // The channel requires 10 fps. - codec.framerate = 10; - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. - frame_count += 2; - EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); - - // The channel requires 8 fps. The adapter adapts to 10 fps, which is the - // closest factor of 30. - codec.framerate = 8; - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(WaitAndSendFrame(0)); // Should be rendered. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be dropped. - EXPECT_TRUE(WaitAndSendFrame(30)); // Should be rendered. - frame_count += 2; - EXPECT_EQ_WAIT(frame_count, renderer_.num_rendered_frames(), kTimeout); - } - // Tests that adapted frames won't be upscaled to a higher resolution. - void SendsLowerResolutionOnSmallerFrames() { - cricket::VideoCodec codec = DefaultCodec(); - codec.width = 320; - codec.height = 240; - EXPECT_TRUE(SetOneCodec(codec)); - EXPECT_TRUE(SetSend(true)); - EXPECT_TRUE(channel_->SetSink(kDefaultReceiveSsrc, &renderer_)); - EXPECT_EQ(0, renderer_.num_rendered_frames()); - EXPECT_TRUE(SendFrame()); - EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout); - - // Check that we send smaller frames at the new resolution. - EXPECT_TRUE(rtc::Thread::Current()->ProcessMessages(33)); - EXPECT_TRUE(video_capturer_->CaptureCustomFrame( - codec.width / 2, codec.height / 2, cricket::FOURCC_I420)); - EXPECT_FRAME_WAIT(2, codec.width / 2, codec.height / 2, kTimeout); + EXPECT_TRUE(channel_->SetVideoSend(1, true, nullptr, nullptr)); + EXPECT_TRUE(channel_->SetVideoSend(2, true, nullptr, nullptr)); } // Test that multiple send streams can be created and deleted properly. @@ -1070,6 +936,7 @@ class VideoMediaChannelTest : public testing::Test, EXPECT_EQ(1, renderer2_.num_rendered_frames()); } + webrtc::RtcEventLogNullImpl event_log_; const std::unique_ptr call_; E engine_; std::unique_ptr video_capturer_; diff --git a/include/webrtc/media/base/videoframe.h b/include/webrtc/media/base/videoframe.h index 4026c26..8e8a05d 100644 --- a/include/webrtc/media/base/videoframe.h +++ b/include/webrtc/media/base/videoframe.h @@ -8,139 +8,29 @@ * be found in the AUTHORS file in the root of the source tree. */ +// TODO(nisse): Deprecated, replace cricket::VideoFrame with +// webrtc::VideoFrame everywhere, then delete this file. See +// https://bugs.chromium.org/p/webrtc/issues/detail?id=5682. + #ifndef WEBRTC_MEDIA_BASE_VIDEOFRAME_H_ #define WEBRTC_MEDIA_BASE_VIDEOFRAME_H_ -#include "webrtc/base/basictypes.h" -#include "webrtc/base/stream.h" -#include "webrtc/common_video/include/video_frame_buffer.h" -#include "webrtc/common_video/rotation.h" - -namespace cricket { - -// Represents a YUV420 (a.k.a. I420) video frame. -class VideoFrame { - public: - VideoFrame() {} - virtual ~VideoFrame() {} - - // Basic accessors. - // Note this is the width and height without rotation applied. - virtual int width() const = 0; - virtual int height() const = 0; - - // Deprecated methods, for backwards compatibility. - // TODO(nisse): Delete when usage in Chrome and other applications - // have been replaced by width() and height(). - virtual size_t GetWidth() const final { return width(); } - virtual size_t GetHeight() const final { return height(); } - - // Returns the handle of the underlying video frame. This is used when the - // frame is backed by a texture. The object should be destroyed when it is no - // longer in use, so the underlying resource can be freed. - virtual void* GetNativeHandle() const = 0; - - // Returns the underlying video frame buffer. This function is ok to call - // multiple times, but the returned object will refer to the same memory. - virtual const rtc::scoped_refptr& - video_frame_buffer() const = 0; - - // System monotonic clock, same timebase as rtc::TimeMicros(). - virtual int64_t timestamp_us() const = 0; - virtual void set_timestamp_us(int64_t time_us) = 0; - - // Deprecated methods, for backwards compatibility. - // TODO(nisse): Delete when usage in Chrome and other applications - // have been replaced. - virtual int64_t GetTimeStamp() const { - return rtc::kNumNanosecsPerMicrosec * timestamp_us(); - } - virtual void SetTimeStamp(int64_t time_ns) { - set_timestamp_us(time_ns / rtc::kNumNanosecsPerMicrosec); - } +// TODO(nisse): Some applications expect that including this file +// implies an include of logging.h. So keep for compatibility, until +// this file can be deleted. +#include "webrtc/base/logging.h" - // Indicates the rotation angle in degrees. - virtual webrtc::VideoRotation rotation() const = 0; +#include "webrtc/api/video/video_frame.h" - // Make a shallow copy of the frame. The frame buffer itself is not copied. - // Both the current and new VideoFrame will share a single reference-counted - // frame buffer. - virtual VideoFrame *Copy() const = 0; +// TODO(nisse): Similarly, some applications expect that including this file +// implies a forward declaration of rtc::Thread. +namespace rtc { +class Thread; +} // namespace rtc - // Since VideoFrame supports shallow copy and the internal frame buffer might - // be shared, this function can be used to check exclusive ownership. - virtual bool IsExclusive() const = 0; - - // Return a copy of frame which has its pending rotation applied. The - // ownership of the returned frame is held by this frame. - virtual const VideoFrame* GetCopyWithRotationApplied() const = 0; - - // Converts the I420 data to RGB of a certain type such as ARGB and ABGR. - // Returns the frame's actual size, regardless of whether it was written or - // not (like snprintf). Parameters size and stride_rgb are in units of bytes. - // If there is insufficient space, nothing is written. - virtual size_t ConvertToRgbBuffer(uint32_t to_fourcc, - uint8_t* buffer, - size_t size, - int stride_rgb) const; - - // Writes the frame into the given planes, stretched to the given width and - // height. The parameter "interpolate" controls whether to interpolate or just - // take the nearest-point. The parameter "crop" controls whether to crop this - // frame to the aspect ratio of the given dimensions before stretching. - virtual void StretchToPlanes(uint8_t* y, - uint8_t* u, - uint8_t* v, - int32_t pitchY, - int32_t pitchU, - int32_t pitchV, - size_t width, - size_t height, - bool interpolate, - bool crop) const; - - // Writes the frame into the target VideoFrame, stretched to the size of that - // frame. The parameter "interpolate" controls whether to interpolate or just - // take the nearest-point. The parameter "crop" controls whether to crop this - // frame to the aspect ratio of the target frame before stretching. - virtual void StretchToFrame(VideoFrame *target, bool interpolate, - bool crop) const; - - // Stretches the frame to the given size, creating a new VideoFrame object to - // hold it. The parameter "interpolate" controls whether to interpolate or - // just take the nearest-point. The parameter "crop" controls whether to crop - // this frame to the aspect ratio of the given dimensions before stretching. - virtual VideoFrame *Stretch(size_t w, size_t h, bool interpolate, - bool crop) const; - - // Sets the video frame to black. - virtual bool SetToBlack(); - - // Tests if sample is valid. Returns true if valid. - static bool Validate(uint32_t fourcc, - int w, - int h, - const uint8_t* sample, - size_t sample_size); - - protected: - // Writes the frame into the given planes, stretched to the given width and - // height. The parameter "interpolate" controls whether to interpolate or just - // take the nearest-point. The parameter "crop" controls whether to crop this - // frame to the aspect ratio of the given dimensions before stretching. - virtual bool CopyToPlanes(uint8_t* dst_y, - uint8_t* dst_u, - uint8_t* dst_v, - int32_t dst_pitch_y, - int32_t dst_pitch_u, - int32_t dst_pitch_v) const; +namespace cricket { - // Creates an empty frame. - virtual VideoFrame* CreateEmptyFrame(int w, - int h, - int64_t timestamp_us) const = 0; - virtual void set_rotation(webrtc::VideoRotation rotation) = 0; -}; +using VideoFrame = webrtc::VideoFrame; } // namespace cricket diff --git a/include/webrtc/media/base/videoframe_unittest.h b/include/webrtc/media/base/videoframe_unittest.h deleted file mode 100644 index 6ceba83..0000000 --- a/include/webrtc/media/base/videoframe_unittest.h +++ /dev/null @@ -1,1835 +0,0 @@ -/* - * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ -#define WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ - -#include -#include -#include - -#include "libyuv/convert.h" -#include "libyuv/convert_from.h" -#include "libyuv/planar_functions.h" -#include "libyuv/rotate.h" -#include "webrtc/base/gunit.h" -#include "webrtc/base/pathutils.h" -#include "webrtc/base/stream.h" -#include "webrtc/base/stringutils.h" -#include "webrtc/common_video/rotation.h" -#include "webrtc/media/base/testutils.h" -#include "webrtc/media/base/videocommon.h" -#include "webrtc/media/base/videoframe.h" - -#if defined(_MSC_VER) -#define ALIGN16(var) __declspec(align(16)) var -#else -#define ALIGN16(var) var __attribute__((aligned(16))) -#endif - -#define kImageFilename "faces.1280x720_P420.yuv" -#define kJpeg420Filename "faces_I420.jpg" -#define kJpeg422Filename "faces_I422.jpg" -#define kJpeg444Filename "faces_I444.jpg" -#define kJpeg411Filename "faces_I411.jpg" -#define kJpeg400Filename "faces_I400.jpg" - -// Generic test class for testing various video frame implementations. -template -class VideoFrameTest : public testing::Test { - public: - VideoFrameTest() : repeat_(1) {} - - protected: - static const int kWidth = 1280; - static const int kHeight = 720; - static const int kAlignment = 16; - static const int kMinWidthAll = 1; // Constants for ConstructYUY2AllSizes. - static const int kMinHeightAll = 1; - static const int kMaxWidthAll = 17; - static const int kMaxHeightAll = 23; - - // Load a video frame from disk. - bool LoadFrameNoRepeat(T* frame) { - int save_repeat = repeat_; // This LoadFrame disables repeat. - repeat_ = 1; - bool success = LoadFrame(kImageFilename, cricket::FOURCC_I420, - kWidth, kHeight, frame); - repeat_ = save_repeat; - return success; - } - - bool LoadFrame(const std::string& filename, - uint32_t format, - int32_t width, - int32_t height, - T* frame) { - return LoadFrame(filename, format, width, height, width, abs(height), - webrtc::kVideoRotation_0, frame); - } - bool LoadFrame(const std::string& filename, - uint32_t format, - int32_t width, - int32_t height, - int dw, - int dh, - webrtc::VideoRotation rotation, - T* frame) { - std::unique_ptr ms(LoadSample(filename)); - return LoadFrame(ms.get(), format, width, height, dw, dh, rotation, frame); - } - // Load a video frame from a memory stream. - bool LoadFrame(rtc::MemoryStream* ms, - uint32_t format, - int32_t width, - int32_t height, - T* frame) { - return LoadFrame(ms, format, width, height, width, abs(height), - webrtc::kVideoRotation_0, frame); - } - bool LoadFrame(rtc::MemoryStream* ms, - uint32_t format, - int32_t width, - int32_t height, - int dw, - int dh, - webrtc::VideoRotation rotation, - T* frame) { - if (!ms) { - return false; - } - size_t data_size; - bool ret = ms->GetSize(&data_size); - EXPECT_TRUE(ret); - if (ret) { - ret = LoadFrame(reinterpret_cast(ms->GetBuffer()), data_size, - format, width, height, dw, dh, rotation, frame); - } - return ret; - } - // Load a frame from a raw buffer. - bool LoadFrame(uint8_t* sample, - size_t sample_size, - uint32_t format, - int32_t width, - int32_t height, - T* frame) { - return LoadFrame(sample, sample_size, format, width, height, width, - abs(height), webrtc::kVideoRotation_0, frame); - } - bool LoadFrame(uint8_t* sample, - size_t sample_size, - uint32_t format, - int32_t width, - int32_t height, - int dw, - int dh, - webrtc::VideoRotation rotation, - T* frame) { - bool ret = false; - for (int i = 0; i < repeat_; ++i) { - ret = frame->Init(format, width, height, dw, dh, - sample, sample_size, 0, rotation); - } - return ret; - } - - rtc::MemoryStream* LoadSample(const std::string& filename) { - rtc::Pathname path(cricket::GetTestFilePath(filename)); - std::unique_ptr fs( - rtc::Filesystem::OpenFile(path, "rb")); - if (!fs.get()) { - LOG(LS_ERROR) << "Could not open test file path: " << path.pathname() - << " from current dir " - << rtc::Filesystem::GetCurrentDirectory().pathname(); - return NULL; - } - - char buf[4096]; - std::unique_ptr ms( - new rtc::MemoryStream()); - rtc::StreamResult res = Flow(fs.get(), buf, sizeof(buf), ms.get()); - if (res != rtc::SR_SUCCESS) { - LOG(LS_ERROR) << "Could not load test file path: " << path.pathname(); - return NULL; - } - - return ms.release(); - } - - bool DumpSample(const std::string& filename, const void* buffer, int size) { - rtc::Pathname path(filename); - std::unique_ptr fs( - rtc::Filesystem::OpenFile(path, "wb")); - if (!fs.get()) { - return false; - } - - return (fs->Write(buffer, size, NULL, NULL) == rtc::SR_SUCCESS); - } - - // Create a test image in the desired color space. - // The image is a checkerboard pattern with 63x63 squares, which allows - // I420 chroma artifacts to easily be seen on the square boundaries. - // The pattern is { { green, orange }, { blue, purple } } - // There is also a gradient within each square to ensure that the luma - // values are handled properly. - rtc::MemoryStream* CreateYuv422Sample(uint32_t fourcc, - uint32_t width, - uint32_t height) { - int y1_pos, y2_pos, u_pos, v_pos; - if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { - return NULL; - } - - std::unique_ptr ms( - new rtc::MemoryStream); - int awidth = (width + 1) & ~1; - int size = awidth * 2 * height; - if (!ms->ReserveSize(size)) { - return NULL; - } - for (uint32_t y = 0; y < height; ++y) { - for (int x = 0; x < awidth; x += 2) { - uint8_t quad[4]; - quad[y1_pos] = (x % 63 + y % 63) + 64; - quad[y2_pos] = ((x + 1) % 63 + y % 63) + 64; - quad[u_pos] = ((x / 63) & 1) ? 192 : 64; - quad[v_pos] = ((y / 63) & 1) ? 192 : 64; - ms->Write(quad, sizeof(quad), NULL, NULL); - } - } - return ms.release(); - } - - // Create a test image for YUV 420 formats with 12 bits per pixel. - rtc::MemoryStream* CreateYuvSample(uint32_t width, - uint32_t height, - uint32_t bpp) { - std::unique_ptr ms( - new rtc::MemoryStream); - if (!ms->ReserveSize(width * height * bpp / 8)) { - return NULL; - } - - for (uint32_t i = 0; i < width * height * bpp / 8; ++i) { - uint8_t value = ((i / 63) & 1) ? 192 : 64; - ms->Write(&value, sizeof(value), NULL, NULL); - } - return ms.release(); - } - - rtc::MemoryStream* CreateRgbSample(uint32_t fourcc, - uint32_t width, - uint32_t height) { - int r_pos, g_pos, b_pos, bytes; - if (!GetRgbPacking(fourcc, &r_pos, &g_pos, &b_pos, &bytes)) { - return NULL; - } - - std::unique_ptr ms( - new rtc::MemoryStream); - if (!ms->ReserveSize(width * height * bytes)) { - return NULL; - } - - for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; ++x) { - uint8_t rgb[4] = {255, 255, 255, 255}; - rgb[r_pos] = ((x / 63) & 1) ? 224 : 32; - rgb[g_pos] = (x % 63 + y % 63) + 96; - rgb[b_pos] = ((y / 63) & 1) ? 224 : 32; - ms->Write(rgb, bytes, NULL, NULL); - } - } - return ms.release(); - } - - // Simple conversion routines to verify the optimized VideoFrame routines. - // Converts from the specified colorspace to I420. - bool ConvertYuv422(const rtc::MemoryStream* ms, - uint32_t fourcc, - uint32_t width, - uint32_t height, - T* frame) { - int y1_pos, y2_pos, u_pos, v_pos; - if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { - return false; - } - - const uint8_t* start = reinterpret_cast(ms->GetBuffer()); - int awidth = (width + 1) & ~1; - frame->InitToBlack(width, height, 0); - int stride_y = frame->video_frame_buffer()->StrideY(); - int stride_u = frame->video_frame_buffer()->StrideU(); - int stride_v = frame->video_frame_buffer()->StrideV(); - uint8_t* plane_y = frame->video_frame_buffer()->MutableDataY(); - uint8_t* plane_u = frame->video_frame_buffer()->MutableDataU(); - uint8_t* plane_v = frame->video_frame_buffer()->MutableDataV(); - for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; x += 2) { - const uint8_t* quad1 = start + (y * awidth + x) * 2; - plane_y[stride_y * y + x] = quad1[y1_pos]; - if ((x + 1) < width) { - plane_y[stride_y * y + x + 1] = quad1[y2_pos]; - } - if ((y & 1) == 0) { - const uint8_t* quad2 = quad1 + awidth * 2; - if ((y + 1) >= height) { - quad2 = quad1; - } - plane_u[stride_u * (y / 2) + x / 2] = - (quad1[u_pos] + quad2[u_pos] + 1) / 2; - plane_v[stride_v * (y / 2) + x / 2] = - (quad1[v_pos] + quad2[v_pos] + 1) / 2; - } - } - } - return true; - } - - // Convert RGB to 420. - // A negative height inverts the image. - bool ConvertRgb(const rtc::MemoryStream* ms, - uint32_t fourcc, - int32_t width, - int32_t height, - T* frame) { - int r_pos, g_pos, b_pos, bytes; - if (!GetRgbPacking(fourcc, &r_pos, &g_pos, &b_pos, &bytes)) { - return false; - } - int pitch = width * bytes; - const uint8_t* start = reinterpret_cast(ms->GetBuffer()); - if (height < 0) { - height = -height; - start = start + pitch * (height - 1); - pitch = -pitch; - } - frame->InitToBlack(width, height, 0); - int stride_y = frame->video_frame_buffer()->StrideY(); - int stride_u = frame->video_frame_buffer()->StrideU(); - int stride_v = frame->video_frame_buffer()->StrideV(); - uint8_t* plane_y = frame->video_frame_buffer()->MutableDataY(); - uint8_t* plane_u = frame->video_frame_buffer()->MutableDataU(); - uint8_t* plane_v = frame->video_frame_buffer()->MutableDataV(); - for (int32_t y = 0; y < height; y += 2) { - for (int32_t x = 0; x < width; x += 2) { - const uint8_t* rgb[4]; - uint8_t yuv[4][3]; - rgb[0] = start + y * pitch + x * bytes; - rgb[1] = rgb[0] + ((x + 1) < width ? bytes : 0); - rgb[2] = rgb[0] + ((y + 1) < height ? pitch : 0); - rgb[3] = rgb[2] + ((x + 1) < width ? bytes : 0); - for (size_t i = 0; i < 4; ++i) { - ConvertRgbPixel(rgb[i][r_pos], rgb[i][g_pos], rgb[i][b_pos], - &yuv[i][0], &yuv[i][1], &yuv[i][2]); - } - plane_y[stride_y * y + x] = yuv[0][0]; - if ((x + 1) < width) { - plane_y[stride_y * y + x + 1] = yuv[1][0]; - } - if ((y + 1) < height) { - plane_y[stride_y * (y + 1) + x] = yuv[2][0]; - if ((x + 1) < width) { - plane_y[stride_y * (y + 1) + x + 1] = yuv[3][0]; - } - } - plane_u[stride_u * (y / 2) + x / 2] = - (yuv[0][1] + yuv[1][1] + yuv[2][1] + yuv[3][1] + 2) / 4; - plane_v[stride_v * (y / 2) + x / 2] = - (yuv[0][2] + yuv[1][2] + yuv[2][2] + yuv[3][2] + 2) / 4; - } - } - return true; - } - - // Simple and slow RGB->YUV conversion. From NTSC standard, c/o Wikipedia. - void ConvertRgbPixel(uint8_t r, - uint8_t g, - uint8_t b, - uint8_t* y, - uint8_t* u, - uint8_t* v) { - *y = static_cast(.257 * r + .504 * g + .098 * b) + 16; - *u = static_cast(-.148 * r - .291 * g + .439 * b) + 128; - *v = static_cast(.439 * r - .368 * g - .071 * b) + 128; - } - - bool GetYuv422Packing(uint32_t fourcc, - int* y1_pos, - int* y2_pos, - int* u_pos, - int* v_pos) { - if (fourcc == cricket::FOURCC_YUY2) { - *y1_pos = 0; *u_pos = 1; *y2_pos = 2; *v_pos = 3; - } else if (fourcc == cricket::FOURCC_UYVY) { - *u_pos = 0; *y1_pos = 1; *v_pos = 2; *y2_pos = 3; - } else { - return false; - } - return true; - } - - bool GetRgbPacking(uint32_t fourcc, - int* r_pos, - int* g_pos, - int* b_pos, - int* bytes) { - if (fourcc == cricket::FOURCC_RAW) { - *r_pos = 0; *g_pos = 1; *b_pos = 2; *bytes = 3; // RGB in memory. - } else if (fourcc == cricket::FOURCC_24BG) { - *r_pos = 2; *g_pos = 1; *b_pos = 0; *bytes = 3; // BGR in memory. - } else if (fourcc == cricket::FOURCC_ABGR) { - *r_pos = 0; *g_pos = 1; *b_pos = 2; *bytes = 4; // RGBA in memory. - } else if (fourcc == cricket::FOURCC_BGRA) { - *r_pos = 1; *g_pos = 2; *b_pos = 3; *bytes = 4; // ARGB in memory. - } else if (fourcc == cricket::FOURCC_ARGB) { - *r_pos = 2; *g_pos = 1; *b_pos = 0; *bytes = 4; // BGRA in memory. - } else { - return false; - } - return true; - } - - // Comparison functions for testing. - static bool IsNull(const cricket::VideoFrame& frame) { - return !frame.video_frame_buffer(); - } - - static bool IsSize(const cricket::VideoFrame& frame, - int width, - int height) { - return !IsNull(frame) && frame.video_frame_buffer()->StrideY() >= width && - frame.video_frame_buffer()->StrideU() >= width / 2 && - frame.video_frame_buffer()->StrideV() >= width / 2 && - frame.width() == width && frame.height() == height; - } - - static bool IsPlaneEqual(const std::string& name, - const uint8_t* plane1, - uint32_t pitch1, - const uint8_t* plane2, - uint32_t pitch2, - uint32_t width, - uint32_t height, - int max_error) { - const uint8_t* r1 = plane1; - const uint8_t* r2 = plane2; - for (uint32_t y = 0; y < height; ++y) { - for (uint32_t x = 0; x < width; ++x) { - if (abs(static_cast(r1[x] - r2[x])) > max_error) { - LOG(LS_INFO) << "IsPlaneEqual(" << name << "): pixel[" - << x << "," << y << "] differs: " - << static_cast(r1[x]) << " vs " - << static_cast(r2[x]); - return false; - } - } - r1 += pitch1; - r2 += pitch2; - } - return true; - } - - static bool IsEqual(const cricket::VideoFrame& frame, - int width, - int height, - int64_t time_stamp, - const uint8_t* y, - uint32_t ypitch, - const uint8_t* u, - uint32_t upitch, - const uint8_t* v, - uint32_t vpitch, - int max_error) { - return IsSize(frame, width, height) && frame.GetTimeStamp() == time_stamp && - IsPlaneEqual("y", frame.video_frame_buffer()->DataY(), - frame.video_frame_buffer()->StrideY(), y, ypitch, - static_cast(width), - static_cast(height), max_error) && - IsPlaneEqual("u", frame.video_frame_buffer()->DataU(), - frame.video_frame_buffer()->StrideU(), u, upitch, - static_cast((width + 1) / 2), - static_cast((height + 1) / 2), max_error) && - IsPlaneEqual("v", frame.video_frame_buffer()->DataV(), - frame.video_frame_buffer()->StrideV(), v, vpitch, - static_cast((width + 1) / 2), - static_cast((height + 1) / 2), max_error); - } - - static bool IsEqual(const cricket::VideoFrame& frame1, - const cricket::VideoFrame& frame2, - int max_error) { - return IsEqual(frame1, - frame2.width(), frame2.height(), - frame2.GetTimeStamp(), - frame2.video_frame_buffer()->DataY(), - frame2.video_frame_buffer()->StrideY(), - frame2.video_frame_buffer()->DataU(), - frame2.video_frame_buffer()->StrideU(), - frame2.video_frame_buffer()->DataV(), - frame2.video_frame_buffer()->StrideV(), - max_error); - } - - static bool IsEqualWithCrop(const cricket::VideoFrame& frame1, - const cricket::VideoFrame& frame2, - int hcrop, int vcrop, int max_error) { - return frame1.width() <= frame2.width() && - frame1.height() <= frame2.height() && - IsEqual(frame1, - frame2.width() - hcrop * 2, - frame2.height() - vcrop * 2, - frame2.GetTimeStamp(), - frame2.video_frame_buffer()->DataY() - + vcrop * frame2.video_frame_buffer()->StrideY() - + hcrop, - frame2.video_frame_buffer()->StrideY(), - frame2.video_frame_buffer()->DataU() - + vcrop * frame2.video_frame_buffer()->StrideU() / 2 - + hcrop / 2, - frame2.video_frame_buffer()->StrideU(), - frame2.video_frame_buffer()->DataV() - + vcrop * frame2.video_frame_buffer()->StrideV() / 2 - + hcrop / 2, - frame2.video_frame_buffer()->StrideV(), - max_error); - } - - static bool IsBlack(const cricket::VideoFrame& frame) { - return !IsNull(frame) && - *frame.video_frame_buffer()->DataY() == 16 && - *frame.video_frame_buffer()->DataU() == 128 && - *frame.video_frame_buffer()->DataV() == 128; - } - - //////////////////////// - // Construction tests // - //////////////////////// - - // Test constructing an image from a I420 buffer. - void ConstructI420() { - T frame; - EXPECT_TRUE(IsNull(frame)); - std::unique_ptr ms( - CreateYuvSample(kWidth, kHeight, 12)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_I420, - kWidth, kHeight, &frame)); - - const uint8_t* y = reinterpret_cast(ms.get()->GetBuffer()); - const uint8_t* u = y + kWidth * kHeight; - const uint8_t* v = u + kWidth * kHeight / 4; - EXPECT_TRUE(IsEqual(frame, kWidth, kHeight, 0, y, kWidth, u, - kWidth / 2, v, kWidth / 2, 0)); - } - - // Test constructing an image from a YV12 buffer. - void ConstructYV12() { - T frame; - std::unique_ptr ms( - CreateYuvSample(kWidth, kHeight, 12)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YV12, - kWidth, kHeight, &frame)); - - const uint8_t* y = reinterpret_cast(ms.get()->GetBuffer()); - const uint8_t* v = y + kWidth * kHeight; - const uint8_t* u = v + kWidth * kHeight / 4; - EXPECT_TRUE(IsEqual(frame, kWidth, kHeight, 0, y, kWidth, u, - kWidth / 2, v, kWidth / 2, 0)); - } - - // Test constructing an image from a I422 buffer. - void ConstructI422() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - size_t buf_size = kWidth * kHeight * 2; - std::unique_ptr buf(new uint8_t[buf_size + kAlignment]); - uint8_t* y = ALIGNP(buf.get(), kAlignment); - uint8_t* u = y + kWidth * kHeight; - uint8_t* v = u + (kWidth / 2) * kHeight; - EXPECT_EQ(0, libyuv::I420ToI422(frame1.video_frame_buffer()->DataY(), - frame1.video_frame_buffer()->StrideY(), - frame1.video_frame_buffer()->DataU(), - frame1.video_frame_buffer()->StrideU(), - frame1.video_frame_buffer()->DataV(), - frame1.video_frame_buffer()->StrideV(), - y, kWidth, - u, kWidth / 2, - v, kWidth / 2, - kWidth, kHeight)); - EXPECT_TRUE(LoadFrame(y, buf_size, cricket::FOURCC_I422, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 1)); - } - - // Test constructing an image from a YUY2 buffer. - void ConstructYuy2() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - size_t buf_size = kWidth * kHeight * 2; - std::unique_ptr buf(new uint8_t[buf_size + kAlignment]); - uint8_t* yuy2 = ALIGNP(buf.get(), kAlignment); - EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.video_frame_buffer()->DataY(), - frame1.video_frame_buffer()->StrideY(), - frame1.video_frame_buffer()->DataU(), - frame1.video_frame_buffer()->StrideU(), - frame1.video_frame_buffer()->DataV(), - frame1.video_frame_buffer()->StrideV(), - yuy2, kWidth * 2, - kWidth, kHeight)); - EXPECT_TRUE(LoadFrame(yuy2, buf_size, cricket::FOURCC_YUY2, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - - // Test constructing an image from a YUY2 buffer with buffer unaligned. - void ConstructYuy2Unaligned() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - size_t buf_size = kWidth * kHeight * 2; - std::unique_ptr buf(new uint8_t[buf_size + kAlignment + 1]); - uint8_t* yuy2 = ALIGNP(buf.get(), kAlignment) + 1; - EXPECT_EQ(0, libyuv::I420ToYUY2(frame1.video_frame_buffer()->DataY(), - frame1.video_frame_buffer()->StrideY(), - frame1.video_frame_buffer()->DataU(), - frame1.video_frame_buffer()->StrideU(), - frame1.video_frame_buffer()->DataV(), - frame1.video_frame_buffer()->StrideV(), - yuy2, kWidth * 2, - kWidth, kHeight)); - EXPECT_TRUE(LoadFrame(yuy2, buf_size, cricket::FOURCC_YUY2, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - - // Test constructing an image from a wide YUY2 buffer. - // Normal is 1280x720. Wide is 12800x72 - void ConstructYuy2Wide() { - T frame1, frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth * 10, kHeight / 10)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_YUY2, - kWidth * 10, kHeight / 10, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, - kWidth * 10, kHeight / 10, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - - // Test constructing an image from a UYVY buffer. - void ConstructUyvy() { - T frame1, frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_UYVY, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_UYVY, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_UYVY, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - - // Test constructing an image from a random buffer. - // We are merely verifying that the code succeeds and is free of crashes. - void ConstructM420() { - T frame; - std::unique_ptr ms( - CreateYuvSample(kWidth, kHeight, 12)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_M420, - kWidth, kHeight, &frame)); - } - - void ConstructNV21() { - T frame; - std::unique_ptr ms( - CreateYuvSample(kWidth, kHeight, 12)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_NV21, - kWidth, kHeight, &frame)); - } - - void ConstructNV12() { - T frame; - std::unique_ptr ms( - CreateYuvSample(kWidth, kHeight, 12)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_NV12, - kWidth, kHeight, &frame)); - } - - // Test constructing an image from a ABGR buffer - // Due to rounding, some pixels may differ slightly from the VideoFrame impl. - void ConstructABGR() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ABGR, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ABGR, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ABGR, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from a ARGB buffer - // Due to rounding, some pixels may differ slightly from the VideoFrame impl. - void ConstructARGB() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ARGB, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ARGB, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from a wide ARGB buffer - // Normal is 1280x720. Wide is 12800x72 - void ConstructARGBWide() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ARGB, kWidth * 10, kHeight / 10)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ARGB, - kWidth * 10, kHeight / 10, &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, - kWidth * 10, kHeight / 10, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from an BGRA buffer. - // Due to rounding, some pixels may differ slightly from the VideoFrame impl. - void ConstructBGRA() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_BGRA, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_BGRA, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_BGRA, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from a 24BG buffer. - // Due to rounding, some pixels may differ slightly from the VideoFrame impl. - void Construct24BG() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_24BG, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_24BG, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_24BG, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from a raw RGB buffer. - // Due to rounding, some pixels may differ slightly from the VideoFrame impl. - void ConstructRaw() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_RAW, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_RAW, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_RAW, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 2)); - } - - // Test constructing an image from a RGB565 buffer - void ConstructRGB565() { - T frame1, frame2; - size_t out_size = kWidth * kHeight * 2; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment]); - uint8_t* out = ALIGNP(outbuf.get(), kAlignment); - T frame; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - EXPECT_EQ(out_size, frame1.ConvertToRgbBuffer(cricket::FOURCC_RGBP, - out, - out_size, kWidth * 2)); - EXPECT_TRUE(LoadFrame(out, out_size, cricket::FOURCC_RGBP, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 20)); - } - - // Test constructing an image from a ARGB1555 buffer - void ConstructARGB1555() { - T frame1, frame2; - size_t out_size = kWidth * kHeight * 2; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment]); - uint8_t* out = ALIGNP(outbuf.get(), kAlignment); - T frame; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - EXPECT_EQ(out_size, frame1.ConvertToRgbBuffer(cricket::FOURCC_RGBO, - out, - out_size, kWidth * 2)); - EXPECT_TRUE(LoadFrame(out, out_size, cricket::FOURCC_RGBO, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 20)); - } - - // Test constructing an image from a ARGB4444 buffer - void ConstructARGB4444() { - T frame1, frame2; - size_t out_size = kWidth * kHeight * 2; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment]); - uint8_t* out = ALIGNP(outbuf.get(), kAlignment); - T frame; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - EXPECT_EQ(out_size, frame1.ConvertToRgbBuffer(cricket::FOURCC_R444, - out, - out_size, kWidth * 2)); - EXPECT_TRUE(LoadFrame(out, out_size, cricket::FOURCC_R444, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 20)); - } - -// Macro to help test different rotations -#define TEST_MIRROR(FOURCC, BPP) \ - void Construct##FOURCC##Mirror() { \ - T frame1, frame2, frame3; \ - std::unique_ptr ms( \ - CreateYuvSample(kWidth, kHeight, BPP)); \ - ASSERT_TRUE(ms.get() != NULL); \ - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_##FOURCC, kWidth, \ - -kHeight, kWidth, kHeight, \ - webrtc::kVideoRotation_180, &frame1)); \ - size_t data_size; \ - bool ret = ms->GetSize(&data_size); \ - EXPECT_TRUE(ret); \ - EXPECT_TRUE(frame2.Init(cricket::FOURCC_##FOURCC, kWidth, kHeight, kWidth, \ - kHeight, \ - reinterpret_cast(ms->GetBuffer()), \ - data_size, 0, webrtc::kVideoRotation_0)); \ - int width_rotate = frame1.width(); \ - int height_rotate = frame1.height(); \ - EXPECT_TRUE(frame3.InitToBlack(width_rotate, height_rotate, 0)); \ - libyuv::I420Mirror(frame2.video_frame_buffer()->DataY(), \ - frame2.video_frame_buffer()->StrideY(), \ - frame2.video_frame_buffer()->DataU(), \ - frame2.video_frame_buffer()->StrideU(), \ - frame2.video_frame_buffer()->DataV(), \ - frame2.video_frame_buffer()->StrideV(), \ - frame3.video_frame_buffer()->MutableDataY(), \ - frame3.video_frame_buffer()->StrideY(), \ - frame3.video_frame_buffer()->MutableDataU(), \ - frame3.video_frame_buffer()->StrideU(), \ - frame3.video_frame_buffer()->MutableDataV(), \ - frame3.video_frame_buffer()->StrideV(), \ - kWidth, kHeight); \ - EXPECT_TRUE(IsEqual(frame1, frame3, 0)); \ - } - - TEST_MIRROR(I420, 420) - -// Macro to help test different rotations -#define TEST_ROTATE(FOURCC, BPP, ROTATE) \ - void Construct##FOURCC##Rotate##ROTATE() { \ - T frame1, frame2, frame3; \ - std::unique_ptr ms( \ - CreateYuvSample(kWidth, kHeight, BPP)); \ - ASSERT_TRUE(ms.get() != NULL); \ - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_##FOURCC, kWidth, kHeight, \ - kWidth, kHeight, webrtc::kVideoRotation_##ROTATE, \ - &frame1)); \ - size_t data_size; \ - bool ret = ms->GetSize(&data_size); \ - EXPECT_TRUE(ret); \ - EXPECT_TRUE(frame2.Init(cricket::FOURCC_##FOURCC, kWidth, kHeight, kWidth, \ - kHeight, \ - reinterpret_cast(ms->GetBuffer()), \ - data_size, 0, webrtc::kVideoRotation_0)); \ - int width_rotate = frame1.width(); \ - int height_rotate = frame1.height(); \ - EXPECT_TRUE(frame3.InitToBlack(width_rotate, height_rotate, 0)); \ - libyuv::I420Rotate(frame2.video_frame_buffer()->DataY(), \ - frame2.video_frame_buffer()->StrideY(), \ - frame2.video_frame_buffer()->DataU(), \ - frame2.video_frame_buffer()->StrideU(), \ - frame2.video_frame_buffer()->DataV(), \ - frame2.video_frame_buffer()->StrideV(), \ - frame3.video_frame_buffer()->MutableDataY(), \ - frame3.video_frame_buffer()->StrideY(), \ - frame3.video_frame_buffer()->MutableDataU(), \ - frame3.video_frame_buffer()->StrideU(), \ - frame3.video_frame_buffer()->MutableDataV(), \ - frame3.video_frame_buffer()->StrideV(), \ - kWidth, kHeight, libyuv::kRotate##ROTATE); \ - EXPECT_TRUE(IsEqual(frame1, frame3, 0)); \ - } - - // Test constructing an image with rotation. - TEST_ROTATE(I420, 12, 0) - TEST_ROTATE(I420, 12, 90) - TEST_ROTATE(I420, 12, 180) - TEST_ROTATE(I420, 12, 270) - TEST_ROTATE(YV12, 12, 0) - TEST_ROTATE(YV12, 12, 90) - TEST_ROTATE(YV12, 12, 180) - TEST_ROTATE(YV12, 12, 270) - TEST_ROTATE(NV12, 12, 0) - TEST_ROTATE(NV12, 12, 90) - TEST_ROTATE(NV12, 12, 180) - TEST_ROTATE(NV12, 12, 270) - TEST_ROTATE(NV21, 12, 0) - TEST_ROTATE(NV21, 12, 90) - TEST_ROTATE(NV21, 12, 180) - TEST_ROTATE(NV21, 12, 270) - TEST_ROTATE(UYVY, 16, 0) - TEST_ROTATE(UYVY, 16, 90) - TEST_ROTATE(UYVY, 16, 180) - TEST_ROTATE(UYVY, 16, 270) - TEST_ROTATE(YUY2, 16, 0) - TEST_ROTATE(YUY2, 16, 90) - TEST_ROTATE(YUY2, 16, 180) - TEST_ROTATE(YUY2, 16, 270) - - // Test constructing an image from a UYVY buffer rotated 90 degrees. - void ConstructUyvyRotate90() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_UYVY, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_UYVY, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_90, &frame2)); - } - - // Test constructing an image from a UYVY buffer rotated 180 degrees. - void ConstructUyvyRotate180() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_UYVY, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_UYVY, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_180, - &frame2)); - } - - // Test constructing an image from a UYVY buffer rotated 270 degrees. - void ConstructUyvyRotate270() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_UYVY, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_UYVY, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_270, - &frame2)); - } - - // Test constructing an image from a YUY2 buffer rotated 90 degrees. - void ConstructYuy2Rotate90() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_90, &frame2)); - } - - // Test constructing an image from a YUY2 buffer rotated 180 degrees. - void ConstructYuy2Rotate180() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_180, - &frame2)); - } - - // Test constructing an image from a YUY2 buffer rotated 270 degrees. - void ConstructYuy2Rotate270() { - T frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - kWidth, kHeight, webrtc::kVideoRotation_270, - &frame2)); - } - - // Test 1 pixel edge case image I420 buffer. - void ConstructI4201Pixel() { - T frame; - uint8_t pixel[3] = {1, 2, 3}; - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame.Init(cricket::FOURCC_I420, 1, 1, 1, 1, pixel, - sizeof(pixel), 0, webrtc::kVideoRotation_0)); - } - const uint8_t* y = pixel; - const uint8_t* u = y + 1; - const uint8_t* v = u + 1; - EXPECT_TRUE(IsEqual(frame, 1, 1, 0, y, 1, u, 1, v, 1, 0)); - } - - // Test 5 pixel edge case image. - void ConstructI4205Pixel() { - T frame; - uint8_t pixels5x5[5 * 5 + ((5 + 1) / 2 * (5 + 1) / 2) * 2]; - memset(pixels5x5, 1, 5 * 5 + ((5 + 1) / 2 * (5 + 1) / 2) * 2); - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame.Init(cricket::FOURCC_I420, 5, 5, 5, 5, pixels5x5, - sizeof(pixels5x5), 0, - webrtc::kVideoRotation_0)); - } - EXPECT_EQ(5, frame.width()); - EXPECT_EQ(5, frame.height()); - EXPECT_EQ(5, frame.video_frame_buffer()->StrideY()); - EXPECT_EQ(3, frame.video_frame_buffer()->StrideU()); - EXPECT_EQ(3, frame.video_frame_buffer()->StrideV()); - } - - // Test 1 pixel edge case image ARGB buffer. - void ConstructARGB1Pixel() { - T frame; - uint8_t pixel[4] = {64, 128, 192, 255}; - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame.Init(cricket::FOURCC_ARGB, 1, 1, 1, 1, pixel, - sizeof(pixel), 0, - webrtc::kVideoRotation_0)); - } - // Convert back to ARGB. - size_t out_size = 4; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment]); - uint8_t* out = ALIGNP(outbuf.get(), kAlignment); - - EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB, - out, - out_size, // buffer size - out_size)); // stride - #ifdef USE_LMI_CONVERT - // TODO(fbarchard): Expected to fail, but not crash. - EXPECT_FALSE(IsPlaneEqual("argb", pixel, 4, out, 4, 3, 1, 2)); - #else - // TODO(fbarchard): Check for overwrite. - EXPECT_TRUE(IsPlaneEqual("argb", pixel, 4, out, 4, 3, 1, 2)); - #endif - } - - // Test Black, White and Grey pixels. - void ConstructARGBBlackWhitePixel() { - T frame; - uint8_t pixel[10 * 4] = {0, 0, 0, 255, // Black. - 0, 0, 0, 255, // Black. - 64, 64, 64, 255, // Dark Grey. - 64, 64, 64, 255, // Dark Grey. - 128, 128, 128, 255, // Grey. - 128, 128, 128, 255, // Grey. - 196, 196, 196, 255, // Light Grey. - 196, 196, 196, 255, // Light Grey. - 255, 255, 255, 255, // White. - 255, 255, 255, 255}; // White. - - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame.Init(cricket::FOURCC_ARGB, 10, 1, 10, 1, pixel, - sizeof(pixel), 1, 1, 0, - webrtc::kVideoRotation_0)); - } - // Convert back to ARGB - size_t out_size = 10 * 4; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment]); - uint8_t* out = ALIGNP(outbuf.get(), kAlignment); - - EXPECT_EQ(out_size, frame.ConvertToRgbBuffer(cricket::FOURCC_ARGB, - out, - out_size, // buffer size. - out_size)); // stride. - EXPECT_TRUE(IsPlaneEqual("argb", pixel, out_size, - out, out_size, - out_size, 1, 2)); - } - - // Test constructing an image from an I420 buffer with horizontal cropping. - void ConstructI420CropHorizontal() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, - kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, - &frame2)); - EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 0)); - } - - // Test constructing an image from a YUY2 buffer with horizontal cropping. - void ConstructYuy2CropHorizontal() { - T frame1, frame2; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, - &frame2)); - EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 0)); - } - - // Test constructing an image from an ARGB buffer with horizontal cropping. - void ConstructARGBCropHorizontal() { - T frame1, frame2; - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ARGB, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ARGB, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, kWidth, kHeight, - kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, - &frame2)); - EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 2)); - } - - // Test constructing an image from an I420 buffer, cropping top and bottom. - void ConstructI420CropVertical() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, - kWidth, kHeight * 3 / 4, webrtc::kVideoRotation_0, - &frame2)); - EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, 0, kHeight / 8, 0)); - } - - // Test constructing an image from I420 synonymous formats. - void ConstructI420Aliases() { - T frame1, frame2, frame3; - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, - &frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_IYUV, kWidth, kHeight, - &frame2)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_YU12, kWidth, kHeight, - &frame3)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - EXPECT_TRUE(IsEqual(frame1, frame3, 0)); - } - - // Test constructing an image from an I420 MJPG buffer. - void ConstructMjpgI420() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg420Filename, - cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 32)); - } - - // Test constructing an image from an I422 MJPG buffer. - void ConstructMjpgI422() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg422Filename, - cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 32)); - } - - // Test constructing an image from an I444 MJPG buffer. - void ConstructMjpgI444() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg444Filename, - cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 32)); - } - - // Test constructing an image from an I444 MJPG buffer. - void ConstructMjpgI411() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg411Filename, - cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 32)); - } - - // Test constructing an image from an I400 MJPG buffer. - // TODO(fbarchard): Stronger compare on chroma. Compare agaisnt a grey image. - void ConstructMjpgI400() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg400Filename, - cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); - EXPECT_TRUE(IsPlaneEqual("y", frame1.video_frame_buffer()->DataY(), - frame1.video_frame_buffer()->StrideY(), - frame2.video_frame_buffer()->DataY(), - frame2.video_frame_buffer()->StrideY(), - kWidth, kHeight, 32)); - EXPECT_TRUE(IsEqual(frame1, frame2, 128)); - } - - // Test constructing an image from an I420 MJPG buffer. - void ValidateFrame(const char* name, - uint32_t fourcc, - int data_adjust, - int size_adjust, - bool expected_result) { - T frame; - std::unique_ptr ms(LoadSample(name)); - ASSERT_TRUE(ms.get() != NULL); - const uint8_t* sample = - reinterpret_cast(ms.get()->GetBuffer()); - size_t sample_size; - ms->GetSize(&sample_size); - // Optional adjust size to test invalid size. - size_t data_size = sample_size + data_adjust; - - // Allocate a buffer with end page aligned. - const int kPadToHeapSized = 16 * 1024 * 1024; - std::unique_ptr page_buffer( - new uint8_t[((data_size + kPadToHeapSized + 4095) & ~4095)]); - uint8_t* data_ptr = page_buffer.get(); - if (!data_ptr) { - LOG(LS_WARNING) << "Failed to allocate memory for ValidateFrame test."; - EXPECT_FALSE(expected_result); // NULL is okay if failure was expected. - return; - } - data_ptr += kPadToHeapSized + (-(static_cast(data_size)) & 4095); - memcpy(data_ptr, sample, std::min(data_size, sample_size)); - for (int i = 0; i < repeat_; ++i) { - EXPECT_EQ(expected_result, frame.Validate(fourcc, kWidth, kHeight, - data_ptr, - sample_size + size_adjust)); - } - } - - // Test validate for I420 MJPG buffer. - void ValidateMjpgI420() { - ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, 0, 0, true); - } - - // Test validate for I422 MJPG buffer. - void ValidateMjpgI422() { - ValidateFrame(kJpeg422Filename, cricket::FOURCC_MJPG, 0, 0, true); - } - - // Test validate for I444 MJPG buffer. - void ValidateMjpgI444() { - ValidateFrame(kJpeg444Filename, cricket::FOURCC_MJPG, 0, 0, true); - } - - // Test validate for I411 MJPG buffer. - void ValidateMjpgI411() { - ValidateFrame(kJpeg411Filename, cricket::FOURCC_MJPG, 0, 0, true); - } - - // Test validate for I400 MJPG buffer. - void ValidateMjpgI400() { - ValidateFrame(kJpeg400Filename, cricket::FOURCC_MJPG, 0, 0, true); - } - - // Test validate for I420 buffer. - void ValidateI420() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, 0, true); - } - - // Test validate for I420 buffer where size is too small - void ValidateI420SmallSize() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, -16384, false); - } - - // Test validate for I420 buffer where size is too large (16 MB) - // Will produce warning but pass. - void ValidateI420LargeSize() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 16000000, 16000000, - true); - } - - // Test validate for I420 buffer where size is 1 GB (not reasonable). - void ValidateI420HugeSize() { -#ifndef WIN32 // TODO(fbarchard): Reenable when fixing bug 9603762. - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 1000000000u, - 1000000000u, false); -#endif - } - - // The following test that Validate crashes if the size is greater than the - // actual buffer size. - // TODO(fbarchard): Consider moving a filter into the capturer/plugin. -#if defined(_MSC_VER) && !defined(NDEBUG) - int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) { - if (code == EXCEPTION_ACCESS_VIOLATION) { - LOG(LS_INFO) << "Caught EXCEPTION_ACCESS_VIOLATION as expected."; - return EXCEPTION_EXECUTE_HANDLER; - } else { - LOG(LS_INFO) << "Did not catch EXCEPTION_ACCESS_VIOLATION. Unexpected."; - return EXCEPTION_CONTINUE_SEARCH; - } - } - - // Test validate fails for truncated MJPG data buffer. If ValidateFrame - // crashes the exception handler will return and unittest passes with OK. - void ValidateMjpgI420InvalidSize() { - __try { - ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, -16384, 0, false); - FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; - } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { - return; // Successfully crashed in ValidateFrame. - } - } - - // Test validate fails for truncated I420 buffer. - void ValidateI420InvalidSize() { - __try { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, -16384, 0, false); - FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; - } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { - return; // Successfully crashed in ValidateFrame. - } - } -#endif - - // Test constructing an image from a YUY2 buffer (and synonymous formats). - void ConstructYuy2Aliases() { - T frame1, frame2, frame3, frame4; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_YUY2, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUVS, - kWidth, kHeight, &frame3)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUYV, - kWidth, kHeight, &frame4)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - EXPECT_TRUE(IsEqual(frame1, frame3, 0)); - EXPECT_TRUE(IsEqual(frame1, frame4, 0)); - } - - // Test constructing an image from a UYVY buffer (and synonymous formats). - void ConstructUyvyAliases() { - T frame1, frame2, frame3, frame4; - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_UYVY, kWidth, kHeight)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_UYVY, kWidth, kHeight, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_UYVY, - kWidth, kHeight, &frame2)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_2VUY, - kWidth, kHeight, &frame3)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_HDYC, - kWidth, kHeight, &frame4)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - EXPECT_TRUE(IsEqual(frame1, frame3, 0)); - EXPECT_TRUE(IsEqual(frame1, frame4, 0)); - } - - // Test creating a copy. - void ConstructCopy() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame2.Init(frame1)); - } - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - - // Test creating a copy and check that it just increments the refcount. - void ConstructCopyIsRef() { - T frame1, frame2; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame2.Init(frame1)); - } - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - EXPECT_EQ(frame1.video_frame_buffer(), frame2.video_frame_buffer()); - } - - // Test creating an empty image and initing it to black. - void ConstructBlack() { - T frame; - for (int i = 0; i < repeat_; ++i) { - EXPECT_TRUE(frame.InitToBlack(kWidth, kHeight, 0)); - } - EXPECT_TRUE(IsSize(frame, kWidth, kHeight)); - EXPECT_TRUE(IsBlack(frame)); - } - - // Test constructing an image from a YUY2 buffer with a range of sizes. - // Only tests that conversion does not crash or corrupt heap. - void ConstructYuy2AllSizes() { - T frame1, frame2; - for (int height = kMinHeightAll; height <= kMaxHeightAll; ++height) { - for (int width = kMinWidthAll; width <= kMaxWidthAll; ++width) { - std::unique_ptr ms( - CreateYuv422Sample(cricket::FOURCC_YUY2, width, height)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertYuv422(ms.get(), cricket::FOURCC_YUY2, width, height, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_YUY2, - width, height, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 0)); - } - } - } - - // Test constructing an image from a ARGB buffer with a range of sizes. - // Only tests that conversion does not crash or corrupt heap. - void ConstructARGBAllSizes() { - T frame1, frame2; - for (int height = kMinHeightAll; height <= kMaxHeightAll; ++height) { - for (int width = kMinWidthAll; width <= kMaxWidthAll; ++width) { - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ARGB, width, height)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ARGB, width, height, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, - width, height, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 64)); - } - } - // Test a practical window size for screencasting usecase. - const int kOddWidth = 1228; - const int kOddHeight = 260; - for (int j = 0; j < 2; ++j) { - for (int i = 0; i < 2; ++i) { - std::unique_ptr ms( - CreateRgbSample(cricket::FOURCC_ARGB, kOddWidth + i, kOddHeight + j)); - ASSERT_TRUE(ms.get() != NULL); - EXPECT_TRUE(ConvertRgb(ms.get(), cricket::FOURCC_ARGB, - kOddWidth + i, kOddHeight + j, - &frame1)); - EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, - kOddWidth + i, kOddHeight + j, &frame2)); - EXPECT_TRUE(IsEqual(frame1, frame2, 64)); - } - } - } - - ////////////////////// - // Conversion tests // - ////////////////////// - - enum ToFrom { TO, FROM }; - - // Helper function for test converting from I420 to packed formats. - inline void ConvertToBuffer(int bpp, - int rowpad, - bool invert, - ToFrom to_from, - int error, - uint32_t fourcc, - int (*RGBToI420)(const uint8_t* src_frame, - int src_stride_frame, - uint8_t* dst_y, - int dst_stride_y, - uint8_t* dst_u, - int dst_stride_u, - uint8_t* dst_v, - int dst_stride_v, - int width, - int height)) { - T frame1, frame2; - int repeat_to = (to_from == TO) ? repeat_ : 1; - int repeat_from = (to_from == FROM) ? repeat_ : 1; - - int astride = kWidth * bpp + rowpad; - size_t out_size = astride * kHeight; - std::unique_ptr outbuf(new uint8_t[out_size + kAlignment + 1]); - memset(outbuf.get(), 0, out_size + kAlignment + 1); - uint8_t* outtop = ALIGNP(outbuf.get(), kAlignment); - uint8_t* out = outtop; - int stride = astride; - if (invert) { - out += (kHeight - 1) * stride; // Point to last row. - stride = -stride; - } - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - - for (int i = 0; i < repeat_to; ++i) { - EXPECT_EQ(out_size, frame1.ConvertToRgbBuffer(fourcc, - out, - out_size, stride)); - } - EXPECT_TRUE(frame2.InitToBlack(kWidth, kHeight, 0)); - for (int i = 0; i < repeat_from; ++i) { - EXPECT_EQ(0, RGBToI420(out, stride, - frame2.video_frame_buffer()->MutableDataY(), - frame2.video_frame_buffer()->StrideY(), - frame2.video_frame_buffer()->MutableDataU(), - frame2.video_frame_buffer()->StrideU(), - frame2.video_frame_buffer()->MutableDataV(), - frame2.video_frame_buffer()->StrideV(), - kWidth, kHeight)); - } - if (rowpad) { - EXPECT_EQ(0, outtop[kWidth * bpp]); // Ensure stride skipped end of row. - EXPECT_NE(0, outtop[astride]); // Ensure pixel at start of 2nd row. - } else { - EXPECT_NE(0, outtop[kWidth * bpp]); // Expect something to be here. - } - EXPECT_EQ(0, outtop[out_size]); // Ensure no overrun. - EXPECT_TRUE(IsEqual(frame1, frame2, error)); - } - - static const int kError = 20; - static const int kErrorHigh = 40; - static const int kOddStride = 23; - - // Tests ConvertToRGBBuffer formats. - void ConvertToARGBBuffer() { - ConvertToBuffer(4, 0, false, TO, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertToBGRABuffer() { - ConvertToBuffer(4, 0, false, TO, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertToABGRBuffer() { - ConvertToBuffer(4, 0, false, TO, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertToRGB24Buffer() { - ConvertToBuffer(3, 0, false, TO, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertToRAWBuffer() { - ConvertToBuffer(3, 0, false, TO, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertToRGB565Buffer() { - ConvertToBuffer(2, 0, false, TO, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertToARGB1555Buffer() { - ConvertToBuffer(2, 0, false, TO, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertToARGB4444Buffer() { - ConvertToBuffer(2, 0, false, TO, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertToI400Buffer() { - ConvertToBuffer(1, 0, false, TO, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertToYUY2Buffer() { - ConvertToBuffer(2, 0, false, TO, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertToUYVYBuffer() { - ConvertToBuffer(2, 0, false, TO, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Tests ConvertToRGBBuffer formats with odd stride. - void ConvertToARGBBufferStride() { - ConvertToBuffer(4, kOddStride, false, TO, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertToBGRABufferStride() { - ConvertToBuffer(4, kOddStride, false, TO, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertToABGRBufferStride() { - ConvertToBuffer(4, kOddStride, false, TO, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertToRGB24BufferStride() { - ConvertToBuffer(3, kOddStride, false, TO, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertToRAWBufferStride() { - ConvertToBuffer(3, kOddStride, false, TO, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertToRGB565BufferStride() { - ConvertToBuffer(2, kOddStride, false, TO, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertToARGB1555BufferStride() { - ConvertToBuffer(2, kOddStride, false, TO, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertToARGB4444BufferStride() { - ConvertToBuffer(2, kOddStride, false, TO, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertToI400BufferStride() { - ConvertToBuffer(1, kOddStride, false, TO, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertToYUY2BufferStride() { - ConvertToBuffer(2, kOddStride, false, TO, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertToUYVYBufferStride() { - ConvertToBuffer(2, kOddStride, false, TO, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Tests ConvertToRGBBuffer formats with negative stride to invert image. - void ConvertToARGBBufferInverted() { - ConvertToBuffer(4, 0, true, TO, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertToBGRABufferInverted() { - ConvertToBuffer(4, 0, true, TO, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertToABGRBufferInverted() { - ConvertToBuffer(4, 0, true, TO, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertToRGB24BufferInverted() { - ConvertToBuffer(3, 0, true, TO, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertToRAWBufferInverted() { - ConvertToBuffer(3, 0, true, TO, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertToRGB565BufferInverted() { - ConvertToBuffer(2, 0, true, TO, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertToARGB1555BufferInverted() { - ConvertToBuffer(2, 0, true, TO, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertToARGB4444BufferInverted() { - ConvertToBuffer(2, 0, true, TO, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertToI400BufferInverted() { - ConvertToBuffer(1, 0, true, TO, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertToYUY2BufferInverted() { - ConvertToBuffer(2, 0, true, TO, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertToUYVYBufferInverted() { - ConvertToBuffer(2, 0, true, TO, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Tests ConvertFrom formats. - void ConvertFromARGBBuffer() { - ConvertToBuffer(4, 0, false, FROM, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertFromBGRABuffer() { - ConvertToBuffer(4, 0, false, FROM, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertFromABGRBuffer() { - ConvertToBuffer(4, 0, false, FROM, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertFromRGB24Buffer() { - ConvertToBuffer(3, 0, false, FROM, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertFromRAWBuffer() { - ConvertToBuffer(3, 0, false, FROM, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertFromRGB565Buffer() { - ConvertToBuffer(2, 0, false, FROM, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertFromARGB1555Buffer() { - ConvertToBuffer(2, 0, false, FROM, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertFromARGB4444Buffer() { - ConvertToBuffer(2, 0, false, FROM, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertFromI400Buffer() { - ConvertToBuffer(1, 0, false, FROM, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertFromYUY2Buffer() { - ConvertToBuffer(2, 0, false, FROM, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertFromUYVYBuffer() { - ConvertToBuffer(2, 0, false, FROM, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Tests ConvertFrom formats with odd stride. - void ConvertFromARGBBufferStride() { - ConvertToBuffer(4, kOddStride, false, FROM, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertFromBGRABufferStride() { - ConvertToBuffer(4, kOddStride, false, FROM, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertFromABGRBufferStride() { - ConvertToBuffer(4, kOddStride, false, FROM, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertFromRGB24BufferStride() { - ConvertToBuffer(3, kOddStride, false, FROM, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertFromRAWBufferStride() { - ConvertToBuffer(3, kOddStride, false, FROM, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertFromRGB565BufferStride() { - ConvertToBuffer(2, kOddStride, false, FROM, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertFromARGB1555BufferStride() { - ConvertToBuffer(2, kOddStride, false, FROM, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertFromARGB4444BufferStride() { - ConvertToBuffer(2, kOddStride, false, FROM, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertFromI400BufferStride() { - ConvertToBuffer(1, kOddStride, false, FROM, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertFromYUY2BufferStride() { - ConvertToBuffer(2, kOddStride, false, FROM, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertFromUYVYBufferStride() { - ConvertToBuffer(2, kOddStride, false, FROM, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Tests ConvertFrom formats with negative stride to invert image. - void ConvertFromARGBBufferInverted() { - ConvertToBuffer(4, 0, true, FROM, kError, - cricket::FOURCC_ARGB, libyuv::ARGBToI420); - } - void ConvertFromBGRABufferInverted() { - ConvertToBuffer(4, 0, true, FROM, kError, - cricket::FOURCC_BGRA, libyuv::BGRAToI420); - } - void ConvertFromABGRBufferInverted() { - ConvertToBuffer(4, 0, true, FROM, kError, - cricket::FOURCC_ABGR, libyuv::ABGRToI420); - } - void ConvertFromRGB24BufferInverted() { - ConvertToBuffer(3, 0, true, FROM, kError, - cricket::FOURCC_24BG, libyuv::RGB24ToI420); - } - void ConvertFromRAWBufferInverted() { - ConvertToBuffer(3, 0, true, FROM, kError, - cricket::FOURCC_RAW, libyuv::RAWToI420); - } - void ConvertFromRGB565BufferInverted() { - ConvertToBuffer(2, 0, true, FROM, kError, - cricket::FOURCC_RGBP, libyuv::RGB565ToI420); - } - void ConvertFromARGB1555BufferInverted() { - ConvertToBuffer(2, 0, true, FROM, kError, - cricket::FOURCC_RGBO, libyuv::ARGB1555ToI420); - } - void ConvertFromARGB4444BufferInverted() { - ConvertToBuffer(2, 0, true, FROM, kError, - cricket::FOURCC_R444, libyuv::ARGB4444ToI420); - } - void ConvertFromI400BufferInverted() { - ConvertToBuffer(1, 0, true, FROM, 128, - cricket::FOURCC_I400, libyuv::I400ToI420); - } - void ConvertFromYUY2BufferInverted() { - ConvertToBuffer(2, 0, true, FROM, kError, - cricket::FOURCC_YUY2, libyuv::YUY2ToI420); - } - void ConvertFromUYVYBufferInverted() { - ConvertToBuffer(2, 0, true, FROM, kError, - cricket::FOURCC_UYVY, libyuv::UYVYToI420); - } - - // Test converting from I420 to I422. - void ConvertToI422Buffer() { - T frame1, frame2; - size_t out_size = kWidth * kHeight * 2; - std::unique_ptr buf(new uint8_t[out_size + kAlignment]); - uint8_t* y = ALIGNP(buf.get(), kAlignment); - uint8_t* u = y + kWidth * kHeight; - uint8_t* v = u + (kWidth / 2) * kHeight; - ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - for (int i = 0; i < repeat_; ++i) { - EXPECT_EQ(0, libyuv::I420ToI422(frame1.video_frame_buffer()->DataY(), - frame1.video_frame_buffer()->StrideY(), - frame1.video_frame_buffer()->DataU(), - frame1.video_frame_buffer()->StrideU(), - frame1.video_frame_buffer()->DataV(), - frame1.video_frame_buffer()->StrideV(), - y, kWidth, - u, kWidth / 2, - v, kWidth / 2, - kWidth, kHeight)); - } - EXPECT_TRUE(frame2.Init(cricket::FOURCC_I422, kWidth, kHeight, kWidth, - kHeight, y, out_size, 1, 1, 0, - webrtc::kVideoRotation_0)); - EXPECT_TRUE(IsEqual(frame1, frame2, 1)); - } - - /////////////////// - // General tests // - /////////////////// - - void Copy() { - std::unique_ptr source(new T); - std::unique_ptr target; - ASSERT_TRUE(LoadFrameNoRepeat(source.get())); - target.reset(source->Copy()); - EXPECT_TRUE(IsEqual(*source, *target, 0)); - source.reset(); - ASSERT_TRUE(target->video_frame_buffer() != NULL); - EXPECT_TRUE(target->video_frame_buffer()->DataY() != NULL); - } - - void CopyIsRef() { - std::unique_ptr source(new T); - std::unique_ptr target; - ASSERT_TRUE(LoadFrameNoRepeat(source.get())); - target.reset(source->Copy()); - EXPECT_TRUE(IsEqual(*source, *target, 0)); - const T* const_source = source.get(); - EXPECT_EQ(const_source->video_frame_buffer(), target->video_frame_buffer()); - } - - void StretchToFrame() { - // Create the source frame as a black frame. - T source; - EXPECT_TRUE(source.InitToBlack(kWidth * 2, kHeight * 2, 0)); - EXPECT_TRUE(IsSize(source, kWidth * 2, kHeight * 2)); - - // Create the target frame by loading from a file. - T target1; - ASSERT_TRUE(LoadFrameNoRepeat(&target1)); - EXPECT_FALSE(IsBlack(target1)); - - // Stretch and check if the stretched target is black. - source.StretchToFrame(&target1, true, false); - EXPECT_TRUE(IsBlack(target1)); - - // Crop and stretch and check if the stretched target is black. - T target2; - ASSERT_TRUE(LoadFrameNoRepeat(&target2)); - source.StretchToFrame(&target2, true, true); - EXPECT_TRUE(IsBlack(target2)); - EXPECT_EQ(source.GetTimeStamp(), target2.GetTimeStamp()); - } - - int repeat_; -}; - -#endif // WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ diff --git a/include/webrtc/media/base/videoframefactory.h b/include/webrtc/media/base/videoframefactory.h deleted file mode 100644 index 6aa2ce5..0000000 --- a/include/webrtc/media/base/videoframefactory.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_BASE_VIDEOFRAMEFACTORY_H_ -#define WEBRTC_MEDIA_BASE_VIDEOFRAMEFACTORY_H_ - -#include - -#include "webrtc/media/base/videoframe.h" - -namespace cricket { - -struct CapturedFrame; -class VideoFrame; - -// Creates cricket::VideoFrames, or a subclass of cricket::VideoFrame -// depending on the subclass of VideoFrameFactory. -class VideoFrameFactory { - public: - VideoFrameFactory() : apply_rotation_(false) {} - virtual ~VideoFrameFactory() {} - - // The returned frame aliases the aliased_frame if the input color - // space allows for aliasing, otherwise a color conversion will - // occur. Returns NULL if conversion fails. - - // The returned frame will be a center crop of |input_frame| with - // size |cropped_width| x |cropped_height|. - virtual VideoFrame* CreateAliasedFrame(const CapturedFrame* input_frame, - int cropped_width, - int cropped_height) const = 0; - - // The returned frame will be a center crop of |input_frame| with size - // |cropped_width| x |cropped_height|, scaled to |output_width| x - // |output_height|. - virtual VideoFrame* CreateAliasedFrame(const CapturedFrame* input_frame, - int cropped_input_width, - int cropped_input_height, - int output_width, - int output_height) const; - - void SetApplyRotation(bool enable) { apply_rotation_ = enable; } - - protected: - bool apply_rotation_; - - private: - // An internal frame buffer to avoid reallocations. It is mutable because it - // does not affect behaviour, only performance. - mutable std::unique_ptr output_frame_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_VIDEOFRAMEFACTORY_H_ diff --git a/include/webrtc/media/base/videosinkinterface.h b/include/webrtc/media/base/videosinkinterface.h index df7677b..f8b20b0 100644 --- a/include/webrtc/media/base/videosinkinterface.h +++ b/include/webrtc/media/base/videosinkinterface.h @@ -19,9 +19,9 @@ namespace rtc { template class VideoSinkInterface { public: - virtual void OnFrame(const VideoFrameT& frame) = 0; - protected: virtual ~VideoSinkInterface() {} + + virtual void OnFrame(const VideoFrameT& frame) = 0; }; } // namespace rtc diff --git a/include/webrtc/media/base/videosourcebase.h b/include/webrtc/media/base/videosourcebase.h index 40d2fb3..36c6e4e 100644 --- a/include/webrtc/media/base/videosourcebase.h +++ b/include/webrtc/media/base/videosourcebase.h @@ -13,29 +13,28 @@ #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/thread_checker.h" -#include "webrtc/media/base/videoframe.h" #include "webrtc/media/base/videosourceinterface.h" namespace rtc { // VideoSourceBase is not thread safe. -class VideoSourceBase : public VideoSourceInterface { +class VideoSourceBase : public VideoSourceInterface { public: VideoSourceBase(); - void AddOrUpdateSink(VideoSinkInterface* sink, + void AddOrUpdateSink(VideoSinkInterface* sink, const VideoSinkWants& wants) override; - void RemoveSink(VideoSinkInterface* sink) override; + void RemoveSink(VideoSinkInterface* sink) override; protected: struct SinkPair { - SinkPair(VideoSinkInterface* sink, - VideoSinkWants wants) + SinkPair(VideoSinkInterface* sink, VideoSinkWants wants) : sink(sink), wants(wants) {} - VideoSinkInterface* sink; + VideoSinkInterface* sink; VideoSinkWants wants; }; - SinkPair* FindSinkPair(const VideoSinkInterface* sink); + SinkPair* FindSinkPair(const VideoSinkInterface* sink); const std::vector& sink_pairs() const { return sinks_; } ThreadChecker thread_checker_; diff --git a/include/webrtc/media/base/videosourceinterface.h b/include/webrtc/media/base/videosourceinterface.h index bae02c8..0ea1c60 100644 --- a/include/webrtc/media/base/videosourceinterface.h +++ b/include/webrtc/media/base/videosourceinterface.h @@ -28,12 +28,12 @@ struct VideoSinkWants { // Tells the source the maximum number of pixels the sink wants. rtc::Optional max_pixel_count; - // Like |max_pixel_count| but relative to the given value. The source is - // requested to produce frames with a resolution one "step up" from the given - // value. In practice, this means that the sink can consume this amount of - // pixels but wants more and the source should produce a resolution one - // "step" higher than this but not higher. - rtc::Optional max_pixel_count_step_up; + // Tells the source the desired number of pixels the sinks wants. This will + // typically be used when stepping the resolution up again when conditions + // have improved after an earlier downgrade. The source should select the + // closest resolution to this pixel count, but if max_pixel_count is set, it + // still sets the absolute upper bound. + rtc::Optional target_pixel_count; }; template diff --git a/include/webrtc/media/base/yuvframegenerator.h b/include/webrtc/media/base/yuvframegenerator.h deleted file mode 100644 index bb3ed48..0000000 --- a/include/webrtc/media/base/yuvframegenerator.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Generates YUV420 frames with a "landscape with striped crosshair" in the -// Y-plane, plus a horizontal gradient in the U-plane and a vertical one in the -// V-plane. This makes for a nice mix of colours that is suited for both -// catching visual errors and making sure e.g. YUV->RGB/BGR conversion looks -// the same on different platforms. -// There is also a solid box bouncing around in the Y-plane, and two differently -// coloured lines bouncing horizontally and vertically in the U and V plane. -// This helps illustrating how the frame boundary goes, and can aid as a quite -// handy visual help for noticing e.g. packet loss if the frames are encoded -// and sent over the network. - -#ifndef WEBRTC_MEDIA_BASE_YUVFRAMEGENERATOR_H_ -#define WEBRTC_MEDIA_BASE_YUVFRAMEGENERATOR_H_ - -#include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" - -namespace cricket { - -class YuvFrameGenerator { - public: - // Constructs a frame-generator that produces frames of size |width|x|height|. - // If |enable_barcode| is specified, barcodes can be included in the frames - // when calling |GenerateNextFrame(uint8_t*, uint32_t)|. If |enable_barcode| - // is |true| then |width|x|height| should be at least 160x100; otherwise this - // constructor will abort. - YuvFrameGenerator(int width, int height, bool enable_barcode); - ~YuvFrameGenerator(); - - int GetFrameSize() { return frame_data_size_; } - - // Generate the next frame and return it in the provided |frame_buffer|. If - // barcode_value is not |nullptr| the value referred by it will be encoded - // into a barcode in the frame. The value should in the range: - // [0..9,999,999]. If the value exceeds this range or barcodes were not - // requested in the constructor, this function will abort. - void GenerateNextFrame(uint8_t* frame_buffer, int32_t barcode_value); - - int GetHeight() { return height_; } - int GetWidth() { return width_; } - - // Fetch the bounds of the barcode from the generator. The barcode will - // always be at this location. This function will abort if barcodes were not - // requested in the constructor. - void GetBarcodeBounds(int* top, int* left, int* width, int* height); - - private: - void DrawLandscape(uint8_t* p, int w, int h); - void DrawGradientX(uint8_t* p, int w, int h); - void DrawGradientY(uint8_t* p, int w, int h); - void DrawMovingLineX(uint8_t* p, int w, int h, int n); - void DrawMovingLineY(uint8_t* p, int w, int h, int n); - void DrawBouncingCube(uint8_t* p, int w, int h, int n); - - void DrawBarcode(uint32_t value); - int DrawSideGuardBars(int x, int y, int height); - int DrawMiddleGuardBars(int x, int y, int height); - int DrawEanEncodedDigit(int digit, int x, int y, int height, bool r_code); - void DrawBlockRectangle(uint8_t* p, - int x_start, - int y_start, - int width, - int height, - int pitch, - uint8_t value); - - private: - int width_; - int height_; - int frame_index_; - int frame_data_size_; - uint8_t* y_data_; - uint8_t* u_data_; - uint8_t* v_data_; - - int barcode_start_x_; - int barcode_start_y_; - - RTC_DISALLOW_COPY_AND_ASSIGN(YuvFrameGenerator); -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_BASE_YUVFRAMEGENERATOR_H_ diff --git a/include/webrtc/media/devices/carbonvideorenderer.h b/include/webrtc/media/devices/carbonvideorenderer.h deleted file mode 100644 index e90c131..0000000 --- a/include/webrtc/media/devices/carbonvideorenderer.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Definition of class CarbonVideoRenderer that implements the abstract class -// cricket::VideoRenderer via Carbon. - -#ifndef WEBRTC_MEDIA_DEVICES_CARBONVIDEORENDERER_H_ -#define WEBRTC_MEDIA_DEVICES_CARBONVIDEORENDERER_H_ - -#include - -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/media/base/videosinkinterface.h" - -namespace cricket { - -class CarbonVideoRenderer - : public rtc::VideoSinkInterface { - public: - CarbonVideoRenderer(int x, int y); - virtual ~CarbonVideoRenderer(); - - // Implementation of VideoSinkInterface. - void OnFrame(const VideoFrame& frame) override; - - // Needs to be called on the main thread. - bool Initialize(); - - private: - bool SetSize(int width, int height); - bool DrawFrame(); - - static OSStatus DrawEventHandler(EventHandlerCallRef handler, - EventRef event, - void* data); - std::unique_ptr image_; - rtc::CriticalSection image_crit_; - int image_width_; - int image_height_; - int x_; - int y_; - WindowRef window_ref_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_DEVICES_CARBONVIDEORENDERER_H_ diff --git a/include/webrtc/media/devices/gdivideorenderer.h b/include/webrtc/media/devices/gdivideorenderer.h deleted file mode 100644 index c88ebd7..0000000 --- a/include/webrtc/media/devices/gdivideorenderer.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// -// Definition of class GdiVideoRenderer that implements the abstract class -// cricket::VideoRenderer via GDI on Windows. - -#ifndef WEBRTC_MEDIA_DEVICES_GDIVIDEORENDERER_H_ -#define WEBRTC_MEDIA_DEVICES_GDIVIDEORENDERER_H_ -#ifdef WIN32 - -#include - -#include "webrtc/media/base/videosinkinterface.h" - -namespace cricket { - -class VideoFrame; - -class GdiVideoRenderer : public rtc::VideoSinkInterface { - public: - GdiVideoRenderer(int x, int y); - virtual ~GdiVideoRenderer(); - - // Implementation of VideoSinkInterface - void OnFrame(const VideoFrame& frame) override; - - private: - class VideoWindow; // forward declaration, defined in the .cc file - std::unique_ptr window_; - // The initial position of the window. - int initial_x_; - int initial_y_; -}; - -} // namespace cricket - -#endif // WIN32 -#endif // WEBRTC_MEDIA_DEVICES_GDIVIDEORENDERER_H_ diff --git a/include/webrtc/media/devices/gtkvideorenderer.h b/include/webrtc/media/devices/gtkvideorenderer.h deleted file mode 100644 index 750a5bb..0000000 --- a/include/webrtc/media/devices/gtkvideorenderer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Definition of class GtkVideoRenderer that implements the abstract class -// cricket::VideoRenderer via GTK. - -#ifndef WEBRTC_MEDIA_DEVICES_GTKVIDEORENDERER_H_ -#define WEBRTC_MEDIA_DEVICES_GTKVIDEORENDERER_H_ - -#include - -#include "webrtc/base/basictypes.h" -#include "webrtc/media/base/videosinkinterface.h" - -typedef struct _GtkWidget GtkWidget; // forward declaration, defined in gtk.h - -namespace cricket { - -class VideoFrame; - -class GtkVideoRenderer : public rtc::VideoSinkInterface { - public: - GtkVideoRenderer(int x, int y); - virtual ~GtkVideoRenderer(); - - // Implementation of VideoSinkInterface. - void OnFrame(const VideoFrame& frame) override; - - private: - bool SetSize(int width, int height); - // Initialize the attributes when the first frame arrives. - bool Initialize(int width, int height); - // Pump the Gtk event loop until there are no events left. - void Pump(); - // Check if the window has been closed. - bool IsClosed() const; - - std::unique_ptr image_; - GtkWidget* window_; - GtkWidget* draw_area_; - // The initial position of the window. - int initial_x_; - int initial_y_; - - int width_; - int height_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_DEVICES_GTKVIDEORENDERER_H_ diff --git a/include/webrtc/media/devices/videorendererfactory.h b/include/webrtc/media/devices/videorendererfactory.h deleted file mode 100644 index 0bacdbd..0000000 --- a/include/webrtc/media/devices/videorendererfactory.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// -// A factory to create a GUI video renderer. - -#ifndef WEBRTC_MEDIA_DEVICES_VIDEORENDERERFACTORY_H_ -#define WEBRTC_MEDIA_DEVICES_VIDEORENDERERFACTORY_H_ - -#include "webrtc/media/base/videosinkinterface.h" -#if defined(WEBRTC_LINUX) && defined(HAVE_GTK) -#include "webrtc/media/devices/gtkvideorenderer.h" -#elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) && !defined(CARBON_DEPRECATED) -#include "webrtc/media/devices/carbonvideorenderer.h" -#elif defined(WIN32) -#include "webrtc/media/devices/gdivideorenderer.h" -#endif - -namespace cricket { - -class VideoRendererFactory { - public: - static rtc::VideoSinkInterface* CreateGuiVideoRenderer( - int x, - int y) { - #if defined(WEBRTC_LINUX) && defined(HAVE_GTK) - return new GtkVideoRenderer(x, y); - #elif defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) && \ - !defined(CARBON_DEPRECATED) - CarbonVideoRenderer* renderer = new CarbonVideoRenderer(x, y); - // Needs to be initialized on the main thread. - if (renderer->Initialize()) { - return renderer; - } else { - delete renderer; - return NULL; - } - #elif defined(WIN32) - return new GdiVideoRenderer(x, y); - #else - return NULL; - #endif - } -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_DEVICES_VIDEORENDERERFACTORY_H_ diff --git a/include/webrtc/media/engine/apm_helpers.h b/include/webrtc/media/engine/apm_helpers.h new file mode 100644 index 0000000..1bcf051 --- /dev/null +++ b/include/webrtc/media/engine/apm_helpers.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_ +#define WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_ + +#include "webrtc/common_types.h" + +namespace webrtc { + +class AudioProcessing; +class AudioDeviceModule; + +namespace apm_helpers { + +AgcConfig GetAgcConfig(AudioProcessing* apm); +void SetAgcConfig(AudioProcessing* apm, + const AgcConfig& config); +void SetAgcStatus(AudioProcessing* apm, + AudioDeviceModule* adm, + bool enable, + AgcModes mode); +void SetEcStatus(AudioProcessing* apm, + bool enable, + EcModes mode); +void SetEcMetricsStatus(AudioProcessing* apm, bool enable); +void SetAecmMode(AudioProcessing* apm, bool enable_cng); +void SetNsStatus(AudioProcessing* apm, bool enable); +void SetTypingDetectionStatus(AudioProcessing* apm, bool enable); + +} // namespace apm_helpers +} // namespace webrtc + +#endif // WEBRTC_MEDIA_ENGINE_APM_HELPERS_H_ diff --git a/include/webrtc/media/engine/constants.h b/include/webrtc/media/engine/constants.h index 68a2bc6..19d06a1 100644 --- a/include/webrtc/media/engine/constants.h +++ b/include/webrtc/media/engine/constants.h @@ -18,9 +18,7 @@ extern const int kVideoRtpBufferSize; extern const char kH264CodecName[]; -extern const int kMinVideoBitrate; -extern const int kStartVideoBitrate; -extern const int kMaxVideoBitrate; +extern const int kMinVideoBitrateKbps; } // namespace cricket diff --git a/include/webrtc/media/engine/fakewebrtccall.h b/include/webrtc/media/engine/fakewebrtccall.h index c9caf8e..8a1547b 100644 --- a/include/webrtc/media/engine/fakewebrtccall.h +++ b/include/webrtc/media/engine/fakewebrtccall.h @@ -21,13 +21,15 @@ #define WEBRTC_MEDIA_ENGINE_FAKEWEBRTCCALL_H_ #include +#include #include -#include "webrtc/audio_receive_stream.h" -#include "webrtc/audio_send_stream.h" +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/buffer.h" -#include "webrtc/call.h" -#include "webrtc/video_frame.h" +#include "webrtc/call/audio_receive_stream.h" +#include "webrtc/call/audio_send_stream.h" +#include "webrtc/call/call.h" +#include "webrtc/call/flexfec_receive_stream.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" @@ -36,69 +38,85 @@ class FakeAudioSendStream final : public webrtc::AudioSendStream { public: struct TelephoneEvent { int payload_type = -1; + int payload_frequency = -1; int event_code = 0; int duration_ms = 0; }; - explicit FakeAudioSendStream(const webrtc::AudioSendStream::Config& config); + explicit FakeAudioSendStream( + int id, const webrtc::AudioSendStream::Config& config); + int id() const { return id_; } const webrtc::AudioSendStream::Config& GetConfig() const; void SetStats(const webrtc::AudioSendStream::Stats& stats); TelephoneEvent GetLatestTelephoneEvent() const; bool IsSending() const { return sending_; } + bool muted() const { return muted_; } private: // webrtc::AudioSendStream implementation. void Start() override { sending_ = true; } void Stop() override { sending_ = false; } - bool SendTelephoneEvent(int payload_type, int event, + bool SendTelephoneEvent(int payload_type, int payload_frequency, int event, int duration_ms) override; + void SetMuted(bool muted) override; webrtc::AudioSendStream::Stats GetStats() const override; + int id_ = -1; TelephoneEvent latest_telephone_event_; webrtc::AudioSendStream::Config config_; webrtc::AudioSendStream::Stats stats_; bool sending_ = false; + bool muted_ = false; }; class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream { public: explicit FakeAudioReceiveStream( - const webrtc::AudioReceiveStream::Config& config); + int id, const webrtc::AudioReceiveStream::Config& config); + int id() const { return id_; } const webrtc::AudioReceiveStream::Config& GetConfig() const; void SetStats(const webrtc::AudioReceiveStream::Stats& stats); int received_packets() const { return received_packets_; } bool VerifyLastPacket(const uint8_t* data, size_t length) const; const webrtc::AudioSinkInterface* sink() const { return sink_.get(); } + float gain() const { return gain_; } bool DeliverRtp(const uint8_t* packet, size_t length, const webrtc::PacketTime& packet_time); + bool started() const { return started_; } private: // webrtc::AudioReceiveStream implementation. - void Start() override {} - void Stop() override {} + void Start() override { started_ = true; } + void Stop() override { started_ = false; } webrtc::AudioReceiveStream::Stats GetStats() const override; void SetSink(std::unique_ptr sink) override; + void SetGain(float gain) override; + int id_ = -1; webrtc::AudioReceiveStream::Config config_; webrtc::AudioReceiveStream::Stats stats_; - int received_packets_; + int received_packets_ = 0; std::unique_ptr sink_; + float gain_ = 1.0f; rtc::Buffer last_packet_; + bool started_ = false; }; -class FakeVideoSendStream final : public webrtc::VideoSendStream, - public webrtc::VideoCaptureInput { +class FakeVideoSendStream final + : public webrtc::VideoSendStream, + public rtc::VideoSinkInterface { public: - FakeVideoSendStream(const webrtc::VideoSendStream::Config& config, - const webrtc::VideoEncoderConfig& encoder_config); - webrtc::VideoSendStream::Config GetConfig() const; - webrtc::VideoEncoderConfig GetEncoderConfig() const; - std::vector GetVideoStreams(); + FakeVideoSendStream(webrtc::VideoSendStream::Config config, + webrtc::VideoEncoderConfig encoder_config); + ~FakeVideoSendStream() override; + const webrtc::VideoSendStream::Config& GetConfig() const; + const webrtc::VideoEncoderConfig& GetEncoderConfig() const; + const std::vector& GetVideoStreams() const; bool IsSending() const; bool GetVp8Settings(webrtc::VideoCodecVP8* settings) const; @@ -113,37 +131,55 @@ class FakeVideoSendStream final : public webrtc::VideoSendStream, return num_encoder_reconfigurations_; } + void EnableEncodedFrameRecording(const std::vector& files, + size_t byte_limit) override; + + bool resolution_scaling_enabled() const { + return resolution_scaling_enabled_; + } + void InjectVideoSinkWants(const rtc::VideoSinkWants& wants); + + rtc::VideoSourceInterface* source() const { + return source_; + } + private: - void IncomingCapturedFrame(const webrtc::VideoFrame& frame) override; + // rtc::VideoSinkInterface implementation. + void OnFrame(const webrtc::VideoFrame& frame) override; // webrtc::VideoSendStream implementation. void Start() override; void Stop() override; + void SetSource(rtc::VideoSourceInterface* source, + const webrtc::VideoSendStream::DegradationPreference& + degradation_preference) override; webrtc::VideoSendStream::Stats GetStats() override; - void ReconfigureVideoEncoder( - const webrtc::VideoEncoderConfig& config) override; - webrtc::VideoCaptureInput* Input() override; + void ReconfigureVideoEncoder(webrtc::VideoEncoderConfig config) override; bool sending_; webrtc::VideoSendStream::Config config_; webrtc::VideoEncoderConfig encoder_config_; + std::vector video_streams_; + rtc::VideoSinkWants sink_wants_; + bool codec_settings_set_; union VpxSettings { webrtc::VideoCodecVP8 vp8; webrtc::VideoCodecVP9 vp9; } vpx_settings_; + bool resolution_scaling_enabled_; + rtc::VideoSourceInterface* source_; int num_swapped_frames_; - webrtc::VideoFrame last_frame_; + rtc::Optional last_frame_; webrtc::VideoSendStream::Stats stats_; int num_encoder_reconfigurations_ = 0; }; class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream { public: - explicit FakeVideoReceiveStream( - const webrtc::VideoReceiveStream::Config& config); + explicit FakeVideoReceiveStream(webrtc::VideoReceiveStream::Config config); - webrtc::VideoReceiveStream::Config GetConfig(); + const webrtc::VideoReceiveStream::Config& GetConfig() const; bool IsReceiving() const; @@ -151,6 +187,9 @@ class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream { void SetStats(const webrtc::VideoReceiveStream::Stats& stats); + void EnableEncodedFrameRecording(rtc::PlatformFile file, + size_t byte_limit) override; + private: // webrtc::VideoReceiveStream implementation. void Start() override; @@ -163,6 +202,24 @@ class FakeVideoReceiveStream final : public webrtc::VideoReceiveStream { webrtc::VideoReceiveStream::Stats stats_; }; +class FakeFlexfecReceiveStream final : public webrtc::FlexfecReceiveStream { + public: + explicit FakeFlexfecReceiveStream( + const webrtc::FlexfecReceiveStream::Config& config); + + const webrtc::FlexfecReceiveStream::Config& GetConfig() const; + + private: + // webrtc::FlexfecReceiveStream implementation. + void Start() override; + void Stop() override; + + webrtc::FlexfecReceiveStream::Stats GetStats() const override; + + webrtc::FlexfecReceiveStream::Config config_; + bool receiving_; +}; + class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { public: explicit FakeCall(const webrtc::Call::Config& config); @@ -177,7 +234,16 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { const std::vector& GetAudioReceiveStreams(); const FakeAudioReceiveStream* GetAudioReceiveStream(uint32_t ssrc); + const std::vector& GetFlexfecReceiveStreams(); + rtc::SentPacket last_sent_packet() const { return last_sent_packet_; } + + // This is useful if we care about the last media packet (with id populated) + // but not the last ICE packet (with -1 ID). + int last_sent_nonnegative_packet_id() const { + return last_sent_nonnegative_packet_id_; + } + webrtc::NetworkState GetNetworkState(webrtc::MediaType media) const; int GetNumCreatedSendStreams() const; int GetNumCreatedReceiveStreams() const; @@ -194,14 +260,20 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { webrtc::AudioReceiveStream* receive_stream) override; webrtc::VideoSendStream* CreateVideoSendStream( - const webrtc::VideoSendStream::Config& config, - const webrtc::VideoEncoderConfig& encoder_config) override; + webrtc::VideoSendStream::Config config, + webrtc::VideoEncoderConfig encoder_config) override; void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) override; webrtc::VideoReceiveStream* CreateVideoReceiveStream( - const webrtc::VideoReceiveStream::Config& config) override; + webrtc::VideoReceiveStream::Config config) override; void DestroyVideoReceiveStream( webrtc::VideoReceiveStream* receive_stream) override; + + webrtc::FlexfecReceiveStream* CreateFlexfecReceiveStream( + const webrtc::FlexfecReceiveStream::Config& config) override; + void DestroyFlexfecReceiveStream( + webrtc::FlexfecReceiveStream* receive_stream) override; + webrtc::PacketReceiver* Receiver() override; DeliveryStatus DeliverPacket(webrtc::MediaType media_type, @@ -217,21 +289,29 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { const rtc::NetworkRoute& network_route) override {} void SignalChannelNetworkState(webrtc::MediaType media, webrtc::NetworkState state) override; + void OnTransportOverheadChanged(webrtc::MediaType media, + int transport_overhead_per_packet) override; void OnSentPacket(const rtc::SentPacket& sent_packet) override; webrtc::Call::Config config_; webrtc::NetworkState audio_network_state_; webrtc::NetworkState video_network_state_; rtc::SentPacket last_sent_packet_; + int last_sent_nonnegative_packet_id_ = -1; + int next_stream_id_ = 665; webrtc::Call::Stats stats_; std::vector video_send_streams_; std::vector audio_send_streams_; std::vector video_receive_streams_; std::vector audio_receive_streams_; + std::vector flexfec_receive_streams_; int num_created_send_streams_; int num_created_receive_streams_; + + int audio_transport_overhead_; + int video_transport_overhead_; }; } // namespace cricket -#endif // TALK_MEDIA_WEBRTC_WEBRTCVIDEOENGINE2_UNITTEST_H_ +#endif // WEBRTC_MEDIA_ENGINE_FAKEWEBRTCCALL_H_ diff --git a/include/webrtc/media/engine/fakewebrtccommon.h b/include/webrtc/media/engine/fakewebrtccommon.h deleted file mode 100644 index 5c13c1b..0000000 --- a/include/webrtc/media/engine/fakewebrtccommon.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_ENGINE_FAKEWEBRTCCOMMON_H_ -#define WEBRTC_MEDIA_ENGINE_FAKEWEBRTCCOMMON_H_ - -#include "webrtc/base/common.h" - -namespace cricket { - -#define WEBRTC_STUB(method, args) \ - int method args override { return 0; } - -#define WEBRTC_STUB_CONST(method, args) \ - int method args const override { return 0; } - -#define WEBRTC_BOOL_STUB(method, args) \ - bool method args override { return true; } - -#define WEBRTC_BOOL_STUB_CONST(method, args) \ - bool method args const override { return true; } - -#define WEBRTC_VOID_STUB(method, args) \ - void method args override {} - -#define WEBRTC_FUNC(method, args) int method args override - -#define WEBRTC_FUNC_CONST(method, args) int method args const override - -#define WEBRTC_BOOL_FUNC(method, args) bool method args override - -#define WEBRTC_VOID_FUNC(method, args) void method args override -} // namespace cricket - -#endif // WEBRTC_MEDIA_ENGINE_FAKEWEBRTCCOMMON_H_ diff --git a/include/webrtc/media/engine/fakewebrtcvcmfactory.h b/include/webrtc/media/engine/fakewebrtcvcmfactory.h index daa2f77..3124cd8 100644 --- a/include/webrtc/media/engine/fakewebrtcvcmfactory.h +++ b/include/webrtc/media/engine/fakewebrtcvcmfactory.h @@ -22,16 +22,14 @@ class FakeWebRtcVcmFactory : public cricket::WebRtcVcmFactoryInterface { public: virtual rtc::scoped_refptr Create( - int module_id, const char* device_id) { if (!device_info.GetDeviceById(device_id)) return NULL; rtc::scoped_refptr module( - new rtc::RefCountedObject(this, - module_id)); + new rtc::RefCountedObject(this)); modules.push_back(module); return module; } - virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) { + virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo() { return &device_info; } virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) { diff --git a/include/webrtc/media/engine/fakewebrtcvideocapturemodule.h b/include/webrtc/media/engine/fakewebrtcvideocapturemodule.h index 2bc715b..0d52999 100644 --- a/include/webrtc/media/engine/fakewebrtcvideocapturemodule.h +++ b/include/webrtc/media/engine/fakewebrtcvideocapturemodule.h @@ -13,6 +13,7 @@ #include +#include "webrtc/api/video/i420_buffer.h" #include "webrtc/media/base/testutils.h" #include "webrtc/media/engine/webrtcvideocapturer.h" @@ -21,36 +22,17 @@ class FakeWebRtcVcmFactory; // Fake class for mocking out webrtc::VideoCaptureModule. class FakeWebRtcVideoCaptureModule : public webrtc::VideoCaptureModule { public: - FakeWebRtcVideoCaptureModule(FakeWebRtcVcmFactory* factory, int32_t id) + FakeWebRtcVideoCaptureModule(FakeWebRtcVcmFactory* factory) : factory_(factory), - id_(id), callback_(NULL), - running_(false), - delay_(0) { + running_(false) { } ~FakeWebRtcVideoCaptureModule(); - int64_t TimeUntilNextProcess() override { return 0; } - void Process() override {} void RegisterCaptureDataCallback( - webrtc::VideoCaptureDataCallback& callback) override { - callback_ = &callback; + rtc::VideoSinkInterface* callback) override { + callback_ = callback; } void DeRegisterCaptureDataCallback() override { callback_ = NULL; } - void RegisterCaptureCallback( - webrtc::VideoCaptureFeedBack& callback) override { - // Not implemented. - } - void DeRegisterCaptureCallback() override { - // Not implemented. - } - void SetCaptureDelay(int32_t delay) override { delay_ = delay; } - int32_t CaptureDelay() override { return delay_; } - void EnableFrameRateCallback(const bool enable) override { - // not implemented - } - void EnableNoPictureAlarm(const bool enable) override { - // not implemented - } int32_t StartCapture(const webrtc::VideoCaptureCapability& cap) override { if (running_) return -1; cap_ = cap; @@ -75,27 +57,21 @@ class FakeWebRtcVideoCaptureModule : public webrtc::VideoCaptureModule { return -1; // not implemented } bool SetApplyRotation(bool enable) override { - return false; // not implemented + return true; // ignored } bool GetApplyRotation() override { return true; // Rotation compensation is turned on. } - VideoCaptureEncodeInterface* GetEncodeInterface( - const webrtc::VideoCodec& codec) override { - return NULL; // not implemented - } - void SendFrame(int w, int h) { if (!running_) return; rtc::scoped_refptr buffer = - new rtc::RefCountedObject(w, h); + webrtc::I420Buffer::Create(w, h); // Initialize memory to satisfy DrMemory tests. See // https://bugs.chromium.org/p/libyuv/issues/detail?id=377 buffer->InitializeData(); if (callback_) { - callback_->OnIncomingCapturedFrame( - id_, + callback_->OnFrame( webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0)); } } @@ -106,11 +82,9 @@ class FakeWebRtcVideoCaptureModule : public webrtc::VideoCaptureModule { private: FakeWebRtcVcmFactory* factory_; - int id_; - webrtc::VideoCaptureDataCallback* callback_; + rtc::VideoSinkInterface* callback_; bool running_; webrtc::VideoCaptureCapability cap_; - int delay_; }; #endif // WEBRTC_MEDIA_ENGINE_FAKEWEBRTCVIDEOCAPTUREMODULE_H_ diff --git a/include/webrtc/media/engine/fakewebrtcvideoengine.h b/include/webrtc/media/engine/fakewebrtcvideoengine.h index f8b8cbb..2dce2c5 100644 --- a/include/webrtc/media/engine/fakewebrtcvideoengine.h +++ b/include/webrtc/media/engine/fakewebrtcvideoengine.h @@ -28,16 +28,6 @@ #include "webrtc/video_encoder.h" namespace cricket { - -static const int kMinVideoBitrate = 100; -static const int kStartVideoBitrate = 300; -static const int kMaxVideoBitrate = 1000; - -// WebRtc channel id and capture id share the same number space. -// This is how AddRenderer(renderId, ...) is able to tell if it is adding a -// renderer for a channel or it is adding a renderer for a capturer. -static const int kViEChannelIdBase = 0; -static const int kViEChannelIdMax = 1000; static const int kEventTimeoutMs = 10000; // Fake class for mocking out webrtc::VideoDecoder @@ -91,6 +81,13 @@ class FakeWebRtcVideoDecoderFactory : public WebRtcVideoDecoderFactory { return decoder; } + virtual webrtc::VideoDecoder* CreateVideoDecoderWithParams( + webrtc::VideoCodecType type, + VideoDecoderParams params) { + params_.push_back(params); + return CreateVideoDecoder(type); + } + virtual void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) { decoders_.erase( std::remove(decoders_.begin(), decoders_.end(), decoder), @@ -110,10 +107,13 @@ class FakeWebRtcVideoDecoderFactory : public WebRtcVideoDecoderFactory { return decoders_; } + const std::vector& params() { return params_; } + private: std::set supported_codec_types_; std::vector decoders_; int num_created_decoders_; + std::vector params_; }; // Fake class for mocking out webrtc::VideoEnoder @@ -122,9 +122,9 @@ class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder { FakeWebRtcVideoEncoder() : init_encode_event_(false, false), num_frames_encoded_(0) {} - virtual int32_t InitEncode(const webrtc::VideoCodec* codecSettings, - int32_t numberOfCores, - size_t maxPayloadSize) { + int32_t InitEncode(const webrtc::VideoCodec* codecSettings, + int32_t numberOfCores, + size_t maxPayloadSize) override { rtc::CritScope lock(&crit_); codec_settings_ = *codecSettings; init_encode_event_.Set(); @@ -138,27 +138,28 @@ class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder { return codec_settings_; } - virtual int32_t Encode(const webrtc::VideoFrame& inputImage, - const webrtc::CodecSpecificInfo* codecSpecificInfo, - const std::vector* frame_types) { + int32_t Encode(const webrtc::VideoFrame& inputImage, + const webrtc::CodecSpecificInfo* codecSpecificInfo, + const std::vector* frame_types) override { rtc::CritScope lock(&crit_); ++num_frames_encoded_; init_encode_event_.Set(); return WEBRTC_VIDEO_CODEC_OK; } - virtual int32_t RegisterEncodeCompleteCallback( - webrtc::EncodedImageCallback* callback) { + int32_t RegisterEncodeCompleteCallback( + webrtc::EncodedImageCallback* callback) override { return WEBRTC_VIDEO_CODEC_OK; } - virtual int32_t Release() { return WEBRTC_VIDEO_CODEC_OK; } + int32_t Release() override { return WEBRTC_VIDEO_CODEC_OK; } - virtual int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) { + int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override { return WEBRTC_VIDEO_CODEC_OK; } - virtual int32_t SetRates(uint32_t newBitRate, uint32_t frameRate) { + int32_t SetRateAllocation(const webrtc::BitrateAllocation& allocation, + uint32_t framerate) override { return WEBRTC_VIDEO_CODEC_OK; } @@ -183,11 +184,10 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { encoders_have_internal_sources_(false) {} webrtc::VideoEncoder* CreateVideoEncoder( - webrtc::VideoCodecType type) override { + const cricket::VideoCodec& codec) override { rtc::CritScope lock(&crit_); - if (supported_codec_types_.count(type) == 0) { - return NULL; - } + if (!FindMatchingCodec(codecs_, codec)) + return nullptr; FakeWebRtcVideoEncoder* encoder = new FakeWebRtcVideoEncoder(); encoders_.push_back(encoder); num_created_encoders_++; @@ -196,10 +196,13 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { } bool WaitForCreatedVideoEncoders(int num_encoders) { - while (created_video_encoder_event_.Wait(kEventTimeoutMs)) { + int64_t start_offset_ms = rtc::TimeMillis(); + int64_t wait_time = kEventTimeoutMs; + do { if (GetNumCreatedEncoders() >= num_encoders) return true; - } + wait_time = kEventTimeoutMs - (rtc::TimeMillis() - start_offset_ms); + } while (wait_time > 0 && created_video_encoder_event_.Wait(wait_time)); return false; } @@ -211,8 +214,7 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { delete encoder; } - const std::vector& codecs() - const override { + const std::vector& supported_codecs() const override { return codecs_; } @@ -225,11 +227,12 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { encoders_have_internal_sources_ = internal_source; } - void AddSupportedVideoCodecType(webrtc::VideoCodecType type, - const std::string& name) { - supported_codec_types_.insert(type); - codecs_.push_back( - WebRtcVideoEncoderFactory::VideoCodec(type, name, 1280, 720, 30)); + void AddSupportedVideoCodec(const cricket::VideoCodec& codec) { + codecs_.push_back(codec); + } + + void AddSupportedVideoCodecType(const std::string& name) { + codecs_.push_back(cricket::VideoCodec(name)); } int GetNumCreatedEncoders() { @@ -243,10 +246,13 @@ class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory { } private: + // Disable overloaded virtual function warning. TODO(magjed): Remove once + // http://crbug/webrtc/6402 is fixed. + using cricket::WebRtcVideoEncoderFactory::CreateVideoEncoder; + rtc::CriticalSection crit_; rtc::Event created_video_encoder_event_; - std::set supported_codec_types_; - std::vector codecs_; + std::vector codecs_; std::vector encoders_ GUARDED_BY(crit_); int num_created_encoders_ GUARDED_BY(crit_); bool encoders_have_internal_sources_; diff --git a/include/webrtc/media/engine/fakewebrtcvoiceengine.h b/include/webrtc/media/engine/fakewebrtcvoiceengine.h index 13a3696..18c7766 100644 --- a/include/webrtc/media/engine/fakewebrtcvoiceengine.h +++ b/include/webrtc/media/engine/fakewebrtcvoiceengine.h @@ -11,22 +11,28 @@ #ifndef WEBRTC_MEDIA_ENGINE_FAKEWEBRTCVOICEENGINE_H_ #define WEBRTC_MEDIA_ENGINE_FAKEWEBRTCVOICEENGINE_H_ +#include + #include #include #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/checks.h" -#include "webrtc/base/gunit.h" #include "webrtc/base/stringutils.h" +#include "webrtc/base/checks.h" #include "webrtc/config.h" #include "webrtc/media/base/codec.h" #include "webrtc/media/base/rtputils.h" -#include "webrtc/media/engine/fakewebrtccommon.h" #include "webrtc/media/engine/webrtcvoe.h" #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" +namespace webrtc { +namespace voe { +class TransmitMixer; +} // namespace voe +} // namespace webrtc + namespace cricket { static const int kOpusBandwidthNb = 4000; @@ -38,190 +44,45 @@ static const int kOpusBandwidthFb = 20000; #define WEBRTC_CHECK_CHANNEL(channel) \ if (channels_.find(channel) == channels_.end()) return -1; -class FakeAudioProcessing : public webrtc::AudioProcessing { - public: - FakeAudioProcessing() : experimental_ns_enabled_(false) {} - - WEBRTC_STUB(Initialize, ()) - WEBRTC_STUB(Initialize, ( - int input_sample_rate_hz, - int output_sample_rate_hz, - int reverse_sample_rate_hz, - webrtc::AudioProcessing::ChannelLayout input_layout, - webrtc::AudioProcessing::ChannelLayout output_layout, - webrtc::AudioProcessing::ChannelLayout reverse_layout)); - WEBRTC_STUB(Initialize, ( - const webrtc::ProcessingConfig& processing_config)); +#define WEBRTC_STUB(method, args) \ + int method args override { return 0; } - WEBRTC_VOID_FUNC(SetExtraOptions, (const webrtc::Config& config)) { - experimental_ns_enabled_ = config.Get().enabled; - } +#define WEBRTC_STUB_CONST(method, args) \ + int method args const override { return 0; } - WEBRTC_STUB_CONST(proc_sample_rate_hz, ()); - WEBRTC_STUB_CONST(proc_split_sample_rate_hz, ()); - size_t num_input_channels() const override { return 0; } - size_t num_proc_channels() const override { return 0; } - size_t num_output_channels() const override { return 0; } - size_t num_reverse_channels() const override { return 0; } - WEBRTC_VOID_STUB(set_output_will_be_muted, (bool muted)); - WEBRTC_STUB(ProcessStream, (webrtc::AudioFrame* frame)); - WEBRTC_STUB(ProcessStream, ( - const float* const* src, - size_t samples_per_channel, - int input_sample_rate_hz, - webrtc::AudioProcessing::ChannelLayout input_layout, - int output_sample_rate_hz, - webrtc::AudioProcessing::ChannelLayout output_layout, - float* const* dest)); - WEBRTC_STUB(ProcessStream, - (const float* const* src, - const webrtc::StreamConfig& input_config, - const webrtc::StreamConfig& output_config, - float* const* dest)); - WEBRTC_STUB(ProcessReverseStream, (webrtc::AudioFrame * frame)); - WEBRTC_STUB(AnalyzeReverseStream, ( - const float* const* data, - size_t samples_per_channel, - int sample_rate_hz, - webrtc::AudioProcessing::ChannelLayout layout)); - WEBRTC_STUB(ProcessReverseStream, - (const float* const* src, - const webrtc::StreamConfig& reverse_input_config, - const webrtc::StreamConfig& reverse_output_config, - float* const* dest)); - WEBRTC_STUB(set_stream_delay_ms, (int delay)); - WEBRTC_STUB_CONST(stream_delay_ms, ()); - WEBRTC_BOOL_STUB_CONST(was_stream_delay_set, ()); - WEBRTC_VOID_STUB(set_stream_key_pressed, (bool key_pressed)); - WEBRTC_VOID_STUB(set_delay_offset_ms, (int offset)); - WEBRTC_STUB_CONST(delay_offset_ms, ()); - WEBRTC_STUB(StartDebugRecording, - (const char filename[kMaxFilenameSize], int64_t max_size_bytes)); - WEBRTC_STUB(StartDebugRecording, (FILE * handle, int64_t max_size_bytes)); - WEBRTC_STUB(StopDebugRecording, ()); - WEBRTC_VOID_STUB(UpdateHistogramsOnCallEnd, ()); - webrtc::EchoCancellation* echo_cancellation() const override { return NULL; } - webrtc::EchoControlMobile* echo_control_mobile() const override { - return NULL; - } - webrtc::GainControl* gain_control() const override { return NULL; } - webrtc::HighPassFilter* high_pass_filter() const override { return NULL; } - webrtc::LevelEstimator* level_estimator() const override { return NULL; } - webrtc::NoiseSuppression* noise_suppression() const override { return NULL; } - webrtc::VoiceDetection* voice_detection() const override { return NULL; } +#define WEBRTC_BOOL_STUB(method, args) \ + bool method args override { return true; } - bool experimental_ns_enabled() { - return experimental_ns_enabled_; - } +#define WEBRTC_VOID_STUB(method, args) \ + void method args override {} - private: - bool experimental_ns_enabled_; -}; +#define WEBRTC_FUNC(method, args) int method args override class FakeWebRtcVoiceEngine - : public webrtc::VoEAudioProcessing, - public webrtc::VoEBase, public webrtc::VoECodec, - public webrtc::VoEHardware, public webrtc::VoERTP_RTCP, + : public webrtc::VoEBase, public webrtc::VoECodec, + public webrtc::VoEHardware, public webrtc::VoEVolumeControl { public: struct Channel { - Channel() { - memset(&send_codec, 0, sizeof(send_codec)); - } - bool playout = false; - float volume_scale = 1.0f; - bool vad = false; - bool codec_fec = false; - int max_encoding_bandwidth = 0; - bool opus_dtx = false; - bool red = false; - bool nack = false; - int cn8_type = 13; - int cn16_type = 105; - int red_type = 117; - int nack_max_packets = 0; - uint32_t send_ssrc = 0; - int associate_send_channel = -1; std::vector recv_codecs; - webrtc::CodecInst send_codec; - int neteq_capacity = -1; + size_t neteq_capacity = 0; bool neteq_fast_accelerate = false; }; - FakeWebRtcVoiceEngine() { - memset(&agc_config_, 0, sizeof(agc_config_)); + explicit FakeWebRtcVoiceEngine(webrtc::AudioProcessing* apm, + webrtc::voe::TransmitMixer* transmit_mixer) + : apm_(apm), transmit_mixer_(transmit_mixer) { } ~FakeWebRtcVoiceEngine() override { RTC_CHECK(channels_.empty()); } - bool ec_metrics_enabled() const { return ec_metrics_enabled_; } - bool IsInited() const { return inited_; } int GetLastChannel() const { return last_channel_; } int GetNumChannels() const { return static_cast(channels_.size()); } - uint32_t GetLocalSSRC(int channel) { - return channels_[channel]->send_ssrc; - } - bool GetPlayout(int channel) { - return channels_[channel]->playout; - } - bool GetVAD(int channel) { - return channels_[channel]->vad; - } - bool GetOpusDtx(int channel) { - return channels_[channel]->opus_dtx; - } - bool GetRED(int channel) { - return channels_[channel]->red; - } - bool GetCodecFEC(int channel) { - return channels_[channel]->codec_fec; - } - int GetMaxEncodingBandwidth(int channel) { - return channels_[channel]->max_encoding_bandwidth; - } - bool GetNACK(int channel) { - return channels_[channel]->nack; - } - int GetNACKMaxPackets(int channel) { - return channels_[channel]->nack_max_packets; - } - int GetSendCNPayloadType(int channel, bool wideband) { - return (wideband) ? - channels_[channel]->cn16_type : - channels_[channel]->cn8_type; - } - int GetSendREDPayloadType(int channel) { - return channels_[channel]->red_type; - } - void set_playout_fail_channel(int channel) { - playout_fail_channel_ = channel; - } void set_fail_create_channel(bool fail_create_channel) { fail_create_channel_ = fail_create_channel; } - int AddChannel(const webrtc::Config& config) { - if (fail_create_channel_) { - return -1; - } - Channel* ch = new Channel(); - auto db = webrtc::acm2::RentACodec::Database(); - ch->recv_codecs.assign(db.begin(), db.end()); - if (config.Get().enabled) { - ch->neteq_capacity = config.Get().capacity; - } - ch->neteq_fast_accelerate = - config.Get().enabled; - channels_[++last_channel_] = ch; - return last_channel_; - } - - int GetNumSetSendCodecs() const { return num_set_send_codecs_; } - - int GetAssociateSendChannel(int channel) { - return channels_[channel]->associate_send_channel; - } WEBRTC_STUB(Release, ()); @@ -229,8 +90,11 @@ class FakeWebRtcVoiceEngine WEBRTC_STUB(RegisterVoiceEngineObserver, ( webrtc::VoiceEngineObserver& observer)); WEBRTC_STUB(DeRegisterVoiceEngineObserver, ()); - WEBRTC_FUNC(Init, (webrtc::AudioDeviceModule* adm, - webrtc::AudioProcessing* audioproc)) { + WEBRTC_FUNC(Init, + (webrtc::AudioDeviceModule* adm, + webrtc::AudioProcessing* audioproc, + const rtc::scoped_refptr& + decoder_factory)) { inited_ = true; return 0; } @@ -239,88 +103,58 @@ class FakeWebRtcVoiceEngine return 0; } webrtc::AudioProcessing* audio_processing() override { - return &audio_processing_; + return apm_; } webrtc::AudioDeviceModule* audio_device_module() override { return nullptr; } + webrtc::voe::TransmitMixer* transmit_mixer() override { + return transmit_mixer_; + } WEBRTC_FUNC(CreateChannel, ()) { - webrtc::Config empty_config; - return AddChannel(empty_config); + return CreateChannel(webrtc::VoEBase::ChannelConfig()); } - WEBRTC_FUNC(CreateChannel, (const webrtc::Config& config)) { - return AddChannel(config); + WEBRTC_FUNC(CreateChannel, (const webrtc::VoEBase::ChannelConfig& config)) { + if (fail_create_channel_) { + return -1; + } + Channel* ch = new Channel(); + auto db = webrtc::acm2::RentACodec::Database(); + ch->recv_codecs.assign(db.begin(), db.end()); + ch->neteq_capacity = config.acm_config.neteq_config.max_packets_in_buffer; + ch->neteq_fast_accelerate = + config.acm_config.neteq_config.enable_fast_accelerate; + channels_[++last_channel_] = ch; + return last_channel_; } WEBRTC_FUNC(DeleteChannel, (int channel)) { WEBRTC_CHECK_CHANNEL(channel); - for (const auto& ch : channels_) { - if (ch.second->associate_send_channel == channel) { - ch.second->associate_send_channel = -1; - } - } delete channels_[channel]; channels_.erase(channel); return 0; } WEBRTC_STUB(StartReceive, (int channel)); - WEBRTC_FUNC(StartPlayout, (int channel)) { - if (playout_fail_channel_ != channel) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->playout = true; - return 0; - } else { - // When playout_fail_channel_ == channel, fail the StartPlayout on this - // channel. - return -1; - } - } + WEBRTC_STUB(StartPlayout, (int channel)); WEBRTC_STUB(StartSend, (int channel)); WEBRTC_STUB(StopReceive, (int channel)); - WEBRTC_FUNC(StopPlayout, (int channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->playout = false; - return 0; - } + WEBRTC_STUB(StopPlayout, (int channel)); WEBRTC_STUB(StopSend, (int channel)); WEBRTC_STUB(GetVersion, (char version[1024])); WEBRTC_STUB(LastError, ()); - WEBRTC_FUNC(AssociateSendChannel, (int channel, - int accociate_send_channel)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->associate_send_channel = accociate_send_channel; - return 0; - } - webrtc::RtcEventLog* GetEventLog() override { return nullptr; } + WEBRTC_STUB(AssociateSendChannel, (int channel, + int accociate_send_channel)); // webrtc::VoECodec WEBRTC_STUB(NumOfCodecs, ()); WEBRTC_STUB(GetCodec, (int index, webrtc::CodecInst& codec)); - WEBRTC_FUNC(SetSendCodec, (int channel, const webrtc::CodecInst& codec)) { - WEBRTC_CHECK_CHANNEL(channel); - // To match the behavior of the real implementation. - if (_stricmp(codec.plname, "telephone-event") == 0 || - _stricmp(codec.plname, "audio/telephone-event") == 0 || - _stricmp(codec.plname, "CN") == 0 || - _stricmp(codec.plname, "red") == 0 ) { - return -1; - } - channels_[channel]->send_codec = codec; - ++num_set_send_codecs_; - return 0; - } - WEBRTC_FUNC(GetSendCodec, (int channel, webrtc::CodecInst& codec)) { - WEBRTC_CHECK_CHANNEL(channel); - codec = channels_[channel]->send_codec; - return 0; - } + WEBRTC_STUB(SetSendCodec, (int channel, const webrtc::CodecInst& codec)); + WEBRTC_STUB(GetSendCodec, (int channel, webrtc::CodecInst& codec)); WEBRTC_STUB(SetBitRate, (int channel, int bitrate_bps)); WEBRTC_STUB(GetRecCodec, (int channel, webrtc::CodecInst& codec)); WEBRTC_FUNC(SetRecPayloadType, (int channel, const webrtc::CodecInst& codec)) { WEBRTC_CHECK_CHANNEL(channel); Channel* ch = channels_[channel]; - if (ch->playout) - return -1; // Channel is in use. // Check if something else already has this slot. if (codec.pltype != -1) { for (std::vector::iterator it = @@ -344,16 +178,8 @@ class FakeWebRtcVoiceEngine } return result; } - WEBRTC_FUNC(SetSendCNPayloadType, (int channel, int type, - webrtc::PayloadFrequencies frequency)) { - WEBRTC_CHECK_CHANNEL(channel); - if (frequency == webrtc::kFreq8000Hz) { - channels_[channel]->cn8_type = type; - } else if (frequency == webrtc::kFreq16000Hz) { - channels_[channel]->cn16_type = type; - } - return 0; - } + WEBRTC_STUB(SetSendCNPayloadType, (int channel, int type, + webrtc::PayloadFrequencies frequency)); WEBRTC_FUNC(GetRecPayloadType, (int channel, webrtc::CodecInst& codec)) { WEBRTC_CHECK_CHANNEL(channel); Channel* ch = channels_[channel]; @@ -369,63 +195,14 @@ class FakeWebRtcVoiceEngine } return -1; // not found } - WEBRTC_FUNC(SetVADStatus, (int channel, bool enable, webrtc::VadModes mode, - bool disableDTX)) { - WEBRTC_CHECK_CHANNEL(channel); - if (channels_[channel]->send_codec.channels == 2) { - // Replicating VoE behavior; VAD cannot be enabled for stereo. - return -1; - } - channels_[channel]->vad = enable; - return 0; - } + WEBRTC_STUB(SetVADStatus, (int channel, bool enable, webrtc::VadModes mode, + bool disableDTX)); WEBRTC_STUB(GetVADStatus, (int channel, bool& enabled, webrtc::VadModes& mode, bool& disabledDTX)); - - WEBRTC_FUNC(SetFECStatus, (int channel, bool enable)) { - WEBRTC_CHECK_CHANNEL(channel); - if (_stricmp(channels_[channel]->send_codec.plname, "opus") != 0) { - // Return -1 if current send codec is not Opus. - // TODO(minyue): Excludes other codecs if they support inband FEC. - return -1; - } - channels_[channel]->codec_fec = enable; - return 0; - } - WEBRTC_FUNC(GetFECStatus, (int channel, bool& enable)) { - WEBRTC_CHECK_CHANNEL(channel); - enable = channels_[channel]->codec_fec; - return 0; - } - - WEBRTC_FUNC(SetOpusMaxPlaybackRate, (int channel, int frequency_hz)) { - WEBRTC_CHECK_CHANNEL(channel); - if (_stricmp(channels_[channel]->send_codec.plname, "opus") != 0) { - // Return -1 if current send codec is not Opus. - return -1; - } - if (frequency_hz <= 8000) - channels_[channel]->max_encoding_bandwidth = kOpusBandwidthNb; - else if (frequency_hz <= 12000) - channels_[channel]->max_encoding_bandwidth = kOpusBandwidthMb; - else if (frequency_hz <= 16000) - channels_[channel]->max_encoding_bandwidth = kOpusBandwidthWb; - else if (frequency_hz <= 24000) - channels_[channel]->max_encoding_bandwidth = kOpusBandwidthSwb; - else - channels_[channel]->max_encoding_bandwidth = kOpusBandwidthFb; - return 0; - } - - WEBRTC_FUNC(SetOpusDtx, (int channel, bool enable_dtx)) { - WEBRTC_CHECK_CHANNEL(channel); - if (_stricmp(channels_[channel]->send_codec.plname, "opus") != 0) { - // Return -1 if current send codec is not Opus. - return -1; - } - channels_[channel]->opus_dtx = enable_dtx; - return 0; - } + WEBRTC_STUB(SetFECStatus, (int channel, bool enable)); + WEBRTC_STUB(GetFECStatus, (int channel, bool& enable)); + WEBRTC_STUB(SetOpusMaxPlaybackRate, (int channel, int frequency_hz)); + WEBRTC_STUB(SetOpusDtx, (int channel, bool enable_dtx)); // webrtc::VoEHardware WEBRTC_STUB(GetNumOfRecordingDevices, (int& num)); @@ -447,58 +224,6 @@ class FakeWebRtcVoiceEngine WEBRTC_STUB(EnableBuiltInNS, (bool enable)); bool BuiltInNSIsAvailable() const override { return false; } - // webrtc::VoERTP_RTCP - WEBRTC_FUNC(SetLocalSSRC, (int channel, unsigned int ssrc)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->send_ssrc = ssrc; - return 0; - } - WEBRTC_STUB(GetLocalSSRC, (int channel, unsigned int& ssrc)); - WEBRTC_STUB(GetRemoteSSRC, (int channel, unsigned int& ssrc)); - WEBRTC_STUB(SetSendAudioLevelIndicationStatus, (int channel, bool enable, - unsigned char id)); - WEBRTC_STUB(SetReceiveAudioLevelIndicationStatus, (int channel, bool enable, - unsigned char id)); - WEBRTC_STUB(SetSendAbsoluteSenderTimeStatus, (int channel, bool enable, - unsigned char id)); - WEBRTC_STUB(SetReceiveAbsoluteSenderTimeStatus, (int channel, bool enable, - unsigned char id)); - WEBRTC_STUB(SetRTCPStatus, (int channel, bool enable)); - WEBRTC_STUB(GetRTCPStatus, (int channel, bool& enabled)); - WEBRTC_STUB(SetRTCP_CNAME, (int channel, const char cname[256])); - WEBRTC_STUB(GetRTCP_CNAME, (int channel, char cname[256])); - WEBRTC_STUB(GetRemoteRTCP_CNAME, (int channel, char* cname)); - WEBRTC_STUB(GetRemoteRTCPData, (int channel, unsigned int& NTPHigh, - unsigned int& NTPLow, - unsigned int& timestamp, - unsigned int& playoutTimestamp, - unsigned int* jitter, - unsigned short* fractionLost)); - WEBRTC_STUB(GetRemoteRTCPReportBlocks, - (int channel, std::vector* receive_blocks)); - WEBRTC_STUB(GetRTPStatistics, (int channel, unsigned int& averageJitterMs, - unsigned int& maxJitterMs, - unsigned int& discardedPackets)); - WEBRTC_STUB(GetRTCPStatistics, (int channel, webrtc::CallStatistics& stats)); - WEBRTC_FUNC(SetREDStatus, (int channel, bool enable, int redPayloadtype)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->red = enable; - channels_[channel]->red_type = redPayloadtype; - return 0; - } - WEBRTC_FUNC(GetREDStatus, (int channel, bool& enable, int& redPayloadtype)) { - WEBRTC_CHECK_CHANNEL(channel); - enable = channels_[channel]->red; - redPayloadtype = channels_[channel]->red_type; - return 0; - } - WEBRTC_FUNC(SetNACKStatus, (int channel, bool enable, int maxNoPackets)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->nack = enable; - channels_[channel]->nack_max_packets = maxNoPackets; - return 0; - } - // webrtc::VoEVolumeControl WEBRTC_STUB(SetSpeakerVolume, (unsigned int)); WEBRTC_STUB(GetSpeakerVolume, (unsigned int&)); @@ -510,136 +235,19 @@ class FakeWebRtcVoiceEngine WEBRTC_STUB(GetSpeechOutputLevel, (int, unsigned int&)); WEBRTC_STUB(GetSpeechInputLevelFullRange, (unsigned int&)); WEBRTC_STUB(GetSpeechOutputLevelFullRange, (int, unsigned int&)); - WEBRTC_FUNC(SetChannelOutputVolumeScaling, (int channel, float scale)) { - WEBRTC_CHECK_CHANNEL(channel); - channels_[channel]->volume_scale= scale; - return 0; - } - WEBRTC_FUNC(GetChannelOutputVolumeScaling, (int channel, float& scale)) { - WEBRTC_CHECK_CHANNEL(channel); - scale = channels_[channel]->volume_scale; - return 0; - } + WEBRTC_STUB(SetChannelOutputVolumeScaling, (int channel, float scale)); + WEBRTC_STUB(GetChannelOutputVolumeScaling, (int channel, float& scale)); WEBRTC_STUB(SetOutputVolumePan, (int channel, float left, float right)); WEBRTC_STUB(GetOutputVolumePan, (int channel, float& left, float& right)); - // webrtc::VoEAudioProcessing - WEBRTC_FUNC(SetNsStatus, (bool enable, webrtc::NsModes mode)) { - ns_enabled_ = enable; - ns_mode_ = mode; - return 0; - } - WEBRTC_FUNC(GetNsStatus, (bool& enabled, webrtc::NsModes& mode)) { - enabled = ns_enabled_; - mode = ns_mode_; - return 0; - } - - WEBRTC_FUNC(SetAgcStatus, (bool enable, webrtc::AgcModes mode)) { - agc_enabled_ = enable; - agc_mode_ = mode; - return 0; - } - WEBRTC_FUNC(GetAgcStatus, (bool& enabled, webrtc::AgcModes& mode)) { - enabled = agc_enabled_; - mode = agc_mode_; - return 0; - } - - WEBRTC_FUNC(SetAgcConfig, (webrtc::AgcConfig config)) { - agc_config_ = config; - return 0; - } - WEBRTC_FUNC(GetAgcConfig, (webrtc::AgcConfig& config)) { - config = agc_config_; - return 0; - } - WEBRTC_FUNC(SetEcStatus, (bool enable, webrtc::EcModes mode)) { - ec_enabled_ = enable; - ec_mode_ = mode; - return 0; - } - WEBRTC_FUNC(GetEcStatus, (bool& enabled, webrtc::EcModes& mode)) { - enabled = ec_enabled_; - mode = ec_mode_; - return 0; - } - WEBRTC_STUB(EnableDriftCompensation, (bool enable)) - WEBRTC_BOOL_STUB(DriftCompensationEnabled, ()) - WEBRTC_VOID_STUB(SetDelayOffsetMs, (int offset)) - WEBRTC_STUB(DelayOffsetMs, ()); - WEBRTC_FUNC(SetAecmMode, (webrtc::AecmModes mode, bool enableCNG)) { - aecm_mode_ = mode; - cng_enabled_ = enableCNG; - return 0; - } - WEBRTC_FUNC(GetAecmMode, (webrtc::AecmModes& mode, bool& enabledCNG)) { - mode = aecm_mode_; - enabledCNG = cng_enabled_; - return 0; - } - WEBRTC_STUB(SetRxNsStatus, (int channel, bool enable, webrtc::NsModes mode)); - WEBRTC_STUB(GetRxNsStatus, (int channel, bool& enabled, - webrtc::NsModes& mode)); - WEBRTC_STUB(SetRxAgcStatus, (int channel, bool enable, - webrtc::AgcModes mode)); - WEBRTC_STUB(GetRxAgcStatus, (int channel, bool& enabled, - webrtc::AgcModes& mode)); - WEBRTC_STUB(SetRxAgcConfig, (int channel, webrtc::AgcConfig config)); - WEBRTC_STUB(GetRxAgcConfig, (int channel, webrtc::AgcConfig& config)); - - WEBRTC_STUB(RegisterRxVadObserver, (int, webrtc::VoERxVadCallback&)); - WEBRTC_STUB(DeRegisterRxVadObserver, (int channel)); - WEBRTC_STUB(VoiceActivityIndicator, (int channel)); - WEBRTC_FUNC(SetEcMetricsStatus, (bool enable)) { - ec_metrics_enabled_ = enable; - return 0; - } - WEBRTC_STUB(GetEcMetricsStatus, (bool& enabled)); - WEBRTC_STUB(GetEchoMetrics, (int& ERL, int& ERLE, int& RERL, int& A_NLP)); - WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std, - float& fraction_poor_delays)); - - WEBRTC_STUB(StartDebugRecording, (const char* fileNameUTF8)); - WEBRTC_STUB(StartDebugRecording, (FILE* handle)); - WEBRTC_STUB(StopDebugRecording, ()); - - WEBRTC_FUNC(SetTypingDetectionStatus, (bool enable)) { - typing_detection_enabled_ = enable; - return 0; - } - WEBRTC_FUNC(GetTypingDetectionStatus, (bool& enabled)) { - enabled = typing_detection_enabled_; - return 0; - } - - WEBRTC_STUB(TimeSinceLastTyping, (int& seconds)); - WEBRTC_STUB(SetTypingDetectionParameters, (int timeWindow, - int costPerTyping, - int reportingThreshold, - int penaltyDecay, - int typeEventDelay)); - int EnableHighPassFilter(bool enable) override { - highpass_filter_enabled_ = enable; - return 0; - } - bool IsHighPassFilterEnabled() override { - return highpass_filter_enabled_; - } - bool IsStereoChannelSwappingEnabled() override { - return stereo_swapping_enabled_; - } - void EnableStereoChannelSwapping(bool enable) override { - stereo_swapping_enabled_ = enable; - } - int GetNetEqCapacity() const { + size_t GetNetEqCapacity() const { auto ch = channels_.find(last_channel_); - ASSERT(ch != channels_.end()); + RTC_DCHECK(ch != channels_.end()); return ch->second->neteq_capacity; } bool GetNetEqFastAccelerate() const { auto ch = channels_.find(last_channel_); - ASSERT(ch != channels_.end()); + RTC_CHECK(ch != channels_.end()); return ch->second->neteq_fast_accelerate; } @@ -648,22 +256,10 @@ class FakeWebRtcVoiceEngine int last_channel_ = -1; std::map channels_; bool fail_create_channel_ = false; - int num_set_send_codecs_ = 0; // how many times we call SetSendCodec(). - bool ec_enabled_ = false; - bool ec_metrics_enabled_ = false; - bool cng_enabled_ = false; - bool ns_enabled_ = false; - bool agc_enabled_ = false; - bool highpass_filter_enabled_ = false; - bool stereo_swapping_enabled_ = false; - bool typing_detection_enabled_ = false; - webrtc::EcModes ec_mode_ = webrtc::kEcDefault; - webrtc::AecmModes aecm_mode_ = webrtc::kAecmSpeakerphone; - webrtc::NsModes ns_mode_ = webrtc::kNsDefault; - webrtc::AgcModes agc_mode_ = webrtc::kAgcDefault; - webrtc::AgcConfig agc_config_; - int playout_fail_channel_ = -1; - FakeAudioProcessing audio_processing_; + webrtc::AudioProcessing* apm_ = nullptr; + webrtc::voe::TransmitMixer* transmit_mixer_ = nullptr; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FakeWebRtcVoiceEngine); }; } // namespace cricket diff --git a/include/webrtc/media/engine/internaldecoderfactory.h b/include/webrtc/media/engine/internaldecoderfactory.h new file mode 100644 index 0000000..20ceecc --- /dev/null +++ b/include/webrtc/media/engine/internaldecoderfactory.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_INTERNALDECODERFACTORY_H_ +#define WEBRTC_MEDIA_ENGINE_INTERNALDECODERFACTORY_H_ + +#include + +#include "webrtc/media/engine/webrtcvideodecoderfactory.h" + +namespace cricket { + +class InternalDecoderFactory : public WebRtcVideoDecoderFactory { + public: + InternalDecoderFactory(); + virtual ~InternalDecoderFactory(); + + // WebRtcVideoDecoderFactory implementation. + webrtc::VideoDecoder* CreateVideoDecoder( + webrtc::VideoCodecType type) override; + + void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override; +}; + +} // namespace cricket + +#endif // WEBRTC_MEDIA_ENGINE_INTERNALDECODERFACTORY_H_ diff --git a/include/webrtc/media/engine/internalencoderfactory.h b/include/webrtc/media/engine/internalencoderfactory.h new file mode 100644 index 0000000..909fa0f --- /dev/null +++ b/include/webrtc/media/engine/internalencoderfactory.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_INTERNALENCODERFACTORY_H_ +#define WEBRTC_MEDIA_ENGINE_INTERNALENCODERFACTORY_H_ + +#include + +#include "webrtc/media/engine/webrtcvideoencoderfactory.h" + +namespace cricket { + +class InternalEncoderFactory : public WebRtcVideoEncoderFactory { + public: + InternalEncoderFactory(); + virtual ~InternalEncoderFactory(); + + // WebRtcVideoEncoderFactory implementation. + webrtc::VideoEncoder* CreateVideoEncoder( + const cricket::VideoCodec& codec) override; + const std::vector& supported_codecs() const override; + void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; + + private: + // Disable overloaded virtual function warning. TODO(magjed): Remove once + // http://crbug/webrtc/6402 is fixed. + using WebRtcVideoEncoderFactory::CreateVideoEncoder; + + std::vector supported_codecs_; +}; + +} // namespace cricket + +#endif // WEBRTC_MEDIA_ENGINE_INTERNALENCODERFACTORY_H_ diff --git a/include/webrtc/media/engine/payload_type_mapper.h b/include/webrtc/media/engine/payload_type_mapper.h new file mode 100644 index 0000000..e634c9a --- /dev/null +++ b/include/webrtc/media/engine/payload_type_mapper.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_ +#define WEBRTC_MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_ + +#include +#include + +#include "webrtc/api/audio_codecs/audio_format.h" +#include "webrtc/base/optional.h" +#include "webrtc/media/base/codec.h" + +namespace cricket { + +webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const AudioCodec& ac); + +class PayloadTypeMapper { + public: + PayloadTypeMapper(); + ~PayloadTypeMapper(); + + // Finds the current payload type for |format| or assigns a new one, if no + // current mapping exists. Will return an empty value if it was unable to + // create a mapping, i.e. if all dynamic payload type ids have been used up. + rtc::Optional GetMappingFor(const webrtc::SdpAudioFormat& format); + + // Finds the current payload type for |format|, if any. Returns an empty value + // if no payload type mapping exists for the format. + rtc::Optional FindMappingFor(const webrtc::SdpAudioFormat& format) const; + + // Like GetMappingFor, but fills in an AudioCodec structure with the necessary + // information instead. + rtc::Optional ToAudioCodec(const webrtc::SdpAudioFormat& format); + + private: + struct SdpAudioFormatOrdering { + bool operator()(const webrtc::SdpAudioFormat& a, + const webrtc::SdpAudioFormat& b) const; + }; + + int next_unused_payload_type_; + int max_payload_type_; + std::map mappings_; + std::set used_payload_types_; +}; + +} // namespace cricket +#endif // WEBRTC_MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_ diff --git a/include/webrtc/media/engine/simulcast.h b/include/webrtc/media/engine/simulcast.h index 20be4c4..3aae70f 100644 --- a/include/webrtc/media/engine/simulcast.h +++ b/include/webrtc/media/engine/simulcast.h @@ -19,6 +19,7 @@ namespace cricket { struct StreamParams; +// TODO(sprang): Remove this, as we're moving away from temporal layer mode. // Config for use with screen cast when temporal layers are enabled. struct ScreenshareLayerConfig { public: @@ -45,12 +46,16 @@ int GetTotalMaxBitrateBps(const std::vector& streams); void GetSimulcastSsrcs(const StreamParams& sp, std::vector* ssrcs); // Get simulcast settings. +// TODO(sprang): Remove default parameter when it's not longer referenced. std::vector GetSimulcastConfig(size_t max_streams, int width, int height, int max_bitrate_bps, int max_qp, - int max_framerate); + int max_framerate, + bool is_screencast = false); + +bool UseSimulcastScreenshare(); } // namespace cricket diff --git a/include/webrtc/media/engine/videodecodersoftwarefallbackwrapper.h b/include/webrtc/media/engine/videodecodersoftwarefallbackwrapper.h new file mode 100644 index 0000000..80d91f4 --- /dev/null +++ b/include/webrtc/media/engine/videodecodersoftwarefallbackwrapper.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_VIDEODECODERSOFTWAREFALLBACKWRAPPER_H_ +#define WEBRTC_MEDIA_ENGINE_VIDEODECODERSOFTWAREFALLBACKWRAPPER_H_ + +#include +#include + +#include "webrtc/video_decoder.h" + +namespace webrtc { + +// Class used to wrap external VideoDecoders to provide a fallback option on +// software decoding when a hardware decoder fails to decode a stream due to +// hardware restrictions, such as max resolution. +class VideoDecoderSoftwareFallbackWrapper : public webrtc::VideoDecoder { + public: + VideoDecoderSoftwareFallbackWrapper(VideoCodecType codec_type, + VideoDecoder* decoder); + + int32_t InitDecode(const VideoCodec* codec_settings, + int32_t number_of_cores) override; + + int32_t Decode(const EncodedImage& input_image, + bool missing_frames, + const RTPFragmentationHeader* fragmentation, + const CodecSpecificInfo* codec_specific_info, + int64_t render_time_ms) override; + + int32_t RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) override; + + int32_t Release() override; + bool PrefersLateDecoding() const override; + + const char* ImplementationName() const override; + + private: + bool InitFallbackDecoder(); + + const VideoCodecType codec_type_; + VideoDecoder* const decoder_; + bool decoder_initialized_; + + VideoCodec codec_settings_; + int32_t number_of_cores_; + std::string fallback_implementation_name_; + std::unique_ptr fallback_decoder_; + DecodedImageCallback* callback_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MEDIA_ENGINE_VIDEODECODERSOFTWAREFALLBACKWRAPPER_H_ diff --git a/include/webrtc/media/engine/videoencodersoftwarefallbackwrapper.h b/include/webrtc/media/engine/videoencodersoftwarefallbackwrapper.h new file mode 100644 index 0000000..055dd29 --- /dev/null +++ b/include/webrtc/media/engine/videoencodersoftwarefallbackwrapper.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_ENGINE_VIDEOENCODERSOFTWAREFALLBACKWRAPPER_H_ +#define WEBRTC_MEDIA_ENGINE_VIDEOENCODERSOFTWAREFALLBACKWRAPPER_H_ + +#include +#include +#include + +#include "webrtc/media/base/codec.h" +#include "webrtc/video_encoder.h" + +namespace webrtc { + +// Class used to wrap external VideoEncoders to provide a fallback option on +// software encoding when a hardware encoder fails to encode a stream due to +// hardware restrictions, such as max resolution. +class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder { + public: + VideoEncoderSoftwareFallbackWrapper(const cricket::VideoCodec& codec, + webrtc::VideoEncoder* encoder); + + int32_t InitEncode(const VideoCodec* codec_settings, + int32_t number_of_cores, + size_t max_payload_size) override; + + int32_t RegisterEncodeCompleteCallback( + EncodedImageCallback* callback) override; + + int32_t Release() override; + int32_t Encode(const VideoFrame& frame, + const CodecSpecificInfo* codec_specific_info, + const std::vector* frame_types) override; + int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; + int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation, + uint32_t framerate) override; + bool SupportsNativeHandle() const override; + ScalingSettings GetScalingSettings() const override; + const char *ImplementationName() const override; + + private: + bool InitFallbackEncoder(); + + // Settings used in the last InitEncode call and used if a dynamic fallback to + // software is required. + VideoCodec codec_settings_; + int32_t number_of_cores_; + size_t max_payload_size_; + + // The last bitrate/framerate set, and a flag for noting they are set. + bool rates_set_; + BitrateAllocation bitrate_allocation_; + uint32_t framerate_; + + // The last channel parameters set, and a flag for noting they are set. + bool channel_parameters_set_; + uint32_t packet_loss_; + int64_t rtt_; + + const cricket::VideoCodec codec_; + webrtc::VideoEncoder* const encoder_; + + std::unique_ptr fallback_encoder_; + std::string fallback_implementation_name_; + EncodedImageCallback* callback_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MEDIA_ENGINE_VIDEOENCODERSOFTWAREFALLBACKWRAPPER_H_ diff --git a/include/webrtc/media/engine/webrtcmediaengine.h b/include/webrtc/media/engine/webrtcmediaengine.h index 19b7d22..b539b58 100644 --- a/include/webrtc/media/engine/webrtcmediaengine.h +++ b/include/webrtc/media/engine/webrtcmediaengine.h @@ -14,11 +14,14 @@ #include #include +#include "webrtc/call/call.h" #include "webrtc/config.h" #include "webrtc/media/base/mediaengine.h" namespace webrtc { +class AudioDecoderFactory; class AudioDeviceModule; +class AudioMixer; } namespace cricket { class WebRtcVideoDecoderFactory; @@ -29,25 +32,47 @@ namespace cricket { class WebRtcMediaEngineFactory { public: + // TODO(ossu): Backwards-compatible interface. Will be deprecated once the + // audio decoder factory is fully plumbed and used throughout WebRTC. + // See: crbug.com/webrtc/6000 static MediaEngineInterface* Create( webrtc::AudioDeviceModule* adm, - WebRtcVideoEncoderFactory* encoder_factory, - WebRtcVideoDecoderFactory* decoder_factory); + WebRtcVideoEncoderFactory* video_encoder_factory, + WebRtcVideoDecoderFactory* video_decoder_factory); + + // TODO(deadbeef): Change these to return an std::unique_ptr<>, to indicate + // that the caller owns the returned object. + static MediaEngineInterface* Create( + webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + WebRtcVideoEncoderFactory* video_encoder_factory, + WebRtcVideoDecoderFactory* video_decoder_factory); + + static MediaEngineInterface* Create( + webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& + audio_decoder_factory, + WebRtcVideoEncoderFactory* video_encoder_factory, + WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer); }; // Verify that extension IDs are within 1-byte extension range and are not // overlapping. -bool ValidateRtpExtensions(const std::vector& extensions); +bool ValidateRtpExtensions(const std::vector& extensions); -// Convert cricket::RtpHeaderExtension:s to webrtc::RtpExtension:s, discarding -// any extensions not validated by the 'supported' predicate. Duplicate +// Discard any extensions not validated by the 'supported' predicate. Duplicate // extensions are removed if 'filter_redundant_extensions' is set, and also any -// mutually exclusive extensions (see implementation for details). +// mutually exclusive extensions (see implementation for details) are removed. std::vector FilterRtpExtensions( - const std::vector& extensions, + const std::vector& extensions, bool (*supported)(const std::string&), bool filter_redundant_extensions); +webrtc::Call::Config::BitrateConfig GetBitrateConfigForCodec( + const Codec& codec); + } // namespace cricket #endif // WEBRTC_MEDIA_ENGINE_WEBRTCMEDIAENGINE_H_ diff --git a/include/webrtc/media/engine/webrtcvideocapturer.h b/include/webrtc/media/engine/webrtcvideocapturer.h index 1efa4ad..1687ce8 100644 --- a/include/webrtc/media/engine/webrtcvideocapturer.h +++ b/include/webrtc/media/engine/webrtcvideocapturer.h @@ -21,7 +21,6 @@ #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/media/base/device.h" #include "webrtc/media/base/videocapturer.h" -#include "webrtc/media/engine/webrtcvideoframe.h" #include "webrtc/modules/video_capture/video_capture.h" namespace cricket { @@ -32,16 +31,15 @@ class WebRtcVcmFactoryInterface { public: virtual ~WebRtcVcmFactoryInterface() {} virtual rtc::scoped_refptr Create( - int id, const char* device) = 0; - virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) = 0; + virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo() = 0; virtual void DestroyDeviceInfo( webrtc::VideoCaptureModule::DeviceInfo* info) = 0; }; // WebRTC-based implementation of VideoCapturer. class WebRtcVideoCapturer : public VideoCapturer, - public webrtc::VideoCaptureDataCallback { + public rtc::VideoSinkInterface { public: WebRtcVideoCapturer(); explicit WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory); @@ -65,10 +63,7 @@ class WebRtcVideoCapturer : public VideoCapturer, private: // Callback when a frame is captured by camera. - void OnIncomingCapturedFrame(const int32_t id, - const webrtc::VideoFrame& frame) override; - void OnCaptureDelayChanged(const int32_t id, - const int32_t delay) override; + void OnFrame(const webrtc::VideoFrame& frame) override; // Used to signal captured frames on the same thread as invoked Start(). // With WebRTC's current VideoCapturer implementations, this will mean a @@ -87,13 +82,6 @@ class WebRtcVideoCapturer : public VideoCapturer, std::unique_ptr async_invoker_; }; -struct WebRtcCapturedFrame : public CapturedFrame { - public: - WebRtcCapturedFrame(const webrtc::VideoFrame& frame, - void* buffer, - size_t length); -}; - } // namespace cricket #endif // WEBRTC_MEDIA_WEBRTC_WEBRTCVIDEOCAPTURER_H_ diff --git a/include/webrtc/media/engine/webrtcvideocapturerfactory.h b/include/webrtc/media/engine/webrtcvideocapturerfactory.h index 128ef9d..c1f91b7 100644 --- a/include/webrtc/media/engine/webrtcvideocapturerfactory.h +++ b/include/webrtc/media/engine/webrtcvideocapturerfactory.h @@ -19,7 +19,7 @@ namespace cricket { // Creates instances of cricket::WebRtcVideoCapturer. class WebRtcVideoDeviceCapturerFactory : public VideoDeviceCapturerFactory { public: - virtual VideoCapturer* Create(const Device& device); + std::unique_ptr Create(const Device& device) override; }; } // namespace cricket diff --git a/include/webrtc/media/engine/webrtcvideochannelfactory.h b/include/webrtc/media/engine/webrtcvideochannelfactory.h deleted file mode 100644 index 06498be..0000000 --- a/include/webrtc/media/engine/webrtcvideochannelfactory.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCHANNELFACTORY_H_ -#define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCHANNELFACTORY_H_ - -namespace cricket { -class VoiceMediaChannel; -class WebRtcVideoEngine2; -class WebRtcVideoChannel2; - -class WebRtcVideoChannelFactory { - public: - virtual ~WebRtcVideoChannelFactory() {} - virtual WebRtcVideoChannel2* Create(WebRtcVideoEngine2* engine, - VoiceMediaChannel* voice_channel) = 0; -}; -} // namespace cricket - -#endif // WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOCHANNELFACTORY_H_ diff --git a/include/webrtc/media/engine/webrtcvideodecoderfactory.h b/include/webrtc/media/engine/webrtcvideodecoderfactory.h index c739096..7f0921f 100644 --- a/include/webrtc/media/engine/webrtcvideodecoderfactory.h +++ b/include/webrtc/media/engine/webrtcvideodecoderfactory.h @@ -20,12 +20,21 @@ class VideoDecoder; namespace cricket { +struct VideoDecoderParams { + std::string receive_stream_id; +}; + class WebRtcVideoDecoderFactory { public: // Caller takes the ownership of the returned object and it should be released // by calling DestroyVideoDecoder(). virtual webrtc::VideoDecoder* CreateVideoDecoder( webrtc::VideoCodecType type) = 0; + virtual webrtc::VideoDecoder* CreateVideoDecoderWithParams( + webrtc::VideoCodecType type, + VideoDecoderParams params) { + return CreateVideoDecoder(type); + } virtual ~WebRtcVideoDecoderFactory() {} virtual void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) = 0; diff --git a/include/webrtc/media/engine/webrtcvideoencoderfactory.h b/include/webrtc/media/engine/webrtcvideoencoderfactory.h index e57a314..35e4092 100644 --- a/include/webrtc/media/engine/webrtcvideoencoderfactory.h +++ b/include/webrtc/media/engine/webrtcvideoencoderfactory.h @@ -11,7 +11,8 @@ #ifndef WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOENCODERFACTORY_H_ #define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOENCODERFACTORY_H_ -#include "webrtc/base/refcount.h" +#include + #include "webrtc/common_types.h" #include "webrtc/media/base/codec.h" @@ -23,28 +24,46 @@ namespace cricket { class WebRtcVideoEncoderFactory { public: + // This VideoCodec class is deprecated. Use cricket::VideoCodec directly + // instead and the corresponding factory function. See + // http://crbug/webrtc/6402 for more info. struct VideoCodec { webrtc::VideoCodecType type; std::string name; - int max_width; - int max_height; - int max_fps; - VideoCodec(webrtc::VideoCodecType t, const std::string& nm, int w, int h, + VideoCodec(webrtc::VideoCodecType t, const std::string& nm) + : type(t), name(nm) {} + + VideoCodec(webrtc::VideoCodecType t, + const std::string& nm, + int w, + int h, int fr) - : type(t), name(nm), max_width(w), max_height(h), max_fps(fr) { - } + : type(t), name(nm) {} }; virtual ~WebRtcVideoEncoderFactory() {} + // TODO(magjed): Make these functions pure virtual when every external client + // implements it. See http://crbug/webrtc/6402 for more info. // Caller takes the ownership of the returned object and it should be released // by calling DestroyVideoEncoder(). virtual webrtc::VideoEncoder* CreateVideoEncoder( - webrtc::VideoCodecType type) = 0; + const cricket::VideoCodec& codec); + + // Returns a list of supported codecs in order of preference. + virtual const std::vector& supported_codecs() const; + + // Caller takes the ownership of the returned object and it should be released + // by calling DestroyVideoEncoder(). + // Deprecated: Use cricket::VideoCodec as argument instead. See + // http://crbug/webrtc/6402 for more info. + virtual webrtc::VideoEncoder* CreateVideoEncoder(webrtc::VideoCodecType type); // Returns a list of supported codecs in order of preference. - virtual const std::vector& codecs() const = 0; + // Deprecated: Return cricket::VideoCodecs instead. See + // http://crbug/webrtc/6402 for more info. + virtual const std::vector& codecs() const; // Returns true if encoders created by this factory of the given codec type // will use internal camera sources, meaning that they don't require/expect @@ -56,6 +75,13 @@ class WebRtcVideoEncoderFactory { } virtual void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) = 0; + + private: + // TODO(magjed): Remove these. They are necessary in order to return a const + // reference to a std::vector in the default implementations of codecs() and + // supported_codecs(). See http://crbug/webrtc/6402 for more info. + mutable std::vector encoder_codecs_; + mutable std::vector codecs_; }; } // namespace cricket diff --git a/include/webrtc/media/engine/webrtcvideoengine2.h b/include/webrtc/media/engine/webrtcvideoengine2.h index 2d1b192..309a84d 100644 --- a/include/webrtc/media/engine/webrtcvideoengine2.h +++ b/include/webrtc/media/engine/webrtcvideoengine2.h @@ -17,6 +17,8 @@ #include #include +#include "webrtc/api/call/transport.h" +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/asyncinvoker.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/networkroute.h" @@ -24,13 +26,11 @@ #include "webrtc/base/thread_checker.h" #include "webrtc/media/base/videosinkinterface.h" #include "webrtc/media/base/videosourceinterface.h" -#include "webrtc/call.h" +#include "webrtc/call/call.h" +#include "webrtc/call/flexfec_receive_stream.h" #include "webrtc/media/base/mediaengine.h" -#include "webrtc/media/engine/webrtcvideochannelfactory.h" #include "webrtc/media/engine/webrtcvideodecoderfactory.h" #include "webrtc/media/engine/webrtcvideoencoderfactory.h" -#include "webrtc/transport.h" -#include "webrtc/video_frame.h" #include "webrtc/video_receive_stream.h" #include "webrtc/video_send_stream.h" @@ -47,7 +47,6 @@ class Thread; namespace cricket { class VideoCapturer; -class VideoFrame; class VideoProcessor; class VideoRenderer; class VoiceMediaChannel; @@ -55,17 +54,14 @@ class WebRtcDecoderObserver; class WebRtcEncoderObserver; class WebRtcLocalStreamInfo; class WebRtcRenderAdapter; +class WebRtcVideoChannel2; class WebRtcVideoChannelRecvInfo; class WebRtcVideoChannelSendInfo; class WebRtcVoiceEngine; class WebRtcVoiceMediaChannel; -struct CapturedFrame; struct Device; -// Exposed here for unittests. -std::vector DefaultVideoCodecList(); - class UnsignalledSsrcHandler { public: enum Action { @@ -84,14 +80,14 @@ class DefaultUnsignalledSsrcHandler : public UnsignalledSsrcHandler { Action OnUnsignalledSsrc(WebRtcVideoChannel2* channel, uint32_t ssrc) override; - rtc::VideoSinkInterface* GetDefaultSink() const; + rtc::VideoSinkInterface* GetDefaultSink() const; void SetDefaultSink(VideoMediaChannel* channel, - rtc::VideoSinkInterface* sink); + rtc::VideoSinkInterface* sink); virtual ~DefaultUnsignalledSsrcHandler() = default; private: uint32_t default_recv_ssrc_; - rtc::VideoSinkInterface* default_sink_; + rtc::VideoSinkInterface* default_sink_; }; // WebRtcVideoEngine2 is used for the new native WebRTC Video API (webrtc:1667). @@ -107,7 +103,7 @@ class WebRtcVideoEngine2 { const MediaConfig& config, const VideoOptions& options); - const std::vector& codecs() const; + std::vector codecs() const; RtpCapabilities GetCapabilities() const; // Set a WebRtcVideoDecoderFactory for external decoding. Video engine does @@ -121,10 +117,6 @@ class WebRtcVideoEngine2 { WebRtcVideoEncoderFactory* encoder_factory); private: - std::vector GetSupportedCodecs() const; - - std::vector video_codecs_; - bool initialized_; WebRtcVideoDecoderFactory* external_decoder_factory_; @@ -137,7 +129,6 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { WebRtcVideoChannel2(webrtc::Call* call, const MediaConfig& config, const VideoOptions& options, - const std::vector& recv_codecs, WebRtcVideoEncoderFactory* external_encoder_factory, WebRtcVideoDecoderFactory* external_decoder_factory); ~WebRtcVideoChannel2() override; @@ -156,20 +147,19 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { const webrtc::RtpParameters& parameters) override; bool GetSendCodec(VideoCodec* send_codec) override; bool SetSend(bool send) override; - bool SetVideoSend(uint32_t ssrc, - bool mute, - const VideoOptions* options) override; + bool SetVideoSend( + uint32_t ssrc, + bool enable, + const VideoOptions* options, + rtc::VideoSourceInterface* source) override; bool AddSendStream(const StreamParams& sp) override; bool RemoveSendStream(uint32_t ssrc) override; bool AddRecvStream(const StreamParams& sp) override; bool AddRecvStream(const StreamParams& sp, bool default_stream); bool RemoveRecvStream(uint32_t ssrc) override; bool SetSink(uint32_t ssrc, - rtc::VideoSinkInterface* sink) override; + rtc::VideoSinkInterface* sink) override; bool GetStats(VideoMediaInfo* info) override; - void SetSource( - uint32_t ssrc, - rtc::VideoSourceInterface* source) override; void OnPacketReceived(rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) override; @@ -178,6 +168,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { void OnReadyToSend(bool ready) override; void OnNetworkRouteChanged(const std::string& transport_name, const rtc::NetworkRoute& network_route) override; + void OnTransportOverheadChanged(int transport_overhead_per_packet) override; void SetInterface(NetworkInterface* iface) override; // Implemented for VideoMediaChannelTest. @@ -201,7 +192,8 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { bool operator!=(const VideoCodecSettings& other) const; VideoCodec codec; - webrtc::FecConfig fec; + webrtc::UlpfecConfig ulpfec; + int flexfec_payload_type; int rtx_payload_type; }; @@ -226,11 +218,11 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { ChangedRecvParameters* changed_params) const; void SetMaxSendBandwidth(int bps); - void SetOptions(uint32_t ssrc, const VideoOptions& options); - void ConfigureReceiverRtp(webrtc::VideoReceiveStream::Config* config, - const StreamParams& sp) const; - bool CodecIsExternallySupported(const std::string& name) const; + void ConfigureReceiverRtp( + webrtc::VideoReceiveStream::Config* config, + webrtc::FlexfecReceiveStream::Config* flexfec_config, + const StreamParams& sp) const; bool ValidateSendSsrcAvailability(const StreamParams& sp) const EXCLUSIVE_LOCKS_REQUIRED(stream_crit_); bool ValidateReceiveSsrcAvailability(const StreamParams& sp) const @@ -241,42 +233,43 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { static std::string CodecSettingsVectorToString( const std::vector& codecs); - // Wrapper for the sender part, this is where the source is connected and - // frames are then converted from cricket frames to webrtc frames. + // Wrapper for the sender part. class WebRtcVideoSendStream - : public rtc::VideoSinkInterface, - public webrtc::LoadObserver { + : public rtc::VideoSourceInterface { public: WebRtcVideoSendStream( webrtc::Call* call, const StreamParams& sp, - const webrtc::VideoSendStream::Config& config, + webrtc::VideoSendStream::Config config, const VideoOptions& options, WebRtcVideoEncoderFactory* external_encoder_factory, bool enable_cpu_overuse_detection, int max_bitrate_bps, const rtc::Optional& codec_settings, - const std::vector& rtp_extensions, + const rtc::Optional>& rtp_extensions, const VideoSendParameters& send_params); virtual ~WebRtcVideoSendStream(); - void SetOptions(const VideoOptions& options); - // TODO(pbos): Move logic from SetOptions into this method. void SetSendParameters(const ChangedSendParameters& send_params); bool SetRtpParameters(const webrtc::RtpParameters& parameters); webrtc::RtpParameters GetRtpParameters() const; - void OnFrame(const cricket::VideoFrame& frame) override; - void SetSource(rtc::VideoSourceInterface* source); - void DisconnectSource(); + // Implements rtc::VideoSourceInterface. + // WebRtcVideoSendStream acts as a source to the webrtc::VideoSendStream + // in |stream_|. This is done to proxy VideoSinkWants from the encoder to + // the worker thread. + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; - void SetSend(bool send); + bool SetVideoSend(bool mute, + const VideoOptions* options, + rtc::VideoSourceInterface* source); - // Implements webrtc::LoadObserver. - void OnLoadUpdate(Load load) override; + void SetSend(bool send); const std::vector& GetSsrcs() const; - VideoSenderInfo GetVideoSenderInfo(); + VideoSenderInfo GetVideoSenderInfo(bool log_stats); void FillBandwidthEstimationInfo(BandwidthEstimationInfo* bwe_info); private: @@ -286,7 +279,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { // similar parameters depending on which options changed etc. struct VideoSendStreamParameters { VideoSendStreamParameters( - const webrtc::VideoSendStream::Config& config, + webrtc::VideoSendStream::Config config, const VideoOptions& options, int max_bitrate_bps, const rtc::Optional& codec_settings); @@ -303,130 +296,83 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { struct AllocatedEncoder { AllocatedEncoder(webrtc::VideoEncoder* encoder, - webrtc::VideoCodecType type, + const cricket::VideoCodec& codec, bool external); webrtc::VideoEncoder* encoder; webrtc::VideoEncoder* external_encoder; - webrtc::VideoCodecType type; + cricket::VideoCodec codec; bool external; }; - struct Dimensions { - // Initial encoder configuration (QCIF, 176x144) frame (to ensure that - // hardware encoders 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). - // TODO(pbos): Consider setting up encoders lazily. - Dimensions() : width(176), height(144) {} - int width; - int height; - }; - - union VideoEncoderSettings { - webrtc::VideoCodecH264 h264; - webrtc::VideoCodecVP8 vp8; - webrtc::VideoCodecVP9 vp9; - }; - - static std::vector CreateVideoStreams( - const VideoCodec& codec, - const VideoOptions& options, - int max_bitrate_bps, - size_t num_streams); - static std::vector CreateSimulcastVideoStreams( - const VideoCodec& codec, - const VideoOptions& options, - int max_bitrate_bps, - size_t num_streams); - - void* ConfigureVideoEncoderSettings(const VideoCodec& codec) - EXCLUSIVE_LOCKS_REQUIRED(lock_); - - AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec) - EXCLUSIVE_LOCKS_REQUIRED(lock_); - void DestroyVideoEncoder(AllocatedEncoder* encoder) - EXCLUSIVE_LOCKS_REQUIRED(lock_); - void SetCodec(const VideoCodecSettings& codec) - EXCLUSIVE_LOCKS_REQUIRED(lock_); - void RecreateWebRtcStream() EXCLUSIVE_LOCKS_REQUIRED(lock_); + rtc::scoped_refptr + ConfigureVideoEncoderSettings(const VideoCodec& codec); + // If force_encoder_allocation is true, a new AllocatedEncoder is always + // created. If false, the allocated encoder may be reused, if the type + // matches. + AllocatedEncoder CreateVideoEncoder(const VideoCodec& codec, + bool force_encoder_allocation); + void DestroyVideoEncoder(AllocatedEncoder* encoder); + void SetCodec(const VideoCodecSettings& codec, + bool force_encoder_allocation); + void RecreateWebRtcStream(); webrtc::VideoEncoderConfig CreateVideoEncoderConfig( - const Dimensions& dimensions, - const VideoCodec& codec) const EXCLUSIVE_LOCKS_REQUIRED(lock_); - void SetDimensions(int width, int height) - EXCLUSIVE_LOCKS_REQUIRED(lock_); + const VideoCodec& codec) const; + void ReconfigureEncoder(); bool ValidateRtpParameters(const webrtc::RtpParameters& parameters); // Calls Start or Stop according to whether or not |sending_| is true, // and whether or not the encoding in |rtp_parameters_| is active. - void UpdateSendState() EXCLUSIVE_LOCKS_REQUIRED(lock_); + void UpdateSendState(); rtc::ThreadChecker thread_checker_; rtc::AsyncInvoker invoker_; rtc::Thread* worker_thread_; - const std::vector ssrcs_; - const std::vector ssrc_groups_; + const std::vector ssrcs_ ACCESS_ON(&thread_checker_); + const std::vector ssrc_groups_ ACCESS_ON(&thread_checker_); webrtc::Call* const call_; - rtc::VideoSinkWants sink_wants_; - // Counter used for deciding if the video resolution is currently - // restricted by CPU usage. It is reset if |source_| is changed. - int cpu_restricted_counter_; - // Total number of times resolution as been requested to be changed due to - // CPU adaptation. - int number_of_cpu_adapt_changes_; - rtc::VideoSourceInterface* source_; + const bool enable_cpu_overuse_detection_; + rtc::VideoSourceInterface* source_ + ACCESS_ON(&thread_checker_); WebRtcVideoEncoderFactory* const external_encoder_factory_ - GUARDED_BY(lock_); + ACCESS_ON(&thread_checker_); + const std::unique_ptr internal_encoder_factory_ + ACCESS_ON(&thread_checker_); - rtc::CriticalSection lock_; - webrtc::VideoSendStream* stream_ GUARDED_BY(lock_); + webrtc::VideoSendStream* stream_ ACCESS_ON(&thread_checker_); + rtc::VideoSinkInterface* encoder_sink_ + ACCESS_ON(&thread_checker_); // Contains settings that are the same for all streams in the MediaChannel, // such as codecs, header extensions, and the global bitrate limit for the // entire channel. - VideoSendStreamParameters parameters_ GUARDED_BY(lock_); + VideoSendStreamParameters parameters_ ACCESS_ON(&thread_checker_); // Contains settings that are unique for each stream, such as max_bitrate. // Does *not* contain codecs, however. // TODO(skvlad): Move ssrcs_ and ssrc_groups_ into rtp_parameters_. // TODO(skvlad): Combine parameters_ and rtp_parameters_ once we have only // one stream per MediaChannel. - webrtc::RtpParameters rtp_parameters_ GUARDED_BY(lock_); - bool pending_encoder_reconfiguration_ GUARDED_BY(lock_); - VideoEncoderSettings encoder_settings_ GUARDED_BY(lock_); - AllocatedEncoder allocated_encoder_ GUARDED_BY(lock_); - Dimensions last_dimensions_ GUARDED_BY(lock_); - webrtc::VideoRotation last_rotation_ GUARDED_BY(lock_) = - webrtc::kVideoRotation_0; - - bool sending_ GUARDED_BY(lock_); - - // The timestamp of the first frame received - // Used to generate the timestamps of subsequent frames - rtc::Optional first_frame_timestamp_ms_ GUARDED_BY(lock_); - - // The timestamp of the last frame received - // Used to generate timestamp for the black frame when source is removed - int64_t last_frame_timestamp_ms_ GUARDED_BY(lock_); + webrtc::RtpParameters rtp_parameters_ ACCESS_ON(&thread_checker_); + AllocatedEncoder allocated_encoder_ ACCESS_ON(&thread_checker_); + + bool sending_ ACCESS_ON(&thread_checker_); }; // Wrapper for the receiver part, contains configs etc. that are needed to - // reconstruct the underlying VideoReceiveStream. Also serves as a wrapper - // between rtc::VideoSinkInterface and - // rtc::VideoSinkInterface. + // reconstruct the underlying VideoReceiveStream. class WebRtcVideoReceiveStream : public rtc::VideoSinkInterface { public: WebRtcVideoReceiveStream( webrtc::Call* call, const StreamParams& sp, - const webrtc::VideoReceiveStream::Config& config, + webrtc::VideoReceiveStream::Config config, WebRtcVideoDecoderFactory* external_decoder_factory, bool default_stream, const std::vector& recv_codecs, - bool red_disabled_by_remote_side); + const webrtc::FlexfecReceiveStream::Config& flexfec_config); ~WebRtcVideoReceiveStream(); const std::vector& GetSsrcs() const; + rtc::Optional GetFirstPrimarySsrc() const; void SetLocalSsrc(uint32_t local_ssrc); // TODO(deadbeef): Move these feedback parameters into the recv parameters. @@ -439,17 +385,9 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { void OnFrame(const webrtc::VideoFrame& frame) override; bool IsDefaultStream() const; - void SetSink(rtc::VideoSinkInterface* sink); + void SetSink(rtc::VideoSinkInterface* sink); - VideoReceiverInfo GetVideoReceiverInfo(); - - // Used to disable RED/FEC when the remote description doesn't contain those - // codecs. This is needed to be able to work around an RTX bug which is only - // happening if the remote side doesn't send RED, but the local side is - // configured to receive RED. - // TODO(holmer): Remove this after a couple of Chrome versions, M53-54 - // time frame. - void SetFecDisabledRemotely(bool disable); + VideoReceiverInfo GetVideoReceiverInfo(bool log_stats); private: struct AllocatedDecoder { @@ -475,21 +413,22 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { std::string GetCodecNameFromPayloadType(int payload_type); webrtc::Call* const call_; - const std::vector ssrcs_; - const std::vector ssrc_groups_; + StreamParams stream_params_; + // Both |stream_| and |flexfec_stream_| are managed by |this|. They are + // destroyed by calling call_->DestroyVideoReceiveStream and + // call_->DestroyFlexfecReceiveStream, respectively. webrtc::VideoReceiveStream* stream_; const bool default_stream_; webrtc::VideoReceiveStream::Config config_; - bool red_disabled_by_remote_side_; + webrtc::FlexfecReceiveStream::Config flexfec_config_; + webrtc::FlexfecReceiveStream* flexfec_stream_; WebRtcVideoDecoderFactory* const external_decoder_factory_; std::vector allocated_decoders_; rtc::CriticalSection sink_lock_; - rtc::VideoSinkInterface* sink_ GUARDED_BY(sink_lock_); - int last_width_ GUARDED_BY(sink_lock_); - int last_height_ GUARDED_BY(sink_lock_); + rtc::VideoSinkInterface* sink_ GUARDED_BY(sink_lock_); // Expands remote RTP timestamps to int64_t to be able to estimate how long // the stream has been running. rtc::TimestampWrapAroundHandler timestamp_wraparound_handler_ @@ -509,15 +448,20 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { static std::vector MapCodecs( const std::vector& codecs); - std::vector FilterSupportedCodecs( - const std::vector& mapped_codecs) const; + // Select what video codec will be used for sending, i.e. what codec is used + // for local encoding, based on supported remote codecs. The first remote + // codec that is supported locally will be selected. + rtc::Optional SelectSendVideoCodec( + const std::vector& remote_mapped_codecs) const; + static bool ReceiveCodecsHaveChanged(std::vector before, std::vector after); - void FillSenderStats(VideoMediaInfo* info); - void FillReceiverStats(VideoMediaInfo* info); + void FillSenderStats(VideoMediaInfo* info, bool log_stats); + void FillReceiverStats(VideoMediaInfo* info, bool log_stats); void FillBandwidthEstimationStats(const webrtc::Call::Stats& stats, VideoMediaInfo* info); + void FillSendAndReceiveCodecStats(VideoMediaInfo* video_media_info); rtc::ThreadChecker thread_checker_; @@ -540,7 +484,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { std::set receive_ssrcs_ GUARDED_BY(stream_crit_); rtc::Optional send_codec_; - std::vector send_rtp_extensions_; + rtc::Optional> send_rtp_extensions_; WebRtcVideoEncoderFactory* const external_encoder_factory_; WebRtcVideoDecoderFactory* const external_decoder_factory_; @@ -552,7 +496,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { VideoSendParameters send_params_; VideoOptions default_send_options_; VideoRecvParameters recv_params_; - bool red_disabled_by_remote_side_; + int64_t last_stats_log_ms_; }; } // namespace cricket diff --git a/include/webrtc/media/engine/webrtcvideoframe.h b/include/webrtc/media/engine/webrtcvideoframe.h index ee34c41..d836905 100644 --- a/include/webrtc/media/engine/webrtcvideoframe.h +++ b/include/webrtc/media/engine/webrtcvideoframe.h @@ -8,6 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ +// TODO(nisse): Deprecated, replace cricket::WebRtcVideoFrame with +// webrtc::VideoFrame everywhere, then delete this file. See +// https://bugs.chromium.org/p/webrtc/issues/detail?id=5682. + #ifndef WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOFRAME_H_ #define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOFRAME_H_ @@ -22,104 +26,7 @@ namespace cricket { -struct CapturedFrame; - -class WebRtcVideoFrame : public VideoFrame { - public: - WebRtcVideoFrame(); - - // Preferred construction, with microsecond timestamp. - WebRtcVideoFrame(const rtc::scoped_refptr& buffer, - webrtc::VideoRotation rotation, - int64_t timestamp_us); - - // TODO(nisse): Deprecate/delete. - WebRtcVideoFrame(const rtc::scoped_refptr& buffer, - int64_t time_stamp_ns, - webrtc::VideoRotation rotation); - - ~WebRtcVideoFrame(); - - // Creates a frame from a raw sample with FourCC "format" and size "w" x "h". - // "h" can be negative indicating a vertically flipped image. - // "dh" is destination height if cropping is desired and is always positive. - // Returns "true" if successful. - bool Init(uint32_t format, - int w, - int h, - int dw, - int dh, - uint8_t* sample, - size_t sample_size, - int64_t time_stamp_ns, - webrtc::VideoRotation rotation); - - // The timestamp of the captured frame is expected to use the same - // timescale and epoch as rtc::Time. - // TODO(nisse): Consider adding a warning message, or even an RTC_DCHECK, if - // the time is too far off. - bool Init(const CapturedFrame* frame, int dw, int dh, bool apply_rotation); - - void InitToEmptyBuffer(int w, int h); - void InitToEmptyBuffer(int w, int h, int64_t time_stamp_ns); - - bool InitToBlack(int w, int h, int64_t time_stamp_ns); - - int width() const override; - int height() const override; - - void* GetNativeHandle() const override; - const rtc::scoped_refptr& video_frame_buffer() - const override; - - /* System monotonic clock */ - int64_t timestamp_us() const override { return timestamp_us_; } - void set_timestamp_us(int64_t time_us) override { timestamp_us_ = time_us; }; - - webrtc::VideoRotation rotation() const override { return rotation_; } - - VideoFrame* Copy() const override; - bool IsExclusive() const override; - size_t ConvertToRgbBuffer(uint32_t to_fourcc, - uint8_t* buffer, - size_t size, - int stride_rgb) const override; - - const VideoFrame* GetCopyWithRotationApplied() const override; - - protected: - void set_rotation(webrtc::VideoRotation rotation) override { - rotation_ = rotation; - } - // Creates a frame from a raw sample with FourCC |format| and size |w| x |h|. - // |h| can be negative indicating a vertically flipped image. - // |dw| is destination width; can be less than |w| if cropping is desired. - // |dh| is destination height, like |dw|, but must be a positive number. - // Returns whether the function succeeded or failed. - bool Reset(uint32_t format, - int w, - int h, - int dw, - int dh, - uint8_t* sample, - size_t sample_size, - int64_t timestamp_us, - webrtc::VideoRotation rotation, - bool apply_rotation); - - private: - VideoFrame* CreateEmptyFrame(int w, int h, - int64_t time_stamp_ns) const override; - - // An opaque reference counted handle that stores the pixel data. - rtc::scoped_refptr video_frame_buffer_; - int64_t timestamp_us_; - webrtc::VideoRotation rotation_; - - // This is mutable as the calculation is expensive but once calculated, it - // remains const. - mutable std::unique_ptr rotated_frame_; -}; +using WebRtcVideoFrame = webrtc::VideoFrame; } // namespace cricket diff --git a/include/webrtc/media/engine/webrtcvideoframefactory.h b/include/webrtc/media/engine/webrtcvideoframefactory.h deleted file mode 100644 index c156996..0000000 --- a/include/webrtc/media/engine/webrtcvideoframefactory.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOFRAMEFACTORY_H_ -#define WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOFRAMEFACTORY_H_ - -#include "webrtc/media/base/videoframefactory.h" - -namespace cricket { - -struct CapturedFrame; - -// Creates instances of cricket::WebRtcVideoFrame. -class WebRtcVideoFrameFactory : public VideoFrameFactory { - public: - VideoFrame* CreateAliasedFrame(const CapturedFrame* aliased_frame, - int width, - int height) const override; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_ENGINE_WEBRTCVIDEOFRAMEFACTORY_H_ diff --git a/include/webrtc/media/engine/webrtcvoe.h b/include/webrtc/media/engine/webrtcvoe.h index 238b4ce..eabde36 100644 --- a/include/webrtc/media/engine/webrtcvoe.h +++ b/include/webrtc/media/engine/webrtcvoe.h @@ -13,18 +13,14 @@ #include -#include "webrtc/base/common.h" #include "webrtc/media/engine/webrtccommon.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/voice_engine/include/voe_audio_processing.h" #include "webrtc/voice_engine/include/voe_base.h" #include "webrtc/voice_engine/include/voe_codec.h" #include "webrtc/voice_engine/include/voe_errors.h" #include "webrtc/voice_engine/include/voe_hardware.h" -#include "webrtc/voice_engine/include/voe_network.h" -#include "webrtc/voice_engine/include/voe_rtp_rtcp.h" #include "webrtc/voice_engine/include/voe_volume_control.h" namespace cricket { @@ -32,12 +28,18 @@ namespace cricket { class scoped_voe_engine { public: explicit scoped_voe_engine(webrtc::VoiceEngine* e) : ptr(e) {} - // VERIFY, to ensure that there are no leaks at shutdown - ~scoped_voe_engine() { if (ptr) VERIFY(webrtc::VoiceEngine::Delete(ptr)); } + // RTC_DCHECK, to ensure that there are no leaks at shutdown + ~scoped_voe_engine() { + if (ptr) { + const bool success = webrtc::VoiceEngine::Delete(ptr); + RTC_DCHECK(success); + } + } // Releases the current pointer. void reset() { if (ptr) { - VERIFY(webrtc::VoiceEngine::Delete(ptr)); + const bool success = webrtc::VoiceEngine::Delete(ptr); + RTC_DCHECK(success); ptr = NULL; } } @@ -75,41 +77,33 @@ class scoped_voe_ptr { class VoEWrapper { public: VoEWrapper() - : engine_(webrtc::VoiceEngine::Create()), processing_(engine_), - base_(engine_), codec_(engine_), hw_(engine_), rtp_(engine_), + : engine_(webrtc::VoiceEngine::Create()), + base_(engine_), codec_(engine_), hw_(engine_), volume_(engine_) { } - VoEWrapper(webrtc::VoEAudioProcessing* processing, - webrtc::VoEBase* base, + VoEWrapper(webrtc::VoEBase* base, webrtc::VoECodec* codec, webrtc::VoEHardware* hw, - webrtc::VoERTP_RTCP* rtp, webrtc::VoEVolumeControl* volume) : engine_(NULL), - processing_(processing), base_(base), codec_(codec), hw_(hw), - rtp_(rtp), volume_(volume) { } ~VoEWrapper() {} webrtc::VoiceEngine* engine() const { return engine_.get(); } - webrtc::VoEAudioProcessing* processing() const { return processing_.get(); } webrtc::VoEBase* base() const { return base_.get(); } webrtc::VoECodec* codec() const { return codec_.get(); } webrtc::VoEHardware* hw() const { return hw_.get(); } - webrtc::VoERTP_RTCP* rtp() const { return rtp_.get(); } webrtc::VoEVolumeControl* volume() const { return volume_.get(); } int error() { return base_->LastError(); } private: scoped_voe_engine engine_; - scoped_voe_ptr processing_; scoped_voe_ptr base_; scoped_voe_ptr codec_; scoped_voe_ptr hw_; - scoped_voe_ptr rtp_; scoped_voe_ptr volume_; }; } // namespace cricket diff --git a/include/webrtc/media/engine/webrtcvoiceengine.h b/include/webrtc/media/engine/webrtcvoiceengine.h index 5b43534..0eeef48 100644 --- a/include/webrtc/media/engine/webrtcvoiceengine.h +++ b/include/webrtc/media/engine/webrtcvoiceengine.h @@ -16,24 +16,30 @@ #include #include -#include "webrtc/audio_state.h" #include "webrtc/base/buffer.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/networkroute.h" #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/base/stream.h" #include "webrtc/base/thread_checker.h" -#include "webrtc/call.h" -#include "webrtc/common.h" +#include "webrtc/call/audio_state.h" +#include "webrtc/call/call.h" #include "webrtc/config.h" #include "webrtc/media/base/rtputils.h" #include "webrtc/media/engine/webrtccommon.h" #include "webrtc/media/engine/webrtcvoe.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" #include "webrtc/pc/channel.h" +namespace webrtc { +namespace voe { +class TransmitMixer; +} // namespace voe +} // namespace webrtc + namespace cricket { class AudioDeviceModule; +class AudioMixer; class AudioSource; class VoEWrapper; class WebRtcVoiceMediaChannel; @@ -46,9 +52,16 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { // Exposed for the WVoE/MC unit test. static bool ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out); - explicit WebRtcVoiceEngine(webrtc::AudioDeviceModule* adm); + WebRtcVoiceEngine( + webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer); // Dependency injection for testing. - WebRtcVoiceEngine(webrtc::AudioDeviceModule* adm, VoEWrapper* voe_wrapper); + WebRtcVoiceEngine( + webrtc::AudioDeviceModule* adm, + const rtc::scoped_refptr& decoder_factory, + rtc::scoped_refptr audio_mixer, + VoEWrapper* voe_wrapper); ~WebRtcVoiceEngine() override; rtc::scoped_refptr GetAudioState() const; @@ -56,11 +69,10 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { const MediaConfig& config, const AudioOptions& options); - bool GetOutputVolume(int* level); - bool SetOutputVolume(int level); int GetInputLevel(); - const std::vector& codecs(); + const std::vector& send_codecs() const; + const std::vector& recv_codecs() const; RtpCapabilities GetCapabilities() const; // For tracking WebRtc channels. Needed because we have to pause them @@ -69,10 +81,6 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { void RegisterChannel(WebRtcVoiceMediaChannel* channel); void UnregisterChannel(WebRtcVoiceMediaChannel* channel); - // Called by WebRtcVoiceMediaChannel to set a gain offset from - // the default AGC target level. - bool AdjustAgcLevel(int delta); - VoEWrapper* voe() { return voe_wrapper_.get(); } int GetLastEngineError(); @@ -85,13 +93,9 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { // Stops AEC dump. void StopAecDump(); - // Starts recording an RtcEventLog using an existing file until the log file - // reaches the maximum filesize or the StopRtcEventLog function is called. - // If the value of max_size_bytes is <= 0, no limit is used. - bool StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes); - - // Stops recording the RtcEventLog. - void StopRtcEventLog(); + const webrtc::AudioProcessing::Config& GetApmConfigForTest() const { + return apm_config_; + } private: // Every option that is "set" will be applied. Every option not "set" will be @@ -106,29 +110,43 @@ class WebRtcVoiceEngine final : public webrtc::TraceCallback { void StartAecDump(const std::string& filename); int CreateVoEChannel(); webrtc::AudioDeviceModule* adm(); + webrtc::AudioProcessing* apm(); + webrtc::voe::TransmitMixer* transmit_mixer(); + + AudioCodecs CollectRecvCodecs() const; rtc::ThreadChecker signal_thread_checker_; rtc::ThreadChecker worker_thread_checker_; // The audio device manager. rtc::scoped_refptr adm_; + rtc::scoped_refptr decoder_factory_; + // Reference to the APM, owned by VoE. + webrtc::AudioProcessing* apm_ = nullptr; + // Reference to the TransmitMixer, owned by VoE. + webrtc::voe::TransmitMixer* transmit_mixer_ = nullptr; // The primary instance of WebRtc VoiceEngine. std::unique_ptr voe_wrapper_; rtc::scoped_refptr audio_state_; - std::vector codecs_; + std::vector send_codecs_; + std::vector recv_codecs_; std::vector channels_; - webrtc::Config voe_config_; + webrtc::VoEBase::ChannelConfig channel_config_; bool is_dumping_aec_ = false; webrtc::AgcConfig default_agc_config_; - // Cache received extended_filter_aec, delay_agnostic_aec, experimental_ns and - // intelligibility_enhancer values, and apply them in case they are missing - // in the audio options. We need to do this because SetExtraOptions() will - // revert to defaults for options which are not provided. + // Cache received extended_filter_aec, delay_agnostic_aec, experimental_ns + // level controller, and intelligibility_enhancer values, and apply them + // in case they are missing in the audio options. We need to do this because + // SetExtraOptions() will revert to defaults for options which are not + // provided. rtc::Optional extended_filter_aec_; rtc::Optional delay_agnostic_aec_; rtc::Optional experimental_ns_; rtc::Optional intelligibility_enhancer_; + rtc::Optional level_control_; + + webrtc::AudioProcessing::Config apm_config_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceEngine); }; @@ -158,9 +176,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, uint32_t ssrc, const webrtc::RtpParameters& parameters) override; - bool SetPlayout(bool playout) override; - bool PausePlayout(); - bool ResumePlayout(); + void SetPlayout(bool playout) override; void SetSend(bool send) override; bool SetAudioSend(uint32_t ssrc, bool enable, @@ -172,12 +188,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, bool RemoveRecvStream(uint32_t ssrc) override; bool GetActiveStreams(AudioInfo::StreamList* actives) override; int GetOutputLevel() override; - int GetTimeSinceLastTyping() override; - void SetTypingDetectionParameters(int time_window, - int cost_per_typing, - int reporting_threshold, - int penalty_decay, - int type_event_delay) override; bool SetOutputVolume(uint32_t ssrc, double volume) override; bool CanInsertDtmf() override; @@ -190,6 +200,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, void OnNetworkRouteChanged(const std::string& transport_name, const rtc::NetworkRoute& network_route) override; void OnReadyToSend(bool ready) override; + void OnTransportOverheadChanged(int transport_overhead_per_packet) override; bool GetStats(VoiceMediaInfo* info) override; void SetRawAudioSink( @@ -218,29 +229,19 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, bool SetOptions(const AudioOptions& options); bool SetRecvCodecs(const std::vector& codecs); bool SetSendCodecs(const std::vector& codecs); - bool SetSendCodecs(int channel, const webrtc::RtpParameters& rtp_parameters); - void SetNack(int channel, bool nack_enabled); - bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec); bool SetLocalSource(uint32_t ssrc, AudioSource* source); bool MuteStream(uint32_t ssrc, bool mute); WebRtcVoiceEngine* engine() { return engine_; } int GetLastEngineError() { return engine()->GetLastEngineError(); } int GetOutputLevel(int channel); - bool SetPlayout(int channel, bool playout); - bool ChangePlayout(bool playout); + void ChangePlayout(bool playout); int CreateVoEChannel(); bool DeleteVoEChannel(int channel); bool IsDefaultRecvStream(uint32_t ssrc) { return default_recv_ssrc_ == static_cast(ssrc); } bool SetMaxSendBitrate(int bps); - bool SetChannelSendParameters(int channel, - const webrtc::RtpParameters& parameters); - bool SetMaxSendBitrate(int channel, int bps); - bool HasSendCodec() const { - return send_codec_spec_.codec_inst.pltype != -1; - } bool ValidateRtpParameters(const webrtc::RtpParameters& parameters); void SetupRecording(); @@ -252,11 +253,14 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, int max_send_bitrate_bps_ = 0; AudioOptions options_; rtc::Optional dtmf_payload_type_; - bool desired_playout_ = false; + int dtmf_payload_freq_ = -1; bool recv_transport_cc_enabled_ = false; + bool recv_nack_enabled_ = false; + bool desired_playout_ = false; bool playout_ = false; bool send_ = false; webrtc::Call* const call_ = nullptr; + webrtc::Call::Config::BitrateConfig bitrate_config_; // SSRC of unsignalled receive stream, or -1 if there isn't one. int64_t default_recv_ssrc_ = -1; @@ -277,22 +281,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, std::map recv_streams_; std::vector recv_rtp_extensions_; - struct SendCodecSpec { - SendCodecSpec() { - webrtc::CodecInst empty_inst = {0}; - codec_inst = empty_inst; - codec_inst.pltype = -1; - } - bool nack_enabled = false; - bool transport_cc_enabled = false; - bool enable_codec_fec = false; - bool enable_opus_dtx = false; - int opus_max_playback_rate = 0; - int red_payload_type = -1; - int cng_payload_type = -1; - int cng_plfreq = -1; - webrtc::CodecInst codec_inst; - } send_codec_spec_; + webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel); }; diff --git a/include/webrtc/media/sctp/sctpdataengine.h b/include/webrtc/media/sctp/sctpdataengine.h deleted file mode 100644 index f9a3b5a..0000000 --- a/include/webrtc/media/sctp/sctpdataengine.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_ -#define WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_ - -#include -#include -#include - -namespace cricket { -// Some ERRNO values get re-#defined to WSA* equivalents in some talk/ -// headers. We save the original ones in an enum. -enum PreservedErrno { - SCTP_EINPROGRESS = EINPROGRESS, - SCTP_EWOULDBLOCK = EWOULDBLOCK -}; -} // namespace cricket - -#include "webrtc/base/copyonwritebuffer.h" -#include "webrtc/base/gtest_prod_util.h" -#include "webrtc/media/base/codec.h" -#include "webrtc/media/base/mediachannel.h" -#include "webrtc/media/base/mediaengine.h" - -// Defined by "usrsctplib/usrsctp.h" -struct sockaddr_conn; -struct sctp_assoc_change; -struct sctp_stream_reset_event; -// Defined by -struct socket; -namespace cricket { -// The highest stream ID (Sid) that SCTP allows, and the number of streams we -// tell SCTP we're going to use. -const uint32_t kMaxSctpSid = 1023; - -// This is the default SCTP port to use. It is passed along the wire and the -// connectee and connector must be using the same port. It is not related to the -// ports at the IP level. (Corresponds to: sockaddr_conn.sconn_port in -// usrsctp.h) -const int kSctpDefaultPort = 5000; - -class SctpDataMediaChannel; - -// A DataEngine that interacts with usrsctp. -// -// From channel calls, data flows like this: -// [worker thread (although it can in princple be another thread)] -// 1. SctpDataMediaChannel::SendData(data) -// 2. usrsctp_sendv(data) -// [worker thread returns; sctp thread then calls the following] -// 3. OnSctpOutboundPacket(wrapped_data) -// [sctp thread returns having posted a message for the worker thread] -// 4. SctpDataMediaChannel::OnMessage(wrapped_data) -// 5. SctpDataMediaChannel::OnPacketFromSctpToNetwork(wrapped_data) -// 6. NetworkInterface::SendPacket(wrapped_data) -// 7. ... across network ... a packet is sent back ... -// 8. SctpDataMediaChannel::OnPacketReceived(wrapped_data) -// 9. usrsctp_conninput(wrapped_data) -// [worker thread returns; sctp thread then calls the following] -// 10. OnSctpInboundData(data) -// [sctp thread returns having posted a message fot the worker thread] -// 11. SctpDataMediaChannel::OnMessage(inboundpacket) -// 12. SctpDataMediaChannel::OnInboundPacketFromSctpToChannel(inboundpacket) -// 13. SctpDataMediaChannel::OnDataFromSctpToChannel(data) -// 14. SctpDataMediaChannel::SignalDataReceived(data) -// [from the same thread, methods registered/connected to -// SctpDataMediaChannel are called with the recieved data] -class SctpDataEngine : public DataEngineInterface, public sigslot::has_slots<> { - public: - SctpDataEngine(); - ~SctpDataEngine() override; - - DataMediaChannel* CreateChannel(DataChannelType data_channel_type) override; - const std::vector& data_codecs() override { return codecs_; } - - private: - const std::vector codecs_; -}; - -// TODO(ldixon): Make into a special type of TypedMessageData. -// Holds data to be passed on to a channel. -struct SctpInboundPacket; - -class SctpDataMediaChannel : public DataMediaChannel, - public rtc::MessageHandler { - public: - // DataMessageType is used for the SCTP "Payload Protocol Identifier", as - // defined in http://tools.ietf.org/html/rfc4960#section-14.4 - // - // For the list of IANA approved values see: - // http://www.iana.org/assignments/sctp-parameters/sctp-parameters.xml - // The value is not used by SCTP itself. It indicates the protocol running - // on top of SCTP. - enum PayloadProtocolIdentifier { - PPID_NONE = 0, // No protocol is specified. - // Matches the PPIDs in mozilla source and - // https://datatracker.ietf.org/doc/draft-ietf-rtcweb-data-protocol Sec. 9 - // They're not yet assigned by IANA. - PPID_CONTROL = 50, - PPID_BINARY_PARTIAL = 52, - PPID_BINARY_LAST = 53, - PPID_TEXT_PARTIAL = 54, - PPID_TEXT_LAST = 51 - }; - - typedef std::set StreamSet; - - // Given a thread which will be used to post messages (received data) to this - // SctpDataMediaChannel instance. - explicit SctpDataMediaChannel(rtc::Thread* thread); - virtual ~SctpDataMediaChannel(); - - // When SetSend is set to true, connects. When set to false, disconnects. - // Calling: "SetSend(true); SetSend(false); SetSend(true);" will connect, - // disconnect, and reconnect. - virtual bool SetSend(bool send); - // Unless SetReceive(true) is called, received packets will be discarded. - virtual bool SetReceive(bool receive); - - virtual bool SetSendParameters(const DataSendParameters& params); - virtual bool SetRecvParameters(const DataRecvParameters& params); - virtual bool AddSendStream(const StreamParams& sp); - virtual bool RemoveSendStream(uint32_t ssrc); - virtual bool AddRecvStream(const StreamParams& sp); - virtual bool RemoveRecvStream(uint32_t ssrc); - - // Called when Sctp gets data. The data may be a notification or data for - // OnSctpInboundData. Called from the worker thread. - virtual void OnMessage(rtc::Message* msg); - // Send data down this channel (will be wrapped as SCTP packets then given to - // sctp that will then post the network interface by OnMessage). - // Returns true iff successful data somewhere on the send-queue/network. - virtual bool SendData(const SendDataParams& params, - const rtc::CopyOnWriteBuffer& payload, - SendDataResult* result = NULL); - // A packet is received from the network interface. Posted to OnMessage. - virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketTime& packet_time); - - // Exposed to allow Post call from c-callbacks. - rtc::Thread* worker_thread() const { return worker_thread_; } - - // Many of these things are unused by SCTP, but are needed to fulfill - // the MediaChannel interface. - virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet, - const rtc::PacketTime& packet_time) {} - virtual void OnReadyToSend(bool ready) {} - - void OnSendThresholdCallback(); - // Helper for debugging. - void set_debug_name_for_testing(const char* debug_name) { - debug_name_ = debug_name; - } - const struct socket* socket() const { return sock_; } - - private: - FRIEND_TEST_ALL_PREFIXES(SctpDataMediaChannelTest, EngineSignalsRightChannel); - static int SendThresholdCallback(struct socket* sock, uint32_t sb_free); - static SctpDataMediaChannel* GetChannelFromSocket(struct socket* sock); - - private: - sockaddr_conn GetSctpSockAddr(int port); - - bool SetSendCodecs(const std::vector& codecs); - bool SetRecvCodecs(const std::vector& codecs); - - // Creates the socket and connects. Sets sending_ to true. - bool Connect(); - // Closes the socket. Sets sending_ to false. - void Disconnect(); - - // Returns false when openning the socket failed; when successfull sets - // sending_ to true - bool OpenSctpSocket(); - // Sets sending_ to false and sock_ to NULL. - void CloseSctpSocket(); - - // Sends a SCTP_RESET_STREAM for all streams in closing_ssids_. - bool SendQueuedStreamResets(); - - // Adds a stream. - bool AddStream(const StreamParams &sp); - // Queues a stream for reset. - bool ResetStream(uint32_t ssrc); - - // Called by OnMessage to send packet on the network. - void OnPacketFromSctpToNetwork(rtc::CopyOnWriteBuffer* buffer); - // Called by OnMessage to decide what to do with the packet. - void OnInboundPacketFromSctpToChannel(SctpInboundPacket* packet); - void OnDataFromSctpToChannel(const ReceiveDataParams& params, - const rtc::CopyOnWriteBuffer& buffer); - void OnNotificationFromSctp(const rtc::CopyOnWriteBuffer& buffer); - void OnNotificationAssocChange(const sctp_assoc_change& change); - - void OnStreamResetEvent(const struct sctp_stream_reset_event* evt); - - // Responsible for marshalling incoming data to the channels listeners, and - // outgoing data to the network interface. - rtc::Thread* worker_thread_; - // The local and remote SCTP port to use. These are passed along the wire - // and the listener and connector must be using the same port. It is not - // related to the ports at the IP level. If set to -1, we default to - // kSctpDefaultPort. - int local_port_; - int remote_port_; - struct socket* sock_; // The socket created by usrsctp_socket(...). - - // sending_ is true iff there is a connected socket. - bool sending_; - // receiving_ controls whether inbound packets are thrown away. - bool receiving_; - - // When a data channel opens a stream, it goes into open_streams_. When we - // want to close it, the stream's ID goes into queued_reset_streams_. When - // we actually transmit a RE-CONFIG chunk with that stream ID, the ID goes - // into sent_reset_streams_. When we get a response RE-CONFIG chunk back - // acknowledging the reset, we remove the stream ID from - // sent_reset_streams_. We use sent_reset_streams_ to differentiate - // between acknowledgment RE-CONFIG and peer-initiated RE-CONFIGs. - StreamSet open_streams_; - StreamSet queued_reset_streams_; - StreamSet sent_reset_streams_; - - // A static human-readable name for debugging messages. - const char* debug_name_; -}; - -} // namespace cricket - -#endif // WEBRTC_MEDIA_SCTP_SCTPDATAENGINE_H_ diff --git a/include/webrtc/media/sctp/sctptransport.h b/include/webrtc/media/sctp/sctptransport.h new file mode 100644 index 0000000..b34db80 --- /dev/null +++ b/include/webrtc/media/sctp/sctptransport.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_SCTP_SCTPTRANSPORT_H_ +#define WEBRTC_MEDIA_SCTP_SCTPTRANSPORT_H_ + +#include + +#include // for unique_ptr. +#include +#include +#include + +#include "webrtc/base/asyncinvoker.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/copyonwritebuffer.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/thread.h" +// For SendDataParams/ReceiveDataParams. +#include "webrtc/media/base/mediachannel.h" +#include "webrtc/media/sctp/sctptransportinternal.h" + +// Defined by "usrsctplib/usrsctp.h" +struct sockaddr_conn; +struct sctp_assoc_change; +struct sctp_stream_reset_event; +// Defined by +struct socket; +namespace cricket { + +// Holds data to be passed on to a channel. +struct SctpInboundPacket; + +// From channel calls, data flows like this: +// [network thread (although it can in princple be another thread)] +// 1. SctpTransport::SendData(data) +// 2. usrsctp_sendv(data) +// [network thread returns; sctp thread then calls the following] +// 3. OnSctpOutboundPacket(wrapped_data) +// [sctp thread returns having async invoked on the network thread] +// 4. SctpTransport::OnPacketFromSctpToNetwork(wrapped_data) +// 5. TransportChannel::SendPacket(wrapped_data) +// 6. ... across network ... a packet is sent back ... +// 7. SctpTransport::OnPacketReceived(wrapped_data) +// 8. usrsctp_conninput(wrapped_data) +// [network thread returns; sctp thread then calls the following] +// 9. OnSctpInboundData(data) +// [sctp thread returns having async invoked on the network thread] +// 10. SctpTransport::OnInboundPacketFromSctpToChannel(inboundpacket) +// 11. SctpTransport::OnDataFromSctpToChannel(data) +// 12. SctpTransport::SignalDataReceived(data) +// [from the same thread, methods registered/connected to +// SctpTransport are called with the recieved data] +// TODO(zhihuang): Rename "channel" to "transport" on network-level. +class SctpTransport : public SctpTransportInternal, + public sigslot::has_slots<> { + public: + // |network_thread| is where packets will be processed and callbacks from + // this transport will be posted, and is the only thread on which public + // methods can be called. + // |channel| is required (must not be null). + SctpTransport(rtc::Thread* network_thread, + rtc::PacketTransportInternal* channel); + ~SctpTransport() override; + + // SctpTransportInternal overrides (see sctptransportinternal.h for comments). + void SetTransportChannel(rtc::PacketTransportInternal* channel) override; + bool Start(int local_port, int remote_port) override; + bool OpenStream(int sid) override; + bool ResetStream(int sid) override; + bool SendData(const SendDataParams& params, + const rtc::CopyOnWriteBuffer& payload, + SendDataResult* result = nullptr) override; + bool ReadyToSendData() override; + void set_debug_name_for_testing(const char* debug_name) override { + debug_name_ = debug_name; + } + + // Exposed to allow Post call from c-callbacks. + // TODO(deadbeef): Remove this or at least make it return a const pointer. + rtc::Thread* network_thread() const { return network_thread_; } + + private: + void ConnectTransportChannelSignals(); + void DisconnectTransportChannelSignals(); + + // Creates the socket and connects. + bool Connect(); + + // Returns false when opening the socket failed. + bool OpenSctpSocket(); + // Helpet method to set socket options. + bool ConfigureSctpSocket(); + // Sets |sock_ |to nullptr. + void CloseSctpSocket(); + + // Sends a SCTP_RESET_STREAM for all streams in closing_ssids_. + bool SendQueuedStreamResets(); + + // Sets the "ready to send" flag and fires signal if needed. + void SetReadyToSendData(); + + // Callbacks from DTLS channel. + void OnWritableState(rtc::PacketTransportInternal* transport); + virtual void OnPacketRead(rtc::PacketTransportInternal* transport, + const char* data, + size_t len, + const rtc::PacketTime& packet_time, + int flags); + + // Methods related to usrsctp callbacks. + void OnSendThresholdCallback(); + sockaddr_conn GetSctpSockAddr(int port); + + // Called using |invoker_| to send packet on the network. + void OnPacketFromSctpToNetwork(const rtc::CopyOnWriteBuffer& buffer); + // Called using |invoker_| to decide what to do with the packet. + // The |flags| parameter is used by SCTP to distinguish notification packets + // from other types of packets. + void OnInboundPacketFromSctpToChannel(const rtc::CopyOnWriteBuffer& buffer, + ReceiveDataParams params, + int flags); + void OnDataFromSctpToChannel(const ReceiveDataParams& params, + const rtc::CopyOnWriteBuffer& buffer); + void OnNotificationFromSctp(const rtc::CopyOnWriteBuffer& buffer); + void OnNotificationAssocChange(const sctp_assoc_change& change); + + void OnStreamResetEvent(const struct sctp_stream_reset_event* evt); + + // Responsible for marshalling incoming data to the channels listeners, and + // outgoing data to the network interface. + rtc::Thread* network_thread_; + // Helps pass inbound/outbound packets asynchronously to the network thread. + rtc::AsyncInvoker invoker_; + // Underlying DTLS channel. + rtc::PacketTransportInternal* transport_channel_; + bool was_ever_writable_ = false; + int local_port_ = kSctpDefaultPort; + int remote_port_ = kSctpDefaultPort; + struct socket* sock_ = nullptr; // The socket created by usrsctp_socket(...). + + // Has Start been called? Don't create SCTP socket until it has. + bool started_ = false; + // Are we ready to queue data (SCTP socket created, and not blocked due to + // congestion control)? Different than |transport_channel_|'s "ready to + // send". + bool ready_to_send_data_ = false; + + typedef std::set StreamSet; + // When a data channel opens a stream, it goes into open_streams_. When we + // want to close it, the stream's ID goes into queued_reset_streams_. When + // we actually transmit a RE-CONFIG chunk with that stream ID, the ID goes + // into sent_reset_streams_. When we get a response RE-CONFIG chunk back + // acknowledging the reset, we remove the stream ID from + // sent_reset_streams_. We use sent_reset_streams_ to differentiate + // between acknowledgment RE-CONFIG and peer-initiated RE-CONFIGs. + StreamSet open_streams_; + StreamSet queued_reset_streams_; + StreamSet sent_reset_streams_; + + // A static human-readable name for debugging messages. + const char* debug_name_ = "SctpTransport"; + // Hides usrsctp interactions from this header file. + class UsrSctpWrapper; + + RTC_DISALLOW_COPY_AND_ASSIGN(SctpTransport); +}; + +class SctpTransportFactory : public SctpTransportInternalFactory { + public: + explicit SctpTransportFactory(rtc::Thread* network_thread) + : network_thread_(network_thread) {} + + std::unique_ptr CreateSctpTransport( + rtc::PacketTransportInternal* channel) override { + return std::unique_ptr( + new SctpTransport(network_thread_, channel)); + } + + private: + rtc::Thread* network_thread_; +}; + +} // namespace cricket + +#endif // WEBRTC_MEDIA_SCTP_SCTPTRANSPORT_H_ diff --git a/include/webrtc/media/sctp/sctptransportinternal.h b/include/webrtc/media/sctp/sctptransportinternal.h new file mode 100644 index 0000000..e0f44e5 --- /dev/null +++ b/include/webrtc/media/sctp/sctptransportinternal.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MEDIA_SCTP_SCTPTRANSPORTINTERNAL_H_ +#define WEBRTC_MEDIA_SCTP_SCTPTRANSPORTINTERNAL_H_ + +// TODO(deadbeef): Move SCTP code out of media/, and make it not depend on +// anything in media/. + +#include // for unique_ptr +#include +#include + +#include "webrtc/base/copyonwritebuffer.h" +#include "webrtc/base/thread.h" +// For SendDataParams/ReceiveDataParams. +// TODO(deadbeef): Use something else for SCTP. It's confusing that we use an +// SSRC field for SID. +#include "webrtc/media/base/mediachannel.h" +#include "webrtc/p2p/base/packettransportinternal.h" + +namespace cricket { + +// The number of outgoing streams that we'll negotiate. Since stream IDs (SIDs) +// are 0-based, the highest usable SID is 1023. +// +// It's recommended to use the maximum of 65535 in: +// https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.2 +// However, we use 1024 in order to save memory. usrsctp allocates 104 bytes +// for each pair of incoming/outgoing streams (on a 64-bit system), so 65535 +// streams would waste ~6MB. +// +// Note: "max" and "min" here are inclusive. +constexpr uint16_t kMaxSctpStreams = 1024; +constexpr uint16_t kMaxSctpSid = kMaxSctpStreams - 1; +constexpr uint16_t kMinSctpSid = 0; + +// This is the default SCTP port to use. It is passed along the wire and the +// connectee and connector must be using the same port. It is not related to the +// ports at the IP level. (Corresponds to: sockaddr_conn.sconn_port in +// usrsctp.h) +const int kSctpDefaultPort = 5000; + +// Abstract SctpTransport interface for use internally (by +// PeerConnection/WebRtcSession/etc.). Exists to allow mock/fake SctpTransports +// to be created. +class SctpTransportInternal { + public: + virtual ~SctpTransportInternal() {} + + // Changes what underlying DTLS channel is uses. Used when switching which + // bundled transport the SctpTransport uses. + // Assumes |channel| is non-null. + virtual void SetTransportChannel(rtc::PacketTransportInternal* channel) = 0; + + // When Start is called, connects as soon as possible; this can be called + // before DTLS completes, in which case the connection will begin when DTLS + // completes. This method can be called multiple times, though not if either + // of the ports are changed. + // + // |local_sctp_port| and |remote_sctp_port| are passed along the wire and the + // listener and connector must be using the same port. They are not related + // to the ports at the IP level. If set to -1, we default to + // kSctpDefaultPort. + // + // TODO(deadbeef): Add remote max message size as parameter to Start, once we + // start supporting it. + // TODO(deadbeef): Support calling Start with different local/remote ports + // and create a new association? Not clear if this is something we need to + // support though. See: https://github.com/w3c/webrtc-pc/issues/979 + virtual bool Start(int local_sctp_port, int remote_sctp_port) = 0; + + // NOTE: Initially there was a "Stop" method here, but it was never used, so + // it was removed. + + // Informs SctpTransport that |sid| will start being used. Returns false if + // it is impossible to use |sid|, or if it's already in use. + // Until calling this, can't send data using |sid|. + // TODO(deadbeef): Actually implement the "returns false if |sid| can't be + // used" part. See: + // https://bugs.chromium.org/p/chromium/issues/detail?id=619849 + virtual bool OpenStream(int sid) = 0; + // The inverse of OpenStream. When this method returns, the reset process may + // have not finished but it will have begun. + // TODO(deadbeef): We need a way to tell when it's done. See: + // https://bugs.chromium.org/p/webrtc/issues/detail?id=4453 + virtual bool ResetStream(int sid) = 0; + // Send data down this channel (will be wrapped as SCTP packets then given to + // usrsctp that will then post the network interface). + // Returns true iff successful data somewhere on the send-queue/network. + // Uses |params.ssrc| as the SCTP sid. + virtual bool SendData(const SendDataParams& params, + const rtc::CopyOnWriteBuffer& payload, + SendDataResult* result = nullptr) = 0; + + // Indicates when the SCTP socket is created and not blocked by congestion + // control. This changes to false when SDR_BLOCK is returned from SendData, + // and + // changes to true when SignalReadyToSendData is fired. The underlying DTLS/ + // ICE channels may be unwritable while ReadyToSendData is true, because data + // can still be queued in usrsctp. + virtual bool ReadyToSendData() = 0; + + sigslot::signal0<> SignalReadyToSendData; + // ReceiveDataParams includes SID, seq num, timestamp, etc. CopyOnWriteBuffer + // contains message payload. + sigslot::signal2 + SignalDataReceived; + // Parameter is SID of closed stream. + sigslot::signal1 SignalStreamClosedRemotely; + + // Helper for debugging. + virtual void set_debug_name_for_testing(const char* debug_name) = 0; +}; + +// Factory class which can be used to allow fake SctpTransports to be injected +// for testing. Or, theoretically, SctpTransportInternal implementations that +// use something other than usrsctp. +class SctpTransportInternalFactory { + public: + virtual ~SctpTransportInternalFactory() {} + + // Create an SCTP transport using |channel| for the underlying transport. + virtual std::unique_ptr CreateSctpTransport( + rtc::PacketTransportInternal* channel) = 0; +}; + +} // namespace cricket + +#endif // WEBRTC_MEDIA_SCTP_SCTPTRANSPORTINTERNAL_H_ diff --git a/include/webrtc/modules/audio_coding/acm2/acm_codec_database.h b/include/webrtc/modules/audio_coding/acm2/acm_codec_database.h index 6c2db9c..22c40db 100644 --- a/include/webrtc/modules/audio_coding/acm2/acm_codec_database.h +++ b/include/webrtc/modules/audio_coding/acm2/acm_codec_database.h @@ -17,9 +17,9 @@ #define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_ #include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" +#include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/acm2/acm_common_defs.h b/include/webrtc/modules/audio_coding/acm2/acm_common_defs.h index 483bdd9..0851932 100644 --- a/include/webrtc/modules/audio_coding/acm2/acm_common_defs.h +++ b/include/webrtc/modules/audio_coding/acm2/acm_common_defs.h @@ -11,7 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_COMMON_DEFS_H_ #define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_COMMON_DEFS_H_ -#include "webrtc/engine_configurations.h" +#include "webrtc/typedefs.h" // Checks for enabled codecs, we prevent enabling codecs which are not // compatible. diff --git a/include/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h b/include/webrtc/modules/audio_coding/acm2/acm_receive_test.h similarity index 81% rename from include/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h rename to include/webrtc/modules/audio_coding/acm2/acm_receive_test.h index 6952641..1076978 100644 --- a/include/webrtc/modules/audio_coding/acm2/acm_receive_test_oldapi.h +++ b/include/webrtc/modules/audio_coding/acm2/acm_receive_test.h @@ -8,13 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_OLDAPI_H_ -#define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_OLDAPI_H_ +#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_H_ #include #include +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/system_wrappers/include/clock.h" namespace webrtc { @@ -37,8 +39,9 @@ class AcmReceiveTestOldApi { AcmReceiveTestOldApi(PacketSource* packet_source, AudioSink* audio_sink, int output_freq_hz, - NumOutputChannels exptected_output_channels); - virtual ~AcmReceiveTestOldApi() {} + NumOutputChannels exptected_output_channels, + rtc::scoped_refptr decoder_factory); + virtual ~AcmReceiveTestOldApi(); // Registers the codecs with default parameters from ACM. void RegisterDefaultCodecs(); @@ -47,15 +50,11 @@ class AcmReceiveTestOldApi { // files. void RegisterNetEqTestCodecs(); - int RegisterExternalReceiveCodec(int rtp_payload_type, - AudioDecoder* external_decoder, - int sample_rate_hz, - int num_channels, - const std::string& name); - // Runs the test and returns true if successful. void Run(); + AudioCodingModule* get_acm() { return acm_.get(); } + protected: // Method is called after each block of output audio is received from ACM. virtual void AfterGetAudio() {} @@ -94,4 +93,4 @@ class AcmReceiveTestToggleOutputFreqOldApi : public AcmReceiveTestOldApi { } // namespace test } // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_OLDAPI_H_ +#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_RECEIVE_TEST_H_ diff --git a/include/webrtc/modules/audio_coding/acm2/acm_receiver.h b/include/webrtc/modules/audio_coding/acm2/acm_receiver.h index f37212c..63ed43d 100644 --- a/include/webrtc/modules/audio_coding/acm2/acm_receiver.h +++ b/include/webrtc/modules/audio_coding/acm2/acm_receiver.h @@ -21,10 +21,8 @@ #include "webrtc/base/optional.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_audio/vad/include/webrtc_vad.h" -#include "webrtc/engine_configurations.h" #include "webrtc/modules/audio_coding/acm2/acm_resampler.h" #include "webrtc/modules/audio_coding/acm2/call_statistics.h" -#include "webrtc/modules/audio_coding/acm2/initial_delay_manager.h" #include "webrtc/modules/audio_coding/include/audio_coding_module.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/include/module_common_types.h" @@ -39,15 +37,6 @@ namespace acm2 { class AcmReceiver { public: - struct Decoder { - int acm_codec_id; - uint8_t payload_type; - // This field is meaningful for codecs where both mono and - // stereo versions are registered under the same ID. - size_t channels; - int sample_rate_hz; - }; - // Constructor of the class explicit AcmReceiver(const AudioCodingModule::Config& config); @@ -123,6 +112,10 @@ class AcmReceiver { AudioDecoder* audio_decoder, const std::string& name); + // Adds a new decoder to the NetEq codec database. Returns true iff + // successful. + bool AddCodec(int rtp_payload_type, const SdpAudioFormat& audio_format); + // // Sets a minimum delay for packet buffer. The given delay is maintained, // unless channel condition dictates a higher delay. @@ -195,12 +188,19 @@ class AcmReceiver { // // Remove all registered codecs. // - int RemoveAllCodecs(); + void RemoveAllCodecs(); // Returns the RTP timestamp for the last sample delivered by GetAudio(). // The return value will be empty if no valid timestamp is available. rtc::Optional GetPlayoutTimestamp(); + // Returns the current total delay from NetEq (packet buffer and sync buffer) + // in ms, with smoothing applied to even out short-time fluctuations due to + // jitter. The packet buffer part of the delay is not updated during DTX/CNG + // periods. + // + int FilteredCurrentDelayMs() const; + // // Get the audio codec associated with the last non-CNG/non-DTMF received // payload. If no non-CNG/non-DTMF packet is received -1 is returned, @@ -208,6 +208,8 @@ class AcmReceiver { // int LastAudioCodec(CodecInst* codec) const; + rtc::Optional LastAudioFormat() const; + // // Get a decoder given its registered payload-type. // @@ -255,20 +257,28 @@ class AcmReceiver { void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const; private: - const Decoder* RtpHeaderToDecoder(const RTPHeader& rtp_header, - uint8_t payload_type) const - EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + struct Decoder { + int acm_codec_id; + uint8_t payload_type; + // This field is meaningful for codecs where both mono and + // stereo versions are registered under the same ID. + size_t channels; + int sample_rate_hz; + }; + + const rtc::Optional RtpHeaderToDecoder( + const RTPHeader& rtp_header, + uint8_t first_payload_byte) const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); uint32_t NowInTimestamp(int decoder_sampling_rate) const; rtc::CriticalSection crit_sect_; - const Decoder* last_audio_decoder_ GUARDED_BY(crit_sect_); + rtc::Optional last_audio_decoder_ GUARDED_BY(crit_sect_); + rtc::Optional last_audio_format_ GUARDED_BY(crit_sect_); ACMResampler resampler_ GUARDED_BY(crit_sect_); std::unique_ptr last_audio_buffer_ GUARDED_BY(crit_sect_); CallStatistics call_stats_ GUARDED_BY(crit_sect_); NetEq* neteq_; - // Decoders map is keyed by payload type - std::map decoders_ GUARDED_BY(crit_sect_); Clock* clock_; // TODO(henrik.lundin) Make const if possible. bool resampled_last_output_frame_ GUARDED_BY(crit_sect_); rtc::Optional last_packet_sample_rate_hz_ GUARDED_BY(crit_sect_); diff --git a/include/webrtc/modules/audio_coding/acm2/acm_send_test_oldapi.h b/include/webrtc/modules/audio_coding/acm2/acm_send_test.h similarity index 82% rename from include/webrtc/modules/audio_coding/acm2/acm_send_test_oldapi.h rename to include/webrtc/modules/audio_coding/acm2/acm_send_test.h index 938e39e..96531a3 100644 --- a/include/webrtc/modules/audio_coding/acm2/acm_send_test_oldapi.h +++ b/include/webrtc/modules/audio_coding/acm2/acm_send_test.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_OLDAPI_H_ -#define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_OLDAPI_H_ +#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_H_ #include #include @@ -32,7 +32,7 @@ class AcmSendTestOldApi : public AudioPacketizationCallback, AcmSendTestOldApi(InputAudioFile* audio_source, int source_rate_hz, int test_duration_ms); - virtual ~AcmSendTestOldApi() {} + ~AcmSendTestOldApi() override; // Registers the send codec. Returns true on success, false otherwise. bool RegisterCodec(const char* payload_name, @@ -44,10 +44,8 @@ class AcmSendTestOldApi : public AudioPacketizationCallback, // Registers an external send codec. Returns true on success, false otherwise. bool RegisterExternalCodec(AudioEncoder* external_speech_encoder); - // Returns the next encoded packet. Returns NULL if the test duration was - // exceeded. Ownership of the packet is handed over to the caller. // Inherited from PacketSource. - Packet* NextPacket() override; + std::unique_ptr NextPacket() override; // Inherited from AudioPacketizationCallback. int32_t SendData(FrameType frame_type, @@ -63,9 +61,8 @@ class AcmSendTestOldApi : public AudioPacketizationCallback, static const int kBlockSizeMs = 10; // Creates a Packet object from the last packet produced by ACM (and received - // through the SendData method as a callback). Ownership of the new Packet - // object is transferred to the caller. - Packet* CreatePacket(); + // through the SendData method as a callback). + std::unique_ptr CreatePacket(); SimulatedClock clock_; std::unique_ptr acm_; @@ -88,4 +85,4 @@ class AcmSendTestOldApi : public AudioPacketizationCallback, } // namespace test } // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_OLDAPI_H_ +#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_ACM_SEND_TEST_H_ diff --git a/include/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h b/include/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h deleted file mode 100644 index c098e62..0000000 --- a/include/webrtc/modules/audio_coding/acm2/audio_coding_module_impl.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_ -#define WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_ - -#include -#include -#include - -#include "webrtc/base/buffer.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/thread_annotations.h" -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/modules/audio_coding/acm2/acm_receiver.h" -#include "webrtc/modules/audio_coding/acm2/acm_resampler.h" -#include "webrtc/modules/audio_coding/acm2/codec_manager.h" -#include "webrtc/modules/audio_coding/codecs/audio_encoder.h" - -namespace webrtc { - -class AudioCodingImpl; - -namespace acm2 { - -struct EncoderFactory; - -class AudioCodingModuleImpl final : public AudioCodingModule { - public: - friend webrtc::AudioCodingImpl; - - explicit AudioCodingModuleImpl(const AudioCodingModule::Config& config); - ~AudioCodingModuleImpl() override; - - ///////////////////////////////////////// - // Sender - // - - // Can be called multiple times for Codec, CNG, RED. - int RegisterSendCodec(const CodecInst& send_codec) override; - - void RegisterExternalSendCodec( - AudioEncoder* external_speech_encoder) override; - - void ModifyEncoder( - FunctionView*)> modifier) override; - - // Get current send codec. - rtc::Optional SendCodec() const override; - - // Get current send frequency. - int SendFrequency() const override; - - // Sets the bitrate to the specified value in bits/sec. In case the codec does - // not support the requested value it will choose an appropriate value - // instead. - void SetBitRate(int bitrate_bps) override; - - // Register a transport callback which will be - // called to deliver the encoded buffers. - int RegisterTransportCallback(AudioPacketizationCallback* transport) override; - - // Add 10 ms of raw (PCM) audio data to the encoder. - int Add10MsData(const AudioFrame& audio_frame) override; - - ///////////////////////////////////////// - // (RED) Redundant Coding - // - - // Configure RED status i.e. on/off. - int SetREDStatus(bool enable_red) override; - - // Get RED status. - bool REDStatus() const override; - - ///////////////////////////////////////// - // (FEC) Forward Error Correction (codec internal) - // - - // Configure FEC status i.e. on/off. - int SetCodecFEC(bool enabled_codec_fec) override; - - // Get FEC status. - bool CodecFEC() const override; - - // Set target packet loss rate - int SetPacketLossRate(int loss_rate) override; - - ///////////////////////////////////////// - // (VAD) Voice Activity Detection - // and - // (CNG) Comfort Noise Generation - // - - int SetVAD(bool enable_dtx = true, - bool enable_vad = false, - ACMVADMode mode = VADNormal) override; - - int VAD(bool* dtx_enabled, - bool* vad_enabled, - ACMVADMode* mode) const override; - - int RegisterVADCallback(ACMVADCallback* vad_callback) override; - - ///////////////////////////////////////// - // Receiver - // - - // Initialize receiver, resets codec database etc. - int InitializeReceiver() override; - - // Get current receive frequency. - int ReceiveFrequency() const override; - - // Get current playout frequency. - int PlayoutFrequency() const override; - - int RegisterReceiveCodec(const CodecInst& receive_codec) override; - int RegisterReceiveCodec( - const CodecInst& receive_codec, - FunctionView()> isac_factory) override; - - int RegisterExternalReceiveCodec(int rtp_payload_type, - AudioDecoder* external_decoder, - int sample_rate_hz, - int num_channels, - const std::string& name) override; - - // Get current received codec. - int ReceiveCodec(CodecInst* current_codec) const override; - - // Incoming packet from network parsed and ready for decode. - int IncomingPacket(const uint8_t* incoming_payload, - const size_t payload_length, - const WebRtcRTPHeader& rtp_info) override; - - // Incoming payloads, without rtp-info, the rtp-info will be created in ACM. - // One usage for this API is when pre-encoded files are pushed in ACM. - int IncomingPayload(const uint8_t* incoming_payload, - const size_t payload_length, - uint8_t payload_type, - uint32_t timestamp) override; - - // Minimum playout delay. - int SetMinimumPlayoutDelay(int time_ms) override; - - // Maximum playout delay. - int SetMaximumPlayoutDelay(int time_ms) override; - - // Smallest latency NetEq will maintain. - int LeastRequiredDelayMs() const override; - - RTC_DEPRECATED int32_t PlayoutTimestamp(uint32_t* timestamp) override; - - rtc::Optional PlayoutTimestamp() override; - - // Get 10 milliseconds of raw audio data to play out, and - // automatic resample to the requested frequency if > 0. - int PlayoutData10Ms(int desired_freq_hz, - AudioFrame* audio_frame, - bool* muted) override; - int PlayoutData10Ms(int desired_freq_hz, AudioFrame* audio_frame) override; - - ///////////////////////////////////////// - // Statistics - // - - int GetNetworkStatistics(NetworkStatistics* statistics) override; - - int SetOpusApplication(OpusApplicationMode application) override; - - // If current send codec is Opus, informs it about the maximum playback rate - // the receiver will render. - int SetOpusMaxPlaybackRate(int frequency_hz) override; - - int EnableOpusDtx() override; - - int DisableOpusDtx() override; - - int UnregisterReceiveCodec(uint8_t payload_type) override; - - int EnableNack(size_t max_nack_list_size) override; - - void DisableNack() override; - - std::vector GetNackList(int64_t round_trip_time_ms) const override; - - void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const override; - - private: - struct InputData { - uint32_t input_timestamp; - const int16_t* audio; - size_t length_per_channel; - size_t audio_channel; - // If a re-mix is required (up or down), this buffer will store a re-mixed - // version of the input. - int16_t buffer[WEBRTC_10MS_PCM_AUDIO]; - }; - - // This member class writes values to the named UMA histogram, but only if - // the value has changed since the last time (and always for the first call). - class ChangeLogger { - public: - explicit ChangeLogger(const std::string& histogram_name) - : histogram_name_(histogram_name) {} - // Logs the new value if it is different from the last logged value, or if - // this is the first call. - void MaybeLog(int value); - - private: - int last_value_ = 0; - int first_time_ = true; - const std::string histogram_name_; - }; - - int RegisterReceiveCodecUnlocked( - const CodecInst& codec, - FunctionView()> isac_factory) - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - - int Add10MsDataInternal(const AudioFrame& audio_frame, InputData* input_data) - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - int Encode(const InputData& input_data) - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - - int InitializeReceiverSafe() EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - - bool HaveValidEncoder(const char* caller_name) const - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - - // Preprocessing of input audio, including resampling and down-mixing if - // required, before pushing audio into encoder's buffer. - // - // in_frame: input audio-frame - // ptr_out: pointer to output audio_frame. If no preprocessing is required - // |ptr_out| will be pointing to |in_frame|, otherwise pointing to - // |preprocess_frame_|. - // - // Return value: - // -1: if encountering an error. - // 0: otherwise. - int PreprocessToAddData(const AudioFrame& in_frame, - const AudioFrame** ptr_out) - EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_); - - // Change required states after starting to receive the codec corresponding - // to |index|. - int UpdateUponReceivingCodec(int index); - - rtc::CriticalSection acm_crit_sect_; - rtc::Buffer encode_buffer_ GUARDED_BY(acm_crit_sect_); - int id_; // TODO(henrik.lundin) Make const. - uint32_t expected_codec_ts_ GUARDED_BY(acm_crit_sect_); - uint32_t expected_in_ts_ GUARDED_BY(acm_crit_sect_); - ACMResampler resampler_ GUARDED_BY(acm_crit_sect_); - AcmReceiver receiver_; // AcmReceiver has it's own internal lock. - ChangeLogger bitrate_logger_ GUARDED_BY(acm_crit_sect_); - - std::unique_ptr encoder_factory_ GUARDED_BY(acm_crit_sect_); - - // Current encoder stack, either obtained from - // encoder_factory_->rent_a_codec.RentEncoderStack or provided by a call to - // RegisterEncoder. - std::unique_ptr encoder_stack_ GUARDED_BY(acm_crit_sect_); - - std::unique_ptr isac_decoder_16k_ GUARDED_BY(acm_crit_sect_); - std::unique_ptr isac_decoder_32k_ GUARDED_BY(acm_crit_sect_); - - // This is to keep track of CN instances where we can send DTMFs. - uint8_t previous_pltype_ GUARDED_BY(acm_crit_sect_); - - // Used when payloads are pushed into ACM without any RTP info - // One example is when pre-encoded bit-stream is pushed from - // a file. - // IMPORTANT: this variable is only used in IncomingPayload(), therefore, - // no lock acquired when interacting with this variable. If it is going to - // be used in other methods, locks need to be taken. - std::unique_ptr aux_rtp_header_; - - bool receiver_initialized_ GUARDED_BY(acm_crit_sect_); - - AudioFrame preprocess_frame_ GUARDED_BY(acm_crit_sect_); - bool first_10ms_data_ GUARDED_BY(acm_crit_sect_); - - bool first_frame_ GUARDED_BY(acm_crit_sect_); - uint32_t last_timestamp_ GUARDED_BY(acm_crit_sect_); - uint32_t last_rtp_timestamp_ GUARDED_BY(acm_crit_sect_); - - rtc::CriticalSection callback_crit_sect_; - AudioPacketizationCallback* packetization_callback_ - GUARDED_BY(callback_crit_sect_); - ACMVADCallback* vad_callback_ GUARDED_BY(callback_crit_sect_); - - int codec_histogram_bins_log_[static_cast( - AudioEncoder::CodecType::kMaxLoggedAudioCodecTypes)]; - int number_of_consecutive_empty_packets_; -}; - -} // namespace acm2 -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_AUDIO_CODING_MODULE_IMPL_H_ diff --git a/include/webrtc/modules/audio_coding/acm2/call_statistics.h b/include/webrtc/modules/audio_coding/acm2/call_statistics.h index 888afea..3993319 100644 --- a/include/webrtc/modules/audio_coding/acm2/call_statistics.h +++ b/include/webrtc/modules/audio_coding/acm2/call_statistics.h @@ -37,8 +37,9 @@ class CallStatistics { ~CallStatistics() {} // Call this method to indicate that NetEq engaged in decoding. |speech_type| - // is the audio-type according to NetEq. - void DecodedByNetEq(AudioFrame::SpeechType speech_type); + // is the audio-type according to NetEq, and |muted| indicates if the decoded + // frame was produced in muted state. + void DecodedByNetEq(AudioFrame::SpeechType speech_type, bool muted); // Call this method to indicate that a decoding call resulted in generating // silence, i.e. call to NetEq is bypassed and the output audio is zero. diff --git a/include/webrtc/modules/audio_coding/acm2/codec_manager.h b/include/webrtc/modules/audio_coding/acm2/codec_manager.h index f6c6cd4..b60b7e7 100644 --- a/include/webrtc/modules/audio_coding/acm2/codec_manager.h +++ b/include/webrtc/modules/audio_coding/acm2/codec_manager.h @@ -59,31 +59,13 @@ class CodecManager final { // Uses the provided Rent-A-Codec to create a new encoder stack, if we have a // complete specification; if so, it is then passed to set_encoder. On error, // returns false. - bool MakeEncoder(RentACodec* rac, AudioCodingModule* acm) { - RTC_DCHECK(rac); - RTC_DCHECK(acm); - if (!codec_stack_params_.speech_encoder && send_codec_inst_) { - // We have no speech encoder, but we have a specification for making one. - auto enc = rac->RentEncoder(*send_codec_inst_); - if (!enc) - return false; - codec_stack_params_.speech_encoder = std::move(enc); - } - auto stack = rac->RentEncoderStack(&codec_stack_params_); - if (stack) { - // Give new encoder stack to the ACM. - acm->SetEncoder(std::move(stack)); - } else { - // The specification was good but incomplete, so we have no encoder stack - // to give to the ACM. - } - return true; - } + bool MakeEncoder(RentACodec* rac, AudioCodingModule* acm); private: rtc::ThreadChecker thread_checker_; rtc::Optional send_codec_inst_; RentACodec::StackParameters codec_stack_params_; + bool recreate_encoder_ = true; // Need to recreate encoder? RTC_DISALLOW_COPY_AND_ASSIGN(CodecManager); }; diff --git a/include/webrtc/modules/audio_coding/acm2/initial_delay_manager.h b/include/webrtc/modules/audio_coding/acm2/initial_delay_manager.h deleted file mode 100644 index a73141a..0000000 --- a/include/webrtc/modules/audio_coding/acm2/initial_delay_manager.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_ -#define WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_ - -#include "webrtc/modules/include/module_common_types.h" - -namespace webrtc { - -namespace acm2 { - -class InitialDelayManager { - public: - enum PacketType { - kUndefinedPacket, kCngPacket, kAvtPacket, kAudioPacket, kSyncPacket }; - - // Specifies a stream of sync-packets. - struct SyncStream { - SyncStream() - : num_sync_packets(0), - receive_timestamp(0), - timestamp_step(0) { - memset(&rtp_info, 0, sizeof(rtp_info)); - } - - int num_sync_packets; - - // RTP header of the first sync-packet in the sequence. - WebRtcRTPHeader rtp_info; - - // Received timestamp of the first sync-packet in the sequence. - uint32_t receive_timestamp; - - // Samples per packet. - uint32_t timestamp_step; - }; - - InitialDelayManager(int initial_delay_ms, int late_packet_threshold); - - // Update with the last received RTP header, |header|, and received timestamp, - // |received_timestamp|. |type| indicates the packet type. If codec is changed - // since the last time |new_codec| should be true. |sample_rate_hz| is the - // decoder's sampling rate in Hz. |header| has a field to store sampling rate - // but we are not sure if that is properly set at the send side, and |header| - // is declared constant in the caller of this function - // (AcmReceiver::InsertPacket()). |sync_stream| contains information required - // to generate a stream of sync packets. - void UpdateLastReceivedPacket(const WebRtcRTPHeader& header, - uint32_t receive_timestamp, - PacketType type, - bool new_codec, - int sample_rate_hz, - SyncStream* sync_stream); - - // Based on the last received timestamp and given the current timestamp, - // sequence of late (or perhaps missing) packets is computed. - void LatePackets(uint32_t timestamp_now, SyncStream* sync_stream); - - // Get playout timestamp. - // Returns true if the timestamp is valid (when buffering), otherwise false. - bool GetPlayoutTimestamp(uint32_t* playout_timestamp); - - // True if buffered audio is less than the given initial delay (specified at - // the constructor). Buffering might be disabled by the client of this class. - bool buffering() { return buffering_; } - - // Disable buffering in the class. - void DisableBuffering(); - - // True if any packet received for buffering. - bool PacketBuffered() { return last_packet_type_ != kUndefinedPacket; } - - private: - static const uint8_t kInvalidPayloadType = 0xFF; - - // Update playout timestamps. While buffering, this is about - // |initial_delay_ms| millisecond behind the latest received timestamp. - void UpdatePlayoutTimestamp(const RTPHeader& current_header, - int sample_rate_hz); - - // Record an RTP headr and related parameter - void RecordLastPacket(const WebRtcRTPHeader& rtp_info, - uint32_t receive_timestamp, - PacketType type); - - PacketType last_packet_type_; - WebRtcRTPHeader last_packet_rtp_info_; - uint32_t last_receive_timestamp_; - uint32_t timestamp_step_; - uint8_t audio_payload_type_; - const int initial_delay_ms_; - int buffered_audio_ms_; - bool buffering_; - - // During the initial phase where packets are being accumulated and silence - // is played out, |playout_ts| is a timestamp which is equal to - // |initial_delay_ms_| milliseconds earlier than the most recently received - // RTP timestamp. - uint32_t playout_timestamp_; - - // If the number of late packets exceed this value (computed based on current - // timestamp and last received timestamp), sequence of sync-packets is - // specified. - const int late_packet_threshold_; -}; - -} // namespace acm2 - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_INITIAL_DELAY_MANAGER_H_ diff --git a/include/webrtc/modules/audio_coding/acm2/rent_a_codec.h b/include/webrtc/modules/audio_coding/acm2/rent_a_codec.h index bac37af..069e1d5 100644 --- a/include/webrtc/modules/audio_coding/acm2/rent_a_codec.h +++ b/include/webrtc/modules/audio_coding/acm2/rent_a_codec.h @@ -15,12 +15,12 @@ #include #include +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/api/audio_codecs/audio_format.h" #include "webrtc/base/array_view.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/optional.h" #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" -#include "webrtc/modules/audio_coding/codecs/audio_format.h" #include "webrtc/modules/audio_coding/codecs/audio_encoder.h" #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" #include "webrtc/typedefs.h" @@ -72,6 +72,9 @@ class RentACodec { kCNFB, #endif kAVT, + kAVT16kHz, + kAVT32kHz, + kAVT48kHz, #ifdef WEBRTC_CODEC_RED kRED, #endif @@ -127,6 +130,9 @@ class RentACodec { kDecoderG722_2ch, kDecoderRED, kDecoderAVT, + kDecoderAVT16kHz, + kDecoderAVT32kHz, + kDecoderAVT48kHz, kDecoderCNGnb, kDecoderCNGwb, kDecoderCNGswb32kHz, @@ -220,7 +226,7 @@ class RentACodec { std::unique_ptr RentEncoderStack(StackParameters* param); // Creates and returns an iSAC decoder. - std::unique_ptr RentIsacDecoder(); + std::unique_ptr RentIsacDecoder(int sample_rate_hz); private: std::unique_ptr speech_encoder_; diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h new file mode 100644 index 0000000..82062ab --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_AUDIO_NETWORK_ADAPTOR_IMPL_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_AUDIO_NETWORK_ADAPTOR_IMPL_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { + +class RtcEventLog; + +class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor { + public: + struct Config { + Config(); + ~Config(); + RtcEventLog* event_log; + const Clock* clock; + }; + + AudioNetworkAdaptorImpl( + const Config& config, + std::unique_ptr controller_manager, + std::unique_ptr debug_dump_writer = nullptr); + + ~AudioNetworkAdaptorImpl() override; + + void SetUplinkBandwidth(int uplink_bandwidth_bps) override; + + void SetUplinkPacketLossFraction(float uplink_packet_loss_fraction) override; + + void SetRtt(int rtt_ms) override; + + void SetTargetAudioBitrate(int target_audio_bitrate_bps) override; + + void SetOverhead(size_t overhead_bytes_per_packet) override; + + EncoderRuntimeConfig GetEncoderRuntimeConfig() override; + + void StartDebugDump(FILE* file_handle) override; + + void StopDebugDump() override; + + private: + void DumpNetworkMetrics(); + + void UpdateNetworkMetrics(const Controller::NetworkMetrics& network_metrics); + + const Config config_; + + std::unique_ptr controller_manager_; + + std::unique_ptr debug_dump_writer_; + + const std::unique_ptr event_log_writer_; + + Controller::NetworkMetrics last_metrics_; + + RTC_DISALLOW_COPY_AND_ASSIGN(AudioNetworkAdaptorImpl); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_AUDIO_NETWORK_ADAPTOR_IMPL_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h new file mode 100644 index 0000000..5e03b45 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_BITRATE_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_BITRATE_CONTROLLER_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { +namespace audio_network_adaptor { + +class BitrateController final : public Controller { + public: + struct Config { + Config(int initial_bitrate_bps, int initial_frame_length_ms); + ~Config(); + int initial_bitrate_bps; + int initial_frame_length_ms; + }; + + explicit BitrateController(const Config& config); + + ~BitrateController() override; + + void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; + + void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override; + + private: + const Config config_; + int bitrate_bps_; + int frame_length_ms_; + rtc::Optional target_audio_bitrate_bps_; + rtc::Optional overhead_bytes_per_packet_; + RTC_DISALLOW_COPY_AND_ASSIGN(BitrateController); +}; + +} // namespace audio_network_adaptor +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_BITRATE_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/channel_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/channel_controller.h new file mode 100644 index 0000000..0bcb4fd --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/channel_controller.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CHANNEL_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CHANNEL_CONTROLLER_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { + +class ChannelController final : public Controller { + public: + struct Config { + Config(size_t num_encoder_channels, + size_t intial_channels_to_encode, + int channel_1_to_2_bandwidth_bps, + int channel_2_to_1_bandwidth_bps); + size_t num_encoder_channels; + size_t intial_channels_to_encode; + // Uplink bandwidth above which the number of encoded channels should switch + // from 1 to 2. + int channel_1_to_2_bandwidth_bps; + // Uplink bandwidth below which the number of encoded channels should switch + // from 2 to 1. + int channel_2_to_1_bandwidth_bps; + }; + + explicit ChannelController(const Config& config); + + ~ChannelController() override; + + void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; + + void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override; + + private: + const Config config_; + size_t channels_to_encode_; + rtc::Optional uplink_bandwidth_bps_; + RTC_DISALLOW_COPY_AND_ASSIGN(ChannelController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CHANNEL_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/controller.h new file mode 100644 index 0000000..7679a58 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/controller.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_H_ + +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" + +namespace webrtc { + +class Controller { + public: + struct NetworkMetrics { + NetworkMetrics(); + ~NetworkMetrics(); + rtc::Optional uplink_bandwidth_bps; + rtc::Optional uplink_packet_loss_fraction; + rtc::Optional target_audio_bitrate_bps; + rtc::Optional rtt_ms; + rtc::Optional overhead_bytes_per_packet; + }; + + virtual ~Controller() = default; + + // Informs network metrics update to this controller. Any non-empty field + // indicates an update on the corresponding network metric. + virtual void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) = 0; + + virtual void MakeDecision( + AudioNetworkAdaptor::EncoderRuntimeConfig* config) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h new file mode 100644 index 0000000..338a365 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_MANAGER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_MANAGER_H_ + +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { + +class Clock; + +class ControllerManager { + public: + virtual ~ControllerManager() = default; + + // Sort controllers based on their significance. + virtual std::vector GetSortedControllers( + const Controller::NetworkMetrics& metrics) = 0; + + virtual std::vector GetControllers() const = 0; +}; + +class ControllerManagerImpl final : public ControllerManager { + public: + struct Config { + Config(int min_reordering_time_ms, + float min_reordering_squared_distance, + const Clock* clock); + ~Config(); + // Least time since last reordering for a new reordering to be made. + int min_reordering_time_ms; + // Least squared distance from last scoring point for a new reordering to be + // made. + float min_reordering_squared_distance; + const Clock* clock; + }; + + static std::unique_ptr Create( + const std::string& config_string, + size_t num_encoder_channels, + rtc::ArrayView encoder_frame_lengths_ms, + int min_encoder_bitrate_bps, + size_t intial_channels_to_encode, + int initial_frame_length_ms, + int initial_bitrate_bps, + bool initial_fec_enabled, + bool initial_dtx_enabled, + const Clock* clock); + + explicit ControllerManagerImpl(const Config& config); + + // Dependency injection for testing. + ControllerManagerImpl( + const Config& config, + std::vector>&& controllers, + const std::map>& + chracteristic_points); + + ~ControllerManagerImpl() override; + + // Sort controllers based on their significance. + std::vector GetSortedControllers( + const Controller::NetworkMetrics& metrics) override; + + std::vector GetControllers() const override; + + private: + // Scoring point is a subset of NetworkMetrics that is used for comparing the + // significance of controllers. + struct ScoringPoint { + ScoringPoint(int uplink_bandwidth_bps, float uplink_packet_loss_fraction); + + // Calculate the normalized [0,1] distance between two scoring points. + float SquaredDistanceTo(const ScoringPoint& scoring_point) const; + + int uplink_bandwidth_bps; + float uplink_packet_loss_fraction; + }; + + const Config config_; + + std::vector> controllers_; + + rtc::Optional last_reordering_time_ms_; + ScoringPoint last_scoring_point_; + + std::vector default_sorted_controllers_; + + std::vector sorted_controllers_; + + // |scoring_points_| saves the characteristic scoring points of various + // controllers. + std::map controller_scoring_points_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ControllerManagerImpl); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_CONTROLLER_MANAGER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h new file mode 100644 index 0000000..da4b031 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DEBUG_DUMP_WRITER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DEBUG_DUMP_WRITER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" +#include "webrtc/system_wrappers/include/file_wrapper.h" + +namespace webrtc { + +class DebugDumpWriter { + public: + static std::unique_ptr Create(FILE* file_handle); + + virtual ~DebugDumpWriter() = default; + + virtual void DumpEncoderRuntimeConfig( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config, + int64_t timestamp) = 0; + + virtual void DumpNetworkMetrics(const Controller::NetworkMetrics& metrics, + int64_t timestamp) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DEBUG_DUMP_WRITER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/dtx_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/dtx_controller.h new file mode 100644 index 0000000..1bf2ce7 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/dtx_controller.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DTX_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DTX_CONTROLLER_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { + +class DtxController final : public Controller { + public: + struct Config { + Config(bool initial_dtx_enabled, + int dtx_enabling_bandwidth_bps, + int dtx_disabling_bandwidth_bps); + bool initial_dtx_enabled; + // Uplink bandwidth below which DTX should be switched on. + int dtx_enabling_bandwidth_bps; + // Uplink bandwidth above which DTX should be switched off. + int dtx_disabling_bandwidth_bps; + }; + + explicit DtxController(const Config& config); + + ~DtxController() override; + + void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; + + void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override; + + private: + const Config config_; + bool dtx_enabled_; + rtc::Optional uplink_bandwidth_bps_; + RTC_DISALLOW_COPY_AND_ASSIGN(DtxController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_DTX_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h new file mode 100644 index 0000000..740da8c --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" + +namespace webrtc { +class RtcEventLog; + +class EventLogWriter final { + public: + EventLogWriter(RtcEventLog* event_log, + int min_bitrate_change_bps, + float min_bitrate_change_fraction, + float min_packet_loss_change_fraction); + ~EventLogWriter(); + void MaybeLogEncoderConfig( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config); + + private: + void LogEncoderConfig( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config); + + RtcEventLog* const event_log_; + const int min_bitrate_change_bps_; + const float min_bitrate_change_fraction_; + const float min_packet_loss_change_fraction_; + AudioNetworkAdaptor::EncoderRuntimeConfig last_logged_config_; + RTC_DISALLOW_COPY_AND_ASSIGN(EventLogWriter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.h new file mode 100644 index 0000000..8d9cbb0 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/fec_controller.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/common_audio/smoothing_filter.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { + +class FecController final : public Controller { + public: + struct Config { + struct Threshold { + // Threshold defines a curve in the bandwidth/packet-loss domain. The + // curve is characterized by the two conjunction points: A and B. + // + // packet ^ | + // loss | A| + // | \ A: (low_bandwidth_bps, low_bandwidth_packet_loss) + // | \ B: (high_bandwidth_bps, high_bandwidth_packet_loss) + // | B\________ + // |---------------> bandwidth + Threshold(int low_bandwidth_bps, + float low_bandwidth_packet_loss, + int high_bandwidth_bps, + float high_bandwidth_packet_loss); + int low_bandwidth_bps; + float low_bandwidth_packet_loss; + int high_bandwidth_bps; + float high_bandwidth_packet_loss; + }; + + // |fec_enabling_threshold| defines a curve, above which FEC should be + // enabled. |fec_disabling_threshold| defines a curve, under which FEC + // should be disabled. See below + // + // packet-loss ^ | | + // | | | FEC + // | \ \ ON + // | FEC \ \_______ fec_enabling_threshold + // | OFF \_________ fec_disabling_threshold + // |-----------------> bandwidth + Config(bool initial_fec_enabled, + const Threshold& fec_enabling_threshold, + const Threshold& fec_disabling_threshold, + int time_constant_ms, + const Clock* clock); + bool initial_fec_enabled; + Threshold fec_enabling_threshold; + Threshold fec_disabling_threshold; + int time_constant_ms; + const Clock* clock; + }; + + // Dependency injection for testing. + FecController(const Config& config, + std::unique_ptr smoothing_filter); + + explicit FecController(const Config& config); + + ~FecController() override; + + void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; + + void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override; + + private: + // Characterize Threshold with packet_loss = slope * bandwidth + offset. + struct ThresholdInfo { + explicit ThresholdInfo(const Config::Threshold& threshold); + float slope; + float offset; + }; + + float GetPacketLossThreshold(int bandwidth_bps, + const Config::Threshold& threshold, + const ThresholdInfo& threshold_info) const; + + bool FecEnablingDecision(const rtc::Optional& packet_loss) const; + bool FecDisablingDecision(const rtc::Optional& packet_loss) const; + + const Config config_; + bool fec_enabled_; + rtc::Optional uplink_bandwidth_bps_; + const std::unique_ptr packet_loss_smoother_; + + const ThresholdInfo fec_enabling_threshold_info_; + const ThresholdInfo fec_disabling_threshold_info_; + + RTC_DISALLOW_COPY_AND_ASSIGN(FecController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FEC_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller.h new file mode 100644 index 0000000..74cbb56 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FRAME_LENGTH_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FRAME_LENGTH_CONTROLLER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" + +namespace webrtc { + +// Determines target frame length based on the network metrics and the decision +// of FEC controller. +class FrameLengthController final : public Controller { + public: + struct Config { + struct FrameLengthChange { + FrameLengthChange(int from_frame_length_ms, int to_frame_length_ms); + bool operator<(const FrameLengthChange& rhs) const; + int from_frame_length_ms; + int to_frame_length_ms; + }; + Config(const std::vector& encoder_frame_lengths_ms, + int initial_frame_length_ms, + int min_encoder_bitrate_bps, + float fl_increasing_packet_loss_fraction, + float fl_decreasing_packet_loss_fraction, + std::map fl_changing_bandwidths_bps); + Config(const Config& other); + ~Config(); + std::vector encoder_frame_lengths_ms; + int initial_frame_length_ms; + int min_encoder_bitrate_bps; + // Uplink packet loss fraction below which frame length can increase. + float fl_increasing_packet_loss_fraction; + // Uplink packet loss fraction below which frame length should decrease. + float fl_decreasing_packet_loss_fraction; + std::map fl_changing_bandwidths_bps; + }; + + explicit FrameLengthController(const Config& config); + + ~FrameLengthController() override; + + void UpdateNetworkMetrics(const NetworkMetrics& network_metrics) override; + + void MakeDecision(AudioNetworkAdaptor::EncoderRuntimeConfig* config) override; + + private: + bool FrameLengthIncreasingDecision( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const; + + bool FrameLengthDecreasingDecision( + const AudioNetworkAdaptor::EncoderRuntimeConfig& config) const; + + const Config config_; + + std::vector::const_iterator frame_length_ms_; + + rtc::Optional uplink_bandwidth_bps_; + + rtc::Optional uplink_packet_loss_fraction_; + + rtc::Optional overhead_bytes_per_packet_; + + RTC_DISALLOW_COPY_AND_ASSIGN(FrameLengthController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_FRAME_LENGTH_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h new file mode 100644 index 0000000..14ddbca --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_ + +#include "webrtc/base/optional.h" + +namespace webrtc { + +// An AudioNetworkAdaptor optimizes the audio experience by suggesting a +// suitable runtime configuration (bit rate, frame length, FEC, etc.) to the +// encoder based on network metrics. +class AudioNetworkAdaptor { + public: + struct EncoderRuntimeConfig { + EncoderRuntimeConfig(); + EncoderRuntimeConfig(const EncoderRuntimeConfig& other); + ~EncoderRuntimeConfig(); + rtc::Optional bitrate_bps; + rtc::Optional frame_length_ms; + rtc::Optional uplink_packet_loss_fraction; + rtc::Optional enable_fec; + rtc::Optional enable_dtx; + + // Some encoders can encode fewer channels than the actual input to make + // better use of the bandwidth. |num_channels| sets the number of channels + // to encode. + rtc::Optional num_channels; + }; + + virtual ~AudioNetworkAdaptor() = default; + + virtual void SetUplinkBandwidth(int uplink_bandwidth_bps) = 0; + + virtual void SetUplinkPacketLossFraction( + float uplink_packet_loss_fraction) = 0; + + virtual void SetRtt(int rtt_ms) = 0; + + virtual void SetTargetAudioBitrate(int target_audio_bitrate_bps) = 0; + + virtual void SetOverhead(size_t overhead_bytes_per_packet) = 0; + + virtual EncoderRuntimeConfig GetEncoderRuntimeConfig() = 0; + + virtual void StartDebugDump(FILE* file_handle) = 0; + + virtual void StopDebugDump() = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_INCLUDE_AUDIO_NETWORK_ADAPTOR_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h new file mode 100644 index 0000000..a826911 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_AUDIO_NETWORK_ADAPTOR_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_AUDIO_NETWORK_ADAPTOR_H_ + +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockAudioNetworkAdaptor : public AudioNetworkAdaptor { + public: + virtual ~MockAudioNetworkAdaptor() { Die(); } + MOCK_METHOD0(Die, void()); + + MOCK_METHOD1(SetUplinkBandwidth, void(int uplink_bandwidth_bps)); + + MOCK_METHOD1(SetUplinkPacketLossFraction, + void(float uplink_packet_loss_fraction)); + + MOCK_METHOD1(SetRtt, void(int rtt_ms)); + + MOCK_METHOD1(SetTargetAudioBitrate, void(int target_audio_bitrate_bps)); + + MOCK_METHOD1(SetOverhead, void(size_t overhead_bytes_per_packet)); + + MOCK_METHOD0(GetEncoderRuntimeConfig, EncoderRuntimeConfig()); + + MOCK_METHOD1(StartDebugDump, void(FILE* file_handle)); + + MOCK_METHOD0(StopDebugDump, void()); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_AUDIO_NETWORK_ADAPTOR_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller.h new file mode 100644 index 0000000..2b8dc9e --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_H_ + +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockController : public Controller { + public: + virtual ~MockController() { Die(); } + MOCK_METHOD0(Die, void()); + MOCK_METHOD1(UpdateNetworkMetrics, + void(const NetworkMetrics& network_metrics)); + MOCK_METHOD1(MakeDecision, + void(AudioNetworkAdaptor::EncoderRuntimeConfig* config)); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h new file mode 100644 index 0000000..4976fd8 --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_MANAGER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_MANAGER_H_ + +#include + +#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockControllerManager : public ControllerManager { + public: + virtual ~MockControllerManager() { Die(); } + MOCK_METHOD0(Die, void()); + MOCK_METHOD1( + GetSortedControllers, + std::vector(const Controller::NetworkMetrics& metrics)); + MOCK_CONST_METHOD0(GetControllers, std::vector()); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_CONTROLLER_MANAGER_H_ diff --git a/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h new file mode 100644 index 0000000..6a20f7a --- /dev/null +++ b/include/webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_DEBUG_DUMP_WRITER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_DEBUG_DUMP_WRITER_H_ + +#include "webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockDebugDumpWriter : public DebugDumpWriter { + public: + virtual ~MockDebugDumpWriter() { Die(); } + MOCK_METHOD0(Die, void()); + + MOCK_METHOD2(DumpEncoderRuntimeConfig, + void(const AudioNetworkAdaptor::EncoderRuntimeConfig& config, + int64_t timestamp)); + MOCK_METHOD2(DumpNetworkMetrics, + void(const Controller::NetworkMetrics& metrics, + int64_t timestamp)); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_MOCK_MOCK_DEBUG_DUMP_WRITER_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/audio_decoder.h b/include/webrtc/modules/audio_coding/codecs/audio_decoder.h index 580ddbf..da06282 100644 --- a/include/webrtc/modules/audio_coding/codecs/audio_decoder.h +++ b/include/webrtc/modules/audio_coding/codecs/audio_decoder.h @@ -8,111 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_ +// This file is for backwards compatibility only! Use +// webrtc/api/audio_codecs/audio_decoder.h instead! +// TODO(kwiberg): Remove it. -#include // NULL +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_ -#include "webrtc/base/constructormagic.h" -#include "webrtc/typedefs.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" -namespace webrtc { - -// This is the interface class for decoders in NetEQ. Each codec type will have -// and implementation of this class. -class AudioDecoder { - public: - enum SpeechType { - kSpeech = 1, - kComfortNoise = 2 - }; - - // Used by PacketDuration below. Save the value -1 for errors. - enum { kNotImplemented = -2 }; - - AudioDecoder() = default; - virtual ~AudioDecoder() = default; - - // Decodes |encode_len| bytes from |encoded| and writes the result in - // |decoded|. The maximum bytes allowed to be written into |decoded| is - // |max_decoded_bytes|. Returns the total number of samples across all - // channels. If the decoder produced comfort noise, |speech_type| - // is set to kComfortNoise, otherwise it is kSpeech. The desired output - // sample rate is provided in |sample_rate_hz|, which must be valid for the - // codec at hand. - int Decode(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type); - - // Same as Decode(), but interfaces to the decoders redundant decode function. - // The default implementation simply calls the regular Decode() method. - int DecodeRedundant(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - size_t max_decoded_bytes, - int16_t* decoded, - SpeechType* speech_type); - - // Indicates if the decoder implements the DecodePlc method. - virtual bool HasDecodePlc() const; - - // Calls the packet-loss concealment of the decoder to update the state after - // one or several lost packets. The caller has to make sure that the - // memory allocated in |decoded| should accommodate |num_frames| frames. - virtual size_t DecodePlc(size_t num_frames, int16_t* decoded); - - // Resets the decoder state (empty buffers etc.). - virtual void Reset() = 0; - - // Notifies the decoder of an incoming packet to NetEQ. - virtual int IncomingPacket(const uint8_t* payload, - size_t payload_len, - uint16_t rtp_sequence_number, - uint32_t rtp_timestamp, - uint32_t arrival_timestamp); - - // Returns the last error code from the decoder. - virtual int ErrorCode(); - - // Returns the duration in samples-per-channel of the payload in |encoded| - // which is |encoded_len| bytes long. Returns kNotImplemented if no duration - // estimate is available, or -1 in case of an error. - virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len) const; - - // Returns the duration in samples-per-channel of the redandant payload in - // |encoded| which is |encoded_len| bytes long. Returns kNotImplemented if no - // duration estimate is available, or -1 in case of an error. - virtual int PacketDurationRedundant(const uint8_t* encoded, - size_t encoded_len) const; - - // Detects whether a packet has forward error correction. The packet is - // comprised of the samples in |encoded| which is |encoded_len| bytes long. - // Returns true if the packet has FEC and false otherwise. - virtual bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const; - - virtual size_t Channels() const = 0; - - protected: - static SpeechType ConvertSpeechType(int16_t type); - - virtual int DecodeInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type) = 0; - - virtual int DecodeRedundantInternal(const uint8_t* encoded, - size_t encoded_len, - int sample_rate_hz, - int16_t* decoded, - SpeechType* speech_type); - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoder); -}; - -} // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_INCLUDE_AUDIO_DECODER_H_ +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_DECODER_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/audio_encoder.h b/include/webrtc/modules/audio_coding/codecs/audio_encoder.h index f4c5794..47152f9 100644 --- a/include/webrtc/modules/audio_coding/codecs/audio_encoder.h +++ b/include/webrtc/modules/audio_coding/codecs/audio_encoder.h @@ -17,10 +17,14 @@ #include "webrtc/base/array_view.h" #include "webrtc/base/buffer.h" #include "webrtc/base/deprecation.h" +#include "webrtc/base/optional.h" #include "webrtc/typedefs.h" namespace webrtc { +class Clock; +class RtcEventLog; + // This is the interface class for encoders in AudioCoding module. Each codec // type must have an implementation of this class. class AudioEncoder { @@ -127,6 +131,10 @@ class AudioEncoder { // supported). virtual bool SetDtx(bool enable); + // Returns the status of codec-internal DTX. The default implementation always + // returns false. + virtual bool GetDtx() const; + // Sets the application mode. Returns true if the codec was able to comply. // The default implementation just returns false. enum class Application { kSpeech, kAudio }; @@ -138,16 +146,55 @@ class AudioEncoder { // implementation does nothing. virtual void SetMaxPlaybackRate(int frequency_hz); - // Tells the encoder what the projected packet loss rate is. The rate is in - // the range [0.0, 1.0]. The encoder would typically use this information to - // adjust channel coding efforts, such as FEC. The default implementation - // does nothing. - virtual void SetProjectedPacketLossRate(double fraction); - + // This is to be deprecated. Please use |OnReceivedTargetAudioBitrate| + // instead. // Tells the encoder what average bitrate we'd like it to produce. The // encoder is free to adjust or disregard the given bitrate (the default // implementation does the latter). - virtual void SetTargetBitrate(int target_bps); + RTC_DEPRECATED virtual void SetTargetBitrate(int target_bps); + + // Causes this encoder to let go of any other encoders it contains, and + // returns a pointer to an array where they are stored (which is required to + // live as long as this encoder). Unless the returned array is empty, you may + // not call any methods on this encoder afterwards, except for the + // destructor. The default implementation just returns an empty array. + // NOTE: This method is subject to change. Do not call or override it. + virtual rtc::ArrayView> + ReclaimContainedEncoders(); + + // Enables audio network adaptor. Returns true if successful. + virtual bool EnableAudioNetworkAdaptor(const std::string& config_string, + RtcEventLog* event_log, + const Clock* clock); + + // Disables audio network adaptor. + virtual void DisableAudioNetworkAdaptor(); + + // Provides uplink packet loss fraction to this encoder to allow it to adapt. + // |uplink_packet_loss_fraction| is in the range [0.0, 1.0]. + virtual void OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction); + + // Provides target audio bitrate to this encoder to allow it to adapt. + virtual void OnReceivedTargetAudioBitrate(int target_bps); + + // Provides target audio bitrate and corresponding probing interval of + // the bandwidth estimator to this encoder to allow it to adapt. + virtual void OnReceivedUplinkBandwidth( + int target_audio_bitrate_bps, + rtc::Optional probing_interval_ms); + + // Provides RTT to this encoder to allow it to adapt. + virtual void OnReceivedRtt(int rtt_ms); + + // Provides overhead to this encoder to adapt. The overhead is the number of + // bytes that will be added to each packet the encoder generates. + virtual void OnReceivedOverhead(size_t overhead_bytes_per_packet); + + // To allow encoder to adapt its frame length, it must be provided the frame + // length range that receivers can accept. + virtual void SetReceiverFrameLengthRange(int min_frame_length_ms, + int max_frame_length_ms); protected: // Subclasses implement this to perform the actual encoding. Called by diff --git a/include/webrtc/modules/audio_coding/codecs/audio_format.h b/include/webrtc/modules/audio_coding/codecs/audio_format.h deleted file mode 100644 index 61c0dd9..0000000 --- a/include/webrtc/modules/audio_coding/codecs/audio_format.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_H_ -#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_H_ - -#include -#include -#include -#include - -namespace webrtc { - -// SDP specification for a single audio codec. -// NOTE: This class is still under development and may change without notice. -struct SdpAudioFormat { - using Parameters = std::map; - - // TODO(kwiberg): Get rid of the default constructor when rtc::Optional no - // longer requires it. - SdpAudioFormat(); - SdpAudioFormat(const SdpAudioFormat&); - SdpAudioFormat(SdpAudioFormat&&); - SdpAudioFormat(const char* name, int clockrate_hz, int num_channels); - SdpAudioFormat(const char* name, - int clockrate_hz, - int num_channels, - Parameters&& param); - ~SdpAudioFormat(); - - SdpAudioFormat& operator=(const SdpAudioFormat&); - SdpAudioFormat& operator=(SdpAudioFormat&&); - - std::string name; - int clockrate_hz; - int num_channels; - Parameters parameters; - // Parameters feedback_parameters; ?? -}; - -void swap(SdpAudioFormat& a, SdpAudioFormat& b); -std::ostream& operator<<(std::ostream& os, const SdpAudioFormat& saf); - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/audio_format_conversion.h b/include/webrtc/modules/audio_coding/codecs/audio_format_conversion.h new file mode 100644 index 0000000..0fa3a50 --- /dev/null +++ b/include/webrtc/modules/audio_coding/codecs/audio_format_conversion.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_ + +#include "webrtc/api/audio_codecs/audio_format.h" +#include "webrtc/common_types.h" + +namespace webrtc { + +SdpAudioFormat CodecInstToSdp(const CodecInst& codec_inst); +CodecInst SdpToCodecInst(int payload_type, const SdpAudioFormat& audio_format); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h b/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h index 7234c16..7e6407a 100644 --- a/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h +++ b/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h @@ -8,19 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ +// This file is for backwards compatibility only! Use +// webrtc/api/audio_codecs/builtin_audio_decoder_factory.h instead! +// TODO(kwiberg): Remove it. + #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ -#include - -#include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h" - -namespace webrtc { - -// Creates a new factory that can create the built-in types of audio decoders. -// NOTE: This function is still under development and may change without notice. -std::unique_ptr CreateBuiltinAudioDecoderFactory(); - -} // namespace webrtc +#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h" #endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.h b/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.h new file mode 100644 index 0000000..10f356a --- /dev/null +++ b/include/webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory_internal.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_INTERNAL_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_INTERNAL_H_ + +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" +#include "webrtc/base/scoped_ref_ptr.h" + +namespace webrtc { + +rtc::scoped_refptr +CreateBuiltinAudioDecoderFactoryInternal(); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_BUILTIN_AUDIO_DECODER_FACTORY_INTERNAL_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h b/include/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h index 246e951..0075bd0 100644 --- a/include/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h +++ b/include/webrtc/modules/audio_coding/codecs/cng/audio_encoder_cng.h @@ -61,8 +61,13 @@ class AudioEncoderCng final : public AudioEncoder { bool SetDtx(bool enable) override; bool SetApplication(Application application) override; void SetMaxPlaybackRate(int frequency_hz) override; - void SetProjectedPacketLossRate(double fraction) override; - void SetTargetBitrate(int target_bps) override; + rtc::ArrayView> ReclaimContainedEncoders() + override; + void OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction) override; + void OnReceivedUplinkBandwidth( + int target_audio_bitrate_bps, + rtc::Optional probing_interval_ms) override; private: EncodedInfo EncodePassive(size_t frames_to_encode, diff --git a/include/webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h b/include/webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h index 7a627e7..563d6ae 100644 --- a/include/webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h +++ b/include/webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h @@ -11,19 +11,22 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_G711_AUDIO_DECODER_PCM_H_ +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" namespace webrtc { class AudioDecoderPcmU final : public AudioDecoder { public: explicit AudioDecoderPcmU(size_t num_channels) : num_channels_(num_channels) { - RTC_DCHECK_GE(num_channels, 1u); + RTC_DCHECK_GE(num_channels, 1); } void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + int SampleRateHz() const override; size_t Channels() const override; protected: @@ -41,10 +44,13 @@ class AudioDecoderPcmU final : public AudioDecoder { class AudioDecoderPcmA final : public AudioDecoder { public: explicit AudioDecoderPcmA(size_t num_channels) : num_channels_(num_channels) { - RTC_DCHECK_GE(num_channels, 1u); + RTC_DCHECK_GE(num_channels, 1); } void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + int SampleRateHz() const override; size_t Channels() const override; protected: diff --git a/include/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h b/include/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h index 1837ffa..c53c78c 100644 --- a/include/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h +++ b/include/webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_ +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" typedef struct WebRtcG722DecInst G722DecInst; @@ -24,7 +24,10 @@ class AudioDecoderG722 final : public AudioDecoder { ~AudioDecoderG722() override; bool HasDecodePlc() const override; void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + int SampleRateHz() const override; size_t Channels() const override; protected: @@ -44,6 +47,10 @@ class AudioDecoderG722Stereo final : public AudioDecoder { AudioDecoderG722Stereo(); ~AudioDecoderG722Stereo() override; void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; + int SampleRateHz() const override; + size_t Channels() const override; protected: int DecodeInternal(const uint8_t* encoded, @@ -51,7 +58,6 @@ class AudioDecoderG722Stereo final : public AudioDecoder { int sample_rate_hz, int16_t* decoded, SpeechType* speech_type) override; - size_t Channels() const override; private: // Splits the stereo-interleaved payload in |encoded| into separate payloads diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/include/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h index 036c11f..bc01a5d 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_DECODER_ILBC_H_ +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" typedef struct iLBC_decinst_t_ IlbcDecoderInstance; @@ -25,6 +25,9 @@ class AudioDecoderIlbc final : public AudioDecoder { bool HasDecodePlc() const override; size_t DecodePlc(size_t num_frames, int16_t* decoded) override; void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; + int SampleRateHz() const override; size_t Channels() const override; protected: diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/cb_construct.h b/include/webrtc/modules/audio_coding/codecs/ilbc/cb_construct.h index b676ef9..34c0d1b 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/cb_construct.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/cb_construct.h @@ -19,20 +19,21 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_ +#include #include "defines.h" /*----------------------------------------------------------------* * Construct decoded vector from codebook and gains. *---------------------------------------------------------------*/ -void WebRtcIlbcfix_CbConstruct( - int16_t *decvector, /* (o) Decoded vector */ - int16_t *index, /* (i) Codebook indices */ - int16_t *gain_index, /* (i) Gain quantization indices */ - int16_t *mem, /* (i) Buffer for codevector construction */ - size_t lMem, /* (i) Length of buffer */ - size_t veclen /* (i) Length of vector */ - ); - +// Returns true on success, false on failure. +bool WebRtcIlbcfix_CbConstruct( + int16_t* decvector, /* (o) Decoded vector */ + const int16_t* index, /* (i) Codebook indices */ + const int16_t* gain_index, /* (i) Gain quantization indices */ + int16_t* mem, /* (i) Buffer for codevector construction */ + size_t lMem, /* (i) Length of buffer */ + size_t veclen /* (i) Length of vector */ + ) WARN_UNUSED_RESULT; #endif diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h b/include/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h index 430dfe9..f2582cd 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/create_augmented_vec.h @@ -27,10 +27,11 @@ *----------------------------------------------------------------*/ void WebRtcIlbcfix_CreateAugmentedVec( - size_t index, /* (i) Index for the augmented vector to be created */ - int16_t *buffer, /* (i) Pointer to the end of the codebook memory that - is used for creation of the augmented codebook */ - int16_t *cbVec /* (o) The construced codebook vector */ - ); + size_t index, /* (i) Index for the augmented vector to be + created */ + const int16_t* buffer, /* (i) Pointer to the end of the codebook memory + that is used for creation of the augmented + codebook */ + int16_t* cbVec); /* (o) The construced codebook vector */ #endif diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/decode.h b/include/webrtc/modules/audio_coding/codecs/ilbc/decode.h index 0c4c2ef..f45fedd 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/decode.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/decode.h @@ -25,13 +25,14 @@ * main decoder function *---------------------------------------------------------------*/ -void WebRtcIlbcfix_DecodeImpl( - int16_t *decblock, /* (o) decoded signal block */ - const uint16_t *bytes, /* (i) encoded signal bits */ - IlbcDecoder *iLBCdec_inst, /* (i/o) the decoder state +// Returns 0 on success, -1 on error. +int WebRtcIlbcfix_DecodeImpl( + int16_t* decblock, /* (o) decoded signal block */ + const uint16_t* bytes, /* (i) encoded signal bits */ + IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state structure */ - int16_t mode /* (i) 0: bad packet, PLC, - 1: normal */ - ); + int16_t mode /* (i) 0: bad packet, PLC, + 1: normal */ + ) WARN_UNUSED_RESULT; #endif diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/decode_residual.h b/include/webrtc/modules/audio_coding/codecs/ilbc/decode_residual.h index 67f05a5..38f896e 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/decode_residual.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/decode_residual.h @@ -19,20 +19,22 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_ +#include #include "defines.h" /*----------------------------------------------------------------* * frame residual decoder function (subrutine to iLBC_decode) *---------------------------------------------------------------*/ -void WebRtcIlbcfix_DecodeResidual( - IlbcDecoder *iLBCdec_inst, - /* (i/o) the decoder state structure */ - iLBC_bits *iLBC_encbits, /* (i/o) Encoded bits, which are used - for the decoding */ - int16_t *decresidual, /* (o) decoded residual frame */ - int16_t *syntdenum /* (i) the decoded synthesis filter - coefficients */ - ); +// Returns true on success, false on failure. In case of failure, the decoder +// state may be corrupted and needs resetting. +bool WebRtcIlbcfix_DecodeResidual( + IlbcDecoder* iLBCdec_inst, /* (i/o) the decoder state structure */ + iLBC_bits* iLBC_encbits, /* (i/o) Encoded bits, which are used + for the decoding */ + int16_t* decresidual, /* (o) decoded residual frame */ + int16_t* syntdenum /* (i) the decoded synthesis filter + coefficients */ + ) WARN_UNUSED_RESULT; #endif diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h b/include/webrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h index 61efd22..d540533 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/enhancer_interface.h @@ -25,10 +25,10 @@ * interface for enhancer *---------------------------------------------------------------*/ -size_t WebRtcIlbcfix_EnhancerInterface( /* (o) Estimated lag in end of in[] */ - int16_t *out, /* (o) enhanced signal */ - int16_t *in, /* (i) unenhanced signal */ - IlbcDecoder *iLBCdec_inst /* (i) buffers etc */ - ); +size_t // (o) Estimated lag in end of in[] + WebRtcIlbcfix_EnhancerInterface( + int16_t* out, // (o) enhanced signal + const int16_t* in, // (i) unenhanced signal + IlbcDecoder* iLBCdec_inst); // (i) buffers etc #endif diff --git a/include/webrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h b/include/webrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h index 07f67a2..b770e76 100644 --- a/include/webrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h +++ b/include/webrtc/modules/audio_coding/codecs/ilbc/get_cd_vec.h @@ -19,12 +19,18 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_ -void WebRtcIlbcfix_GetCbVec( - int16_t *cbvec, /* (o) Constructed codebook vector */ - int16_t *mem, /* (i) Codebook buffer */ +#include + +#include "defines.h" + +// Returns true on success, false on failure. In case of failure, the decoder +// state may be corrupted and needs resetting. +bool WebRtcIlbcfix_GetCbVec( + int16_t* cbvec, /* (o) Constructed codebook vector */ + int16_t* mem, /* (i) Codebook buffer */ size_t index, /* (i) Codebook index */ - size_t lMem, /* (i) Length of codebook buffer */ - size_t cbveclen /* (i) Codebook vector length */ - ); + size_t lMem, /* (i) Length of codebook buffer */ + size_t cbveclen /* (i) Codebook vector length */ + ) WARN_UNUSED_RESULT; #endif diff --git a/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h b/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h index b1907bb..1017cbc 100644 --- a/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h +++ b/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h @@ -13,9 +13,10 @@ #include +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" #include "webrtc/base/scoped_ref_ptr.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h" namespace webrtc { @@ -23,9 +24,9 @@ namespace webrtc { template class AudioDecoderIsacT final : public AudioDecoder { public: - AudioDecoderIsacT(); - explicit AudioDecoderIsacT( - const rtc::scoped_refptr& bwinfo); + explicit AudioDecoderIsacT(int sample_rate_hz); + AudioDecoderIsacT(int sample_rate_hz, + const rtc::scoped_refptr& bwinfo); ~AudioDecoderIsacT() override; bool HasDecodePlc() const override; @@ -37,6 +38,7 @@ class AudioDecoderIsacT final : public AudioDecoder { uint32_t rtp_timestamp, uint32_t arrival_timestamp) override; int ErrorCode() override; + int SampleRateHz() const override; size_t Channels() const override; int DecodeInternal(const uint8_t* encoded, size_t encoded_len, @@ -46,8 +48,8 @@ class AudioDecoderIsacT final : public AudioDecoder { private: typename T::instance_type* isac_state_; + int sample_rate_hz_; rtc::scoped_refptr bwinfo_; - int decoder_sample_rate_hz_; RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderIsacT); }; diff --git a/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h b/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h index 4998fea..e19f882 100644 --- a/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h +++ b/include/webrtc/modules/audio_coding/codecs/isac/audio_decoder_isac_t_impl.h @@ -18,13 +18,16 @@ namespace webrtc { template -AudioDecoderIsacT::AudioDecoderIsacT() - : AudioDecoderIsacT(nullptr) {} +AudioDecoderIsacT::AudioDecoderIsacT(int sample_rate_hz) + : AudioDecoderIsacT(sample_rate_hz, nullptr) {} template AudioDecoderIsacT::AudioDecoderIsacT( + int sample_rate_hz, const rtc::scoped_refptr& bwinfo) - : bwinfo_(bwinfo), decoder_sample_rate_hz_(-1) { + : sample_rate_hz_(sample_rate_hz), bwinfo_(bwinfo) { + RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000) + << "Unsupported sample rate " << sample_rate_hz; RTC_CHECK_EQ(0, T::Create(&isac_state_)); T::DecoderInit(isac_state_); if (bwinfo_) { @@ -32,6 +35,7 @@ AudioDecoderIsacT::AudioDecoderIsacT( T::GetBandwidthInfo(isac_state_, &bi); bwinfo_->Set(bi); } + RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz_)); } template @@ -45,12 +49,7 @@ int AudioDecoderIsacT::DecodeInternal(const uint8_t* encoded, int sample_rate_hz, int16_t* decoded, SpeechType* speech_type) { - RTC_CHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000) - << "Unsupported sample rate " << sample_rate_hz; - if (sample_rate_hz != decoder_sample_rate_hz_) { - RTC_CHECK_EQ(0, T::SetDecSampRate(isac_state_, sample_rate_hz)); - decoder_sample_rate_hz_ = sample_rate_hz; - } + RTC_CHECK_EQ(sample_rate_hz_, sample_rate_hz); int16_t temp_type = 1; // Default is speech. int ret = T::DecodeInternal(isac_state_, encoded, encoded_len, decoded, &temp_type); @@ -95,6 +94,11 @@ int AudioDecoderIsacT::ErrorCode() { return T::GetErrorCode(isac_state_); } +template +int AudioDecoderIsacT::SampleRateHz() const { + return sample_rate_hz_; +} + template size_t AudioDecoderIsacT::Channels() const { return 1; diff --git a/include/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/include/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h index b6a1747..e4d58ae 100644 --- a/include/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h +++ b/include/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h @@ -11,8 +11,6 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_ -#include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" - #include "webrtc/base/checks.h" #include "webrtc/common_types.h" diff --git a/include/webrtc/modules/audio_coding/codecs/isac/main/test/debugUtility.h b/include/webrtc/modules/audio_coding/codecs/isac/main/test/debugUtility.h deleted file mode 100644 index d708ad1..0000000 --- a/include/webrtc/modules/audio_coding/codecs/isac/main/test/debugUtility.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_TEST_DEBUGUTILITY_H_ -#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_TEST_DEBUGUTILITY_H_ - -#include -#include -#include "utility.h" - -typedef struct -{ - FILE* res0to4FilePtr; - FILE* res4to8FilePtr; - FILE* res8to12FilePtr; - FILE* res8to16FilePtr; - - FILE* res0to4DecFilePtr; - FILE* res4to8DecFilePtr; - FILE* res8to12DecFilePtr; - FILE* res8to16DecFilePtr; - - FILE* in0to4FilePtr; - FILE* in4to8FilePtr; - FILE* in8to12FilePtr; - FILE* in8to16FilePtr; - - FILE* out0to4FilePtr; - FILE* out4to8FilePtr; - FILE* out8to12FilePtr; - FILE* out8to16FilePtr; - - FILE* fftFilePtr; - FILE* fftDecFilePtr; - - FILE* arrivalTime; - - float lastArrivalTime; - - int prevPacketLost; - int currPacketLost; - int nextPacketLost; - - //double residualSignal4kHZ[240]; - int packetLossPercent; - - int maxPayloadLB; - int maxPayloadUB; - int lbBytes; - int ubBytes; - - -}debugStruct; - - -#define PRINT_ENTROPY_INFO(obj) \ - do \ - { \ - printf("%10u, %u; ", \ - obj->bitstr_obj.streamval, obj->bitstr_obj.stream_index); \ - } while(0) - -int setupDebugStruct(debugStruct* str); - -#endif \ No newline at end of file diff --git a/include/webrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h b/include/webrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h new file mode 100644 index 0000000..46b91ce --- /dev/null +++ b/include/webrtc/modules/audio_coding/codecs/legacy_encoded_audio_frame.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_ +#define WEBRTC_MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_ + +#include + +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/base/array_view.h" + +namespace webrtc { + +class LegacyEncodedAudioFrame final : public AudioDecoder::EncodedAudioFrame { + public: + LegacyEncodedAudioFrame(AudioDecoder* decoder, rtc::Buffer&& payload); + ~LegacyEncodedAudioFrame() override; + + static std::vector SplitBySamples( + AudioDecoder* decoder, + rtc::Buffer&& payload, + uint32_t timestamp, + size_t bytes_per_ms, + uint32_t timestamps_per_ms); + + size_t Duration() const override; + + rtc::Optional Decode( + rtc::ArrayView decoded) const override; + + // For testing: + const rtc::Buffer& payload() const { return payload_; } + + private: + AudioDecoder* const decoder_; + const rtc::Buffer payload_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_LEGACY_ENCODED_AUDIO_FRAME_H_ diff --git a/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h b/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h index 6e5737c..3b91491 100644 --- a/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h +++ b/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_decoder_factory.h @@ -13,14 +13,17 @@ #include -#include "testing/gmock/include/gmock/gmock.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h" +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" +#include "webrtc/api/audio_codecs/builtin_audio_decoder_factory.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/test/gmock.h" namespace webrtc { class MockAudioDecoderFactory : public AudioDecoderFactory { public: - MOCK_METHOD0(GetSupportedFormats, std::vector()); + MOCK_METHOD0(GetSupportedDecoders, std::vector()); + MOCK_METHOD1(IsSupportedDecoder, bool(const SdpAudioFormat&)); std::unique_ptr MakeAudioDecoder( const SdpAudioFormat& format) { std::unique_ptr return_value; @@ -30,6 +33,49 @@ class MockAudioDecoderFactory : public AudioDecoderFactory { MOCK_METHOD2(MakeAudioDecoderMock, void(const SdpAudioFormat& format, std::unique_ptr* return_value)); + + // Creates a MockAudioDecoderFactory with no formats and that may not be + // invoked to create a codec - useful for initializing a voice engine, for + // example. + static rtc::scoped_refptr + CreateUnusedFactory() { + using testing::_; + using testing::AnyNumber; + using testing::Return; + + rtc::scoped_refptr factory = + new rtc::RefCountedObject; + ON_CALL(*factory.get(), GetSupportedDecoders()) + .WillByDefault(Return(std::vector())); + EXPECT_CALL(*factory.get(), GetSupportedDecoders()).Times(AnyNumber()); + ON_CALL(*factory, IsSupportedDecoder(_)).WillByDefault(Return(false)); + EXPECT_CALL(*factory, IsSupportedDecoder(_)).Times(AnyNumber()); + EXPECT_CALL(*factory.get(), MakeAudioDecoderMock(_, _)).Times(0); + return factory; + } + + // Creates a MockAudioDecoderFactory with no formats that may be invoked to + // create a codec any number of times. It will, though, return nullptr on each + // call, since it supports no codecs. + static rtc::scoped_refptr + CreateEmptyFactory() { + using testing::_; + using testing::AnyNumber; + using testing::Return; + using testing::SetArgPointee; + + rtc::scoped_refptr factory = + new rtc::RefCountedObject; + ON_CALL(*factory.get(), GetSupportedDecoders()) + .WillByDefault(Return(std::vector())); + EXPECT_CALL(*factory.get(), GetSupportedDecoders()).Times(AnyNumber()); + ON_CALL(*factory, IsSupportedDecoder(_)).WillByDefault(Return(false)); + EXPECT_CALL(*factory, IsSupportedDecoder(_)).Times(AnyNumber()); + ON_CALL(*factory.get(), MakeAudioDecoderMock(_, _)) + .WillByDefault(SetArgPointee<1>(nullptr)); + EXPECT_CALL(*factory.get(), MakeAudioDecoderMock(_, _)).Times(AnyNumber()); + return factory; + } }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h b/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h index 2ffb30b..4c1b5f7 100644 --- a/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h +++ b/include/webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h @@ -15,8 +15,7 @@ #include "webrtc/base/array_view.h" #include "webrtc/modules/audio_coding/codecs/audio_encoder.h" - -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -40,10 +39,13 @@ class MockAudioEncoder : public AudioEncoder { MOCK_METHOD1(SetDtx, bool(bool enable)); MOCK_METHOD1(SetApplication, bool(Application application)); MOCK_METHOD1(SetMaxPlaybackRate, void(int frequency_hz)); - MOCK_METHOD1(SetProjectedPacketLossRate, void(double fraction)); - MOCK_METHOD1(SetTargetBitrate, void(int target_bps)); MOCK_METHOD1(SetMaxBitrate, void(int max_bps)); MOCK_METHOD1(SetMaxPayloadSize, void(int max_payload_size_bytes)); + MOCK_METHOD2(OnReceivedUplinkBandwidth, + void(int target_audio_bitrate_bps, + rtc::Optional probing_interval_ms)); + MOCK_METHOD1(OnReceivedUplinkPacketLossFraction, + void(float uplink_packet_loss_fraction)); // Note, we explicitly chose not to create a mock for the Encode method. MOCK_METHOD3(EncodeImpl, diff --git a/include/webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h b/include/webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h index be48ca9..e848f37 100644 --- a/include/webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h +++ b/include/webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_OPUS_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_DECODER_OPUS_H_ +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" namespace webrtc { @@ -22,11 +22,14 @@ class AudioDecoderOpus final : public AudioDecoder { explicit AudioDecoderOpus(size_t num_channels); ~AudioDecoderOpus() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; void Reset() override; int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; int PacketDurationRedundant(const uint8_t* encoded, size_t encoded_len) const override; bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override; + int SampleRateHz() const override; size_t Channels() const override; protected: diff --git a/include/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/include/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h index 8900659..3d0483b 100644 --- a/include/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h +++ b/include/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h @@ -11,14 +11,22 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_AUDIO_ENCODER_OPUS_H_ +#include +#include +#include #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/common_audio/smoothing_filter.h" +#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h" #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" #include "webrtc/modules/audio_coding/codecs/audio_encoder.h" namespace webrtc { +class RtcEventLog; + struct CodecInst; class AudioEncoderOpus final : public AudioEncoder { @@ -29,16 +37,36 @@ class AudioEncoderOpus final : public AudioEncoder { }; struct Config { + Config(); + Config(const Config&); + ~Config(); + Config& operator=(const Config&); + bool IsOk() const; + int GetBitrateBps() const; + // Returns empty if the current bitrate falls within the hysteresis window, + // defined by complexity_threshold_bps +/- complexity_threshold_window_bps. + // Otherwise, returns the current complexity depending on whether the + // current bitrate is above or below complexity_threshold_bps. + rtc::Optional GetNewComplexity() const; + int frame_size_ms = 20; size_t num_channels = 1; int payload_type = 120; ApplicationMode application = kVoip; - int bitrate_bps = 64000; + rtc::Optional bitrate_bps; // Unset means to use default value. bool fec_enabled = false; int max_playback_rate_hz = 48000; int complexity = kDefaultComplexity; + // This value may change in the struct's constructor. + int low_rate_complexity = kDefaultComplexity; + // low_rate_complexity is used when the bitrate is below this threshold. + int complexity_threshold_bps = 12500; + int complexity_threshold_window_bps = 1500; bool dtx_enabled = false; + std::vector supported_frame_lengths_ms; + const Clock* clock = Clock::GetRealTimeClock(); + int uplink_bandwidth_update_interval_ms = 200; private: #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) || defined(WEBRTC_ARCH_ARM) @@ -50,8 +78,17 @@ class AudioEncoderOpus final : public AudioEncoder { #endif }; - explicit AudioEncoderOpus(const Config& config); + using AudioNetworkAdaptorCreator = + std::function(const std::string&, + RtcEventLog*, + const Clock*)>; + AudioEncoderOpus( + const Config& config, + AudioNetworkAdaptorCreator&& audio_network_adaptor_creator = nullptr, + std::unique_ptr bitrate_smoother = nullptr); + explicit AudioEncoderOpus(const CodecInst& codec_inst); + ~AudioEncoderOpus() override; int SampleRateHz() const override; @@ -67,16 +104,33 @@ class AudioEncoderOpus final : public AudioEncoder { // being inactive. During that, it still sends 2 packets (one for content, one // for signaling) about every 400 ms. bool SetDtx(bool enable) override; + bool GetDtx() const override; bool SetApplication(Application application) override; void SetMaxPlaybackRate(int frequency_hz) override; - void SetProjectedPacketLossRate(double fraction) override; - void SetTargetBitrate(int target_bps) override; + bool EnableAudioNetworkAdaptor(const std::string& config_string, + RtcEventLog* event_log, + const Clock* clock) override; + void DisableAudioNetworkAdaptor() override; + void OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction) override; + void OnReceivedUplinkBandwidth( + int target_audio_bitrate_bps, + rtc::Optional probing_interval_ms) override; + void OnReceivedRtt(int rtt_ms) override; + void OnReceivedOverhead(size_t overhead_bytes_per_packet) override; + void SetReceiverFrameLengthRange(int min_frame_length_ms, + int max_frame_length_ms) override; + rtc::ArrayView supported_frame_lengths_ms() const { + return config_.supported_frame_lengths_ms; + } // Getters for testing. - double packet_loss_rate() const { return packet_loss_rate_; } + float packet_loss_rate() const { return packet_loss_rate_; } ApplicationMode application() const { return config_.application; } - bool dtx_enabled() const { return config_.dtx_enabled; } + bool fec_enabled() const { return config_.fec_enabled; } + size_t num_channels_to_encode() const { return num_channels_to_encode_; } + int next_frame_length_ms() const { return next_frame_length_ms_; } protected: EncodedInfo EncodeImpl(uint32_t rtp_timestamp, @@ -84,16 +138,44 @@ class AudioEncoderOpus final : public AudioEncoder { rtc::Buffer* encoded) override; private: + class PacketLossFractionSmoother; + size_t Num10msFramesPerPacket() const; size_t SamplesPer10msFrame() const; size_t SufficientOutputBufferSize() const; bool RecreateEncoderInstance(const Config& config); + void SetFrameLength(int frame_length_ms); + void SetNumChannelsToEncode(size_t num_channels_to_encode); + void SetProjectedPacketLossRate(float fraction); + + // TODO(minyue): remove "override" when we can deprecate + // |AudioEncoder::SetTargetBitrate|. + void SetTargetBitrate(int target_bps) override; + + void ApplyAudioNetworkAdaptor(); + std::unique_ptr DefaultAudioNetworkAdaptorCreator( + const std::string& config_string, + RtcEventLog* event_log, + const Clock* clock) const; + + void MaybeUpdateUplinkBandwidth(); Config config_; - double packet_loss_rate_; + const bool send_side_bwe_with_overhead_; + float packet_loss_rate_; std::vector input_buffer_; OpusEncInst* inst_; uint32_t first_timestamp_in_buffer_; + size_t num_channels_to_encode_; + int next_frame_length_ms_; + int complexity_; + std::unique_ptr packet_loss_fraction_smoother_; + AudioNetworkAdaptorCreator audio_network_adaptor_creator_; + std::unique_ptr audio_network_adaptor_; + rtc::Optional overhead_bytes_per_packet_; + const std::unique_ptr bitrate_smoother_; + rtc::Optional bitrate_smoother_last_update_time_; + RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderOpus); }; diff --git a/include/webrtc/modules/audio_coding/codecs/opus/opus_inst.h b/include/webrtc/modules/audio_coding/codecs/opus/opus_inst.h index aa79b46..b2be12a 100644 --- a/include/webrtc/modules/audio_coding/codecs/opus/opus_inst.h +++ b/include/webrtc/modules/audio_coding/codecs/opus/opus_inst.h @@ -13,7 +13,11 @@ #include +#include "webrtc/base/ignore_wundef.h" + +RTC_PUSH_IGNORING_WUNDEF() #include "opus.h" +RTC_POP_IGNORING_WUNDEF() struct WebRtcOpusEncInst { OpusEncoder* encoder; diff --git a/include/webrtc/modules/audio_coding/codecs/opus/opus_interface.h b/include/webrtc/modules/audio_coding/codecs/opus/opus_interface.h index 754b49c..3db5152 100644 --- a/include/webrtc/modules/audio_coding/codecs/opus/opus_interface.h +++ b/include/webrtc/modules/audio_coding/codecs/opus/opus_interface.h @@ -195,6 +195,28 @@ int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst); */ int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity); +/* + * WebRtcOpus_SetForceChannels(...) + * + * If the encoder is initialized as a stereo encoder, Opus will by default + * decide whether to encode in mono or stereo based on the bitrate. This + * function overrules the previous setting, and forces the encoder to encode + * in auto/mono/stereo. + * + * If the Encoder is initialized as a mono encoder, and one tries to force + * stereo, the function will return an error. + * + * Input: + * - inst : Encoder context + * - num_channels : 0 - Not forced + * 1 - Mono + * 2 - Stereo + * + * Return value : 0 - Success + * -1 - Error + */ +int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels); + int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels); int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst); diff --git a/include/webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h b/include/webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h index 692cb94..969aa4e 100644 --- a/include/webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h +++ b/include/webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h @@ -11,16 +11,19 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_DECODER_PCM16B_H_ #define WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_DECODER_PCM16B_H_ +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" namespace webrtc { class AudioDecoderPcm16B final : public AudioDecoder { public: - explicit AudioDecoderPcm16B(size_t num_channels); + AudioDecoderPcm16B(int sample_rate_hz, size_t num_channels); void Reset() override; + std::vector ParsePayload(rtc::Buffer&& payload, + uint32_t timestamp) override; int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override; + int SampleRateHz() const override; size_t Channels() const override; protected: @@ -31,6 +34,7 @@ class AudioDecoderPcm16B final : public AudioDecoder { SpeechType* speech_type) override; private: + const int sample_rate_hz_; const size_t num_channels_; RTC_DISALLOW_COPY_AND_ASSIGN(AudioDecoderPcm16B); }; diff --git a/include/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/include/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h index ead9fd6..b3ec085 100644 --- a/include/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h +++ b/include/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h @@ -49,8 +49,13 @@ class AudioEncoderCopyRed final : public AudioEncoder { bool SetDtx(bool enable) override; bool SetApplication(Application application) override; void SetMaxPlaybackRate(int frequency_hz) override; - void SetProjectedPacketLossRate(double fraction) override; - void SetTargetBitrate(int target_bps) override; + rtc::ArrayView> ReclaimContainedEncoders() + override; + void OnReceivedUplinkPacketLossFraction( + float uplink_packet_loss_fraction) override; + void OnReceivedUplinkBandwidth( + int target_audio_bitrate_bps, + rtc::Optional probing_interval_ms) override; protected: EncodedInfo EncodeImpl(uint32_t rtp_timestamp, diff --git a/include/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h b/include/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h index 3560eac..b79b1ef 100644 --- a/include/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h +++ b/include/webrtc/modules/audio_coding/codecs/tools/audio_codec_speed_test.h @@ -13,7 +13,8 @@ #include #include -#include "testing/gtest/include/gtest/gtest.h" + +#include "webrtc/test/gtest.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/include/audio_coding_module.h b/include/webrtc/modules/audio_coding/include/audio_coding_module.h index daf9ac8..7843fb8 100644 --- a/include/webrtc/modules/audio_coding/include/audio_coding_module.h +++ b/include/webrtc/modules/audio_coding/include/audio_coding_module.h @@ -15,7 +15,9 @@ #include #include +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" #include "webrtc/base/deprecation.h" +#include "webrtc/base/function_view.h" #include "webrtc/base/optional.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" @@ -63,15 +65,14 @@ class AudioCodingModule { public: struct Config { - Config() : id(0), neteq_config(), clock(Clock::GetRealTimeClock()) { - // Post-decode VAD is disabled by default in NetEq, however, Audio - // Conference Mixer relies on VAD decisions and fails without them. - neteq_config.enable_post_decode_vad = true; - } + Config(); + Config(const Config&); + ~Config(); int id; NetEq::Config neteq_config; Clock* clock; + rtc::scoped_refptr decoder_factory; }; /////////////////////////////////////////////////////////////////////////// @@ -209,44 +210,18 @@ class AudioCodingModule { virtual void RegisterExternalSendCodec( AudioEncoder* external_speech_encoder) = 0; - // Just like std::function, FunctionView will wrap any callable and hide its - // actual type, exposing only its signature. But unlike std::function, - // FunctionView doesn't own its callable---it just points to it. Thus, it's a - // good choice mainly as a function argument when the callable argument will - // not be called again once the function has returned. - template - class FunctionView; // Undefined. - - template - class FunctionView final { - public: - // This constructor is implicit, so that callers won't have to convert - // lambdas to FunctionView explicitly. This is safe - // because FunctionView is only a reference to the real callable. - template - FunctionView(F&& f) - : f_(&f), call_(Call::type>) {} - - RetT operator()(ArgT... args) const { - return call_(f_, std::forward(args)...); - } - - private: - template - static RetT Call(void* f, ArgT... args) { - return (*static_cast(f))(std::forward(args)...); - } - void* f_; - RetT (*call_)(void* f, ArgT... args); - }; - // |modifier| is called exactly once with one argument: a pointer to the // unique_ptr that holds the current encoder (which is null if there is no // current encoder). For the duration of the call, |modifier| has exclusive // access to the unique_ptr; it may call the encoder, steal the encoder and // replace it with another encoder or with nullptr, etc. virtual void ModifyEncoder( - FunctionView*)> modifier) = 0; + rtc::FunctionView*)> modifier) = 0; + + // |modifier| is called exactly once with one argument: a const pointer to the + // current encoder (which is null if there is no current encoder). + virtual void QueryEncoder( + rtc::FunctionView query) = 0; // Utility method for simply replacing the existing encoder with a new one. void SetEncoder(std::unique_ptr new_encoder) { @@ -277,6 +252,9 @@ class AudioCodingModule { /////////////////////////////////////////////////////////////////////////// // Sets the bitrate to the specified value in bits/sec. If the value is not // supported by the codec, it will choose another appropriate value. + // + // This is only used in test code that rely on old ACM APIs. + // TODO(minyue): Remove it when possible. virtual void SetBitRate(int bitrate_bps) = 0; // int32_t RegisterTransportCallback() @@ -396,6 +374,8 @@ class AudioCodingModule { // -1 if failed to set packet loss rate, // 0 if succeeded. // + // This is only used in test code that rely on old ACM APIs. + // TODO(minyue): Remove it when possible. virtual int SetPacketLossRate(int packet_loss_rate) = 0; /////////////////////////////////////////////////////////////////////////// @@ -504,6 +484,11 @@ class AudioCodingModule { // virtual int32_t PlayoutFrequency() const = 0; + // Registers a decoder for the given payload type. Returns true iff + // successful. + virtual bool RegisterReceiveCodec(int rtp_payload_type, + const SdpAudioFormat& audio_format) = 0; + /////////////////////////////////////////////////////////////////////////// // int32_t RegisterReceiveCodec() // Register possible decoders, can be called multiple times for @@ -525,7 +510,7 @@ class AudioCodingModule { // the decoder being registered is iSAC. virtual int RegisterReceiveCodec( const CodecInst& receive_codec, - FunctionView()> isac_factory) = 0; + rtc::FunctionView()> isac_factory) = 0; // Registers an external decoder. The name is only used to provide information // back to the caller about the decoder. Hence, the name is arbitrary, and may @@ -567,6 +552,17 @@ class AudioCodingModule { // virtual int32_t ReceiveCodec(CodecInst* curr_receive_codec) const = 0; + /////////////////////////////////////////////////////////////////////////// + // rtc::Optional ReceiveFormat() + // Get the format associated with last received payload. + // + // Return value: + // An SdpAudioFormat describing the format associated with the last + // received payload. + // An empty Optional if no payload has yet been received. + // + virtual rtc::Optional ReceiveFormat() const = 0; + /////////////////////////////////////////////////////////////////////////// // int32_t IncomingPacket() // Call this function to insert a parsed RTP packet into ACM. @@ -641,7 +637,8 @@ class AudioCodingModule { // virtual int SetMaximumPlayoutDelay(int time_ms) = 0; - // + // TODO(kwiberg): Consider if this is needed anymore, now that voe::Channel + // doesn't use it. // The shortest latency, in milliseconds, required by jitter buffer. This // is computed based on inter-arrival times and playout mode of NetEq. The // actual delay is the maximum of least-required-delay and the minimum-delay @@ -672,6 +669,15 @@ class AudioCodingModule { // virtual rtc::Optional PlayoutTimestamp() = 0; + /////////////////////////////////////////////////////////////////////////// + // int FilteredCurrentDelayMs() + // Returns the current total delay from NetEq (packet buffer and sync buffer) + // in ms, with smoothing applied to even out short-time fluctuations due to + // jitter. The packet buffer part of the delay is not updated during DTX/CNG + // periods. + // + virtual int FilteredCurrentDelayMs() const = 0; + /////////////////////////////////////////////////////////////////////////// // int32_t PlayoutData10Ms( // Get 10 milliseconds of raw audio data for playout, at the given sampling diff --git a/include/webrtc/modules/audio_coding/neteq/audio_classifier.h b/include/webrtc/modules/audio_coding/neteq/audio_classifier.h deleted file mode 100644 index 653b275..0000000 --- a/include/webrtc/modules/audio_coding/neteq/audio_classifier.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_CLASSIFIER_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_CLASSIFIER_H_ - -extern "C" { -#include "celt.h" -#include "analysis.h" -#include "opus_private.h" -} - -#include "webrtc/typedefs.h" - -namespace webrtc { - -// This class provides a speech/music classification and is a wrapper over the -// Opus classifier. It currently only supports 48 kHz mono or stereo with a -// frame size of 20 ms. - -class AudioClassifier { - public: - AudioClassifier(); - virtual ~AudioClassifier(); - - // Classifies one frame of audio data in input, - // input_length : must be channels * 960; - // channels : must be 1 (mono) or 2 (stereo). - bool Analysis(const int16_t* input, int input_length, int channels); - - // Gets the current classification : true = music, false = speech. - virtual bool is_music() const; - - // Gets the current music probability. - float music_probability() const { return music_probability_; } - - private: - AnalysisInfo analysis_info_; - bool is_music_; - float music_probability_; - const CELTMode* celt_mode_; - TonalityAnalysisState analysis_state_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_CLASSIFIER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/include/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h index 579ccb3..a876f17 100644 --- a/include/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h +++ b/include/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h @@ -13,14 +13,14 @@ #include -#include "webrtc/engine_configurations.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" +#include "webrtc/typedefs.h" + #ifdef WEBRTC_CODEC_G722 #include "webrtc/modules/audio_coding/codecs/g722/g722_interface.h" #endif -#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" -#include "webrtc/typedefs.h" namespace webrtc { @@ -29,8 +29,5 @@ using NetEqDecoder = acm2::RentACodec::NetEqDecoder; // Returns true if |codec_type| is supported. bool CodecSupported(NetEqDecoder codec_type); -// Returns the sample rate for |codec_type|. -int CodecSampleRateHz(NetEqDecoder codec_type); - } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_AUDIO_DECODER_IMPL_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/audio_vector.h b/include/webrtc/modules/audio_coding/neteq/audio_vector.h index 756292a..57e01ab 100644 --- a/include/webrtc/modules/audio_coding/neteq/audio_vector.h +++ b/include/webrtc/modules/audio_coding/neteq/audio_vector.h @@ -14,6 +14,7 @@ #include // Access to size_t. #include +#include "webrtc/base/checks.h" #include "webrtc/base/constructormagic.h" #include "webrtc/typedefs.h" @@ -110,12 +111,33 @@ class AudioVector { virtual bool Empty() const; // Accesses and modifies an element of AudioVector. - const int16_t& operator[](size_t index) const; - int16_t& operator[](size_t index); + inline const int16_t& operator[](size_t index) const { + return array_[WrapIndex(index, begin_index_, capacity_)]; + } + + inline int16_t& operator[](size_t index) { + return array_[WrapIndex(index, begin_index_, capacity_)]; + } private: static const size_t kDefaultInitialSize = 10; + // This method is used by the [] operators to calculate an index within the + // capacity of the array, but without using the modulo operation (%). + static inline size_t WrapIndex(size_t index, + size_t begin_index, + size_t capacity) { + RTC_DCHECK_LT(index, capacity); + RTC_DCHECK_LT(begin_index, capacity); + size_t ix = begin_index + index; + RTC_DCHECK_GE(ix, index); // Check for overflow. + if (ix >= capacity) { + ix -= capacity; + } + RTC_DCHECK_LT(ix, capacity); + return ix; + } + void Reserve(size_t n); void InsertByPushBack(const int16_t* insert_this, size_t length, diff --git a/include/webrtc/modules/audio_coding/neteq/comfort_noise.h b/include/webrtc/modules/audio_coding/neteq/comfort_noise.h index f877bf6..7476784 100644 --- a/include/webrtc/modules/audio_coding/neteq/comfort_noise.h +++ b/include/webrtc/modules/audio_coding/neteq/comfort_noise.h @@ -45,8 +45,7 @@ class ComfortNoise { void Reset(); // Update the comfort noise generator with the parameters in |packet|. - // Will delete the packet. - int UpdateParameters(Packet* packet); + int UpdateParameters(const Packet& packet); // Generates |requested_length| samples of comfort noise and writes to // |output|. If this is the first in call after Reset (or first after creating diff --git a/include/webrtc/modules/audio_coding/neteq/decision_logic.h b/include/webrtc/modules/audio_coding/neteq/decision_logic.h index 008655d..66c940d 100644 --- a/include/webrtc/modules/audio_coding/neteq/decision_logic.h +++ b/include/webrtc/modules/audio_coding/neteq/decision_logic.h @@ -26,7 +26,7 @@ class DelayManager; class Expand; class PacketBuffer; class SyncBuffer; -struct RTPHeader; +struct Packet; // This is the base class for the decision tree implementations. Derived classes // must implement the method GetDecisionSpecialized(). @@ -66,19 +66,18 @@ class DecisionLogic { // Returns the operation that should be done next. |sync_buffer| and |expand| // are provided for reference. |decoder_frame_length| is the number of samples - // obtained from the last decoded frame. If there is a packet available, the - // packet header should be supplied in |packet_header|; otherwise it should - // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is - // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf| - // should be set to true. The output variable |reset_decoder| will be set to - // true if a reset is required; otherwise it is left unchanged (i.e., it can - // remain true if it was true before the call). - // This method end with calling GetDecisionSpecialized to get the actual - // return value. + // obtained from the last decoded frame. If there is a packet available, it + // should be supplied in |next_packet|; otherwise it should be NULL. The mode + // resulting from the last call to NetEqImpl::GetAudio is supplied in + // |prev_mode|. If there is a DTMF event to play, |play_dtmf| should be set to + // true. The output variable |reset_decoder| will be set to true if a reset is + // required; otherwise it is left unchanged (i.e., it can remain true if it + // was true before the call). This method end with calling + // GetDecisionSpecialized to get the actual return value. Operations GetDecision(const SyncBuffer& sync_buffer, const Expand& expand, size_t decoder_frame_length, - const RTPHeader* packet_header, + const Packet* next_packet, Modes prev_mode, bool play_dtmf, size_t generated_noise_samples, @@ -124,18 +123,17 @@ class DecisionLogic { // Returns the operation that should be done next. |sync_buffer| and |expand| // are provided for reference. |decoder_frame_length| is the number of samples - // obtained from the last decoded frame. If there is a packet available, the - // packet header should be supplied in |packet_header|; otherwise it should - // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is - // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf| - // should be set to true. The output variable |reset_decoder| will be set to - // true if a reset is required; otherwise it is left unchanged (i.e., it can - // remain true if it was true before the call). - // Should be implemented by derived classes. + // obtained from the last decoded frame. If there is a packet available, it + // should be supplied in |next_packet|; otherwise it should be NULL. The mode + // resulting from the last call to NetEqImpl::GetAudio is supplied in + // |prev_mode|. If there is a DTMF event to play, |play_dtmf| should be set to + // true. The output variable |reset_decoder| will be set to true if a reset is + // required; otherwise it is left unchanged (i.e., it can remain true if it + // was true before the call). Should be implemented by derived classes. virtual Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer, const Expand& expand, size_t decoder_frame_length, - const RTPHeader* packet_header, + const Packet* next_packet, Modes prev_mode, bool play_dtmf, bool* reset_decoder, diff --git a/include/webrtc/modules/audio_coding/neteq/decision_logic_fax.h b/include/webrtc/modules/audio_coding/neteq/decision_logic_fax.h index 6958f90..6726126 100644 --- a/include/webrtc/modules/audio_coding/neteq/decision_logic_fax.h +++ b/include/webrtc/modules/audio_coding/neteq/decision_logic_fax.h @@ -40,19 +40,10 @@ class DecisionLogicFax : public DecisionLogic { tick_timer) {} protected: - // Returns the operation that should be done next. |sync_buffer| and |expand| - // are provided for reference. |decoder_frame_length| is the number of samples - // obtained from the last decoded frame. If there is a packet available, the - // packet header should be supplied in |packet_header|; otherwise it should - // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is - // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf| - // should be set to true. The output variable |reset_decoder| will be set to - // true if a reset is required; otherwise it is left unchanged (i.e., it can - // remain true if it was true before the call). Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer, const Expand& expand, size_t decoder_frame_length, - const RTPHeader* packet_header, + const Packet* next_packet, Modes prev_mode, bool play_dtmf, bool* reset_decoder, diff --git a/include/webrtc/modules/audio_coding/neteq/decision_logic_normal.h b/include/webrtc/modules/audio_coding/neteq/decision_logic_normal.h index aa0edf3..0605867 100644 --- a/include/webrtc/modules/audio_coding/neteq/decision_logic_normal.h +++ b/include/webrtc/modules/audio_coding/neteq/decision_logic_normal.h @@ -40,23 +40,13 @@ class DecisionLogicNormal : public DecisionLogic { tick_timer) {} protected: - static const int kAllowMergeWithoutExpandMs = 20; // 20 ms. static const int kReinitAfterExpands = 100; static const int kMaxWaitForPacket = 10; - // Returns the operation that should be done next. |sync_buffer| and |expand| - // are provided for reference. |decoder_frame_length| is the number of samples - // obtained from the last decoded frame. If there is a packet available, the - // packet header should be supplied in |packet_header|; otherwise it should - // be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is - // supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf| - // should be set to true. The output variable |reset_decoder| will be set to - // true if a reset is required; otherwise it is left unchanged (i.e., it can - // remain true if it was true before the call). Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer, const Expand& expand, size_t decoder_frame_length, - const RTPHeader* packet_header, + const Packet* next_packet, Modes prev_mode, bool play_dtmf, bool* reset_decoder, diff --git a/include/webrtc/modules/audio_coding/neteq/decoder_database.h b/include/webrtc/modules/audio_coding/neteq/decoder_database.h index 3a40e08..114cca3 100644 --- a/include/webrtc/modules/audio_coding/neteq/decoder_database.h +++ b/include/webrtc/modules/audio_coding/neteq/decoder_database.h @@ -15,10 +15,10 @@ #include #include +#include "webrtc/api/audio_codecs/audio_decoder_factory.h" +#include "webrtc/api/audio_codecs/audio_format.h" #include "webrtc/base/constructormagic.h" #include "webrtc/common_types.h" // NULL -#include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h" -#include "webrtc/modules/audio_coding/codecs/audio_format.h" #include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include "webrtc/modules/audio_coding/neteq/packet.h" @@ -41,35 +41,99 @@ class DecoderDatabase { // Class that stores decoder info in the database. class DecoderInfo { public: - DecoderInfo(NetEqDecoder ct, - const std::string& nm, - int fs, - AudioDecoder* ext_dec); + DecoderInfo(const SdpAudioFormat& audio_format, + AudioDecoderFactory* factory, + const std::string& codec_name); + explicit DecoderInfo(const SdpAudioFormat& audio_format, + AudioDecoderFactory* factory = nullptr); + explicit DecoderInfo(NetEqDecoder ct, + AudioDecoderFactory* factory = nullptr); + DecoderInfo(const SdpAudioFormat& audio_format, + AudioDecoder* ext_dec, + const std::string& codec_name); DecoderInfo(DecoderInfo&&); ~DecoderInfo(); // Get the AudioDecoder object, creating it first if necessary. - AudioDecoder* GetDecoder(AudioDecoderFactory* factory); + AudioDecoder* GetDecoder() const; // Delete the AudioDecoder object, unless it's external. (This means we can // always recreate it later if we need it.) - void DropDecoder() { decoder_.reset(); } - - const NetEqDecoder codec_type; - const std::string name; - const int fs_hz; - AudioDecoder* const external_decoder; + void DropDecoder() const { decoder_.reset(); } + + int SampleRateHz() const { + if (IsDtmf()) { + // DTMF has a 1:1 mapping between clock rate and sample rate. + return audio_format_.clockrate_hz; + } + const AudioDecoder* decoder = GetDecoder(); + RTC_DCHECK_EQ(1, !!decoder + !!cng_decoder_); + return decoder ? decoder->SampleRateHz() : cng_decoder_->sample_rate_hz; + } + + const SdpAudioFormat& GetFormat() const { return audio_format_; } + + // Returns true if the decoder's format is comfort noise. + bool IsComfortNoise() const { + RTC_DCHECK_EQ(!!cng_decoder_, subtype_ == Subtype::kComfortNoise); + return subtype_ == Subtype::kComfortNoise; + } + + // Returns true if the decoder's format is DTMF. + bool IsDtmf() const { + return subtype_ == Subtype::kDtmf; + } + + // Returns true if the decoder's format is RED. + bool IsRed() const { + return subtype_ == Subtype::kRed; + } + + // Returns true if the decoder's format is named |name|. + bool IsType(const char* name) const; + // Returns true if the decoder's format is named |name|. + bool IsType(const std::string& name) const; + + const std::string& get_name() const { return name_; } private: - const rtc::Optional audio_format_; - std::unique_ptr decoder_; + // TODO(ossu): |name_| is kept here while we retain the old external + // decoder interface. Remove this once using an + // AudioDecoderFactory has supplanted the old functionality. + const std::string name_; + + const SdpAudioFormat audio_format_; + AudioDecoderFactory* const factory_; + mutable std::unique_ptr decoder_; + + // Set iff this is an external decoder. + AudioDecoder* const external_decoder_; + + // Set iff this is a comfort noise decoder. + struct CngDecoder { + static rtc::Optional Create(const SdpAudioFormat& format); + int sample_rate_hz; + }; + const rtc::Optional cng_decoder_; + + enum class Subtype : int8_t { + kNormal, + kComfortNoise, + kDtmf, + kRed + }; + + static Subtype SubtypeFromFormat(const SdpAudioFormat& format); + + const Subtype subtype_; }; // Maximum value for 8 bits, and an invalid RTP payload type (since it is // only 7 bits). static const uint8_t kRtpPayloadTypeError = 0xFF; - DecoderDatabase(std::unique_ptr decoder_factory); + DecoderDatabase( + const rtc::scoped_refptr& decoder_factory); virtual ~DecoderDatabase(); @@ -92,53 +156,36 @@ class DecoderDatabase { NetEqDecoder codec_type, const std::string& name); + // Registers a decoder for the given payload type. Returns kOK on success; + // otherwise an error code. + virtual int RegisterPayload(int rtp_payload_type, + const SdpAudioFormat& audio_format); + // Registers an externally created AudioDecoder object, and associates it // as a decoder of type |codec_type| with |rtp_payload_type|. virtual int InsertExternal(uint8_t rtp_payload_type, NetEqDecoder codec_type, const std::string& codec_name, - int fs_hz, AudioDecoder* decoder); // Removes the entry for |rtp_payload_type| from the database. // Returns kDecoderNotFound or kOK depending on the outcome of the operation. virtual int Remove(uint8_t rtp_payload_type); + // Remove all entries. + virtual void RemoveAll(); + // Returns a pointer to the DecoderInfo struct for |rtp_payload_type|. If // no decoder is registered with that |rtp_payload_type|, NULL is returned. virtual const DecoderInfo* GetDecoderInfo(uint8_t rtp_payload_type) const; - // Returns one RTP payload type associated with |codec_type|, or - // kDecoderNotFound if no entry exists for that value. Note that one - // |codec_type| may be registered with several RTP payload types, and the - // method may return any of them. - virtual uint8_t GetRtpPayloadType(NetEqDecoder codec_type) const; - - // Returns a pointer to the AudioDecoder object associated with - // |rtp_payload_type|, or NULL if none is registered. If the AudioDecoder - // object does not exist for that decoder, the object is created. - virtual AudioDecoder* GetDecoder(uint8_t rtp_payload_type); - - // Returns true if |rtp_payload_type| is registered as a |codec_type|. - virtual bool IsType(uint8_t rtp_payload_type, - NetEqDecoder codec_type) const; - - // Returns true if |rtp_payload_type| is registered as comfort noise. - virtual bool IsComfortNoise(uint8_t rtp_payload_type) const; - - // Returns true if |rtp_payload_type| is registered as DTMF. - virtual bool IsDtmf(uint8_t rtp_payload_type) const; - - // Returns true if |rtp_payload_type| is registered as RED. - virtual bool IsRed(uint8_t rtp_payload_type) const; - // Sets the active decoder to be |rtp_payload_type|. If this call results in a // change of active decoder, |new_decoder| is set to true. The previous active // decoder's AudioDecoder object is deleted. virtual int SetActiveDecoder(uint8_t rtp_payload_type, bool* new_decoder); // Returns the current active decoder, or NULL if no active decoder exists. - virtual AudioDecoder* GetActiveDecoder(); + virtual AudioDecoder* GetActiveDecoder() const; // Sets the active comfort noise decoder to be |rtp_payload_type|. If this // call results in a change of active comfort noise decoder, the previous @@ -147,11 +194,35 @@ class DecoderDatabase { // Returns the current active comfort noise decoder, or NULL if no active // comfort noise decoder exists. - virtual ComfortNoiseDecoder* GetActiveCngDecoder(); + virtual ComfortNoiseDecoder* GetActiveCngDecoder() const; + + // The following are utility methods: they will look up DecoderInfo through + // GetDecoderInfo and call the respective method on that info object, if it + // exists. + + // Returns a pointer to the AudioDecoder object associated with + // |rtp_payload_type|, or NULL if none is registered. If the AudioDecoder + // object does not exist for that decoder, the object is created. + AudioDecoder* GetDecoder(uint8_t rtp_payload_type) const; + + // Returns if |rtp_payload_type| is registered with a format named |name|. + bool IsType(uint8_t rtp_payload_type, const char* name) const; + + // Returns if |rtp_payload_type| is registered with a format named |name|. + bool IsType(uint8_t rtp_payload_type, const std::string& name) const; + + // Returns true if |rtp_payload_type| is registered as comfort noise. + bool IsComfortNoise(uint8_t rtp_payload_type) const; + + // Returns true if |rtp_payload_type| is registered as DTMF. + bool IsDtmf(uint8_t rtp_payload_type) const; + + // Returns true if |rtp_payload_type| is registered as RED. + bool IsRed(uint8_t rtp_payload_type) const; // Returns kOK if all packets in |packet_list| carry payload types that are // registered in the database. Otherwise, returns kDecoderNotFound. - virtual int CheckPayloadTypes(const PacketList& packet_list) const; + int CheckPayloadTypes(const PacketList& packet_list) const; private: typedef std::map DecoderMap; @@ -159,8 +230,8 @@ class DecoderDatabase { DecoderMap decoders_; int active_decoder_type_; int active_cng_decoder_type_; - std::unique_ptr active_cng_decoder_; - const std::unique_ptr decoder_factory_; + mutable std::unique_ptr active_cng_decoder_; + rtc::scoped_refptr decoder_factory_; RTC_DISALLOW_COPY_AND_ASSIGN(DecoderDatabase); }; diff --git a/include/webrtc/modules/audio_coding/neteq/delay_manager.h b/include/webrtc/modules/audio_coding/neteq/delay_manager.h index 6f3c14a..7871572 100644 --- a/include/webrtc/modules/audio_coding/neteq/delay_manager.h +++ b/include/webrtc/modules/audio_coding/neteq/delay_manager.h @@ -72,7 +72,7 @@ class DelayManager { // the nominal frame time, the return value is zero. A positive value // corresponds to packet spacing being too large, while a negative value means // that the packets arrive with less spacing than expected. - virtual int AverageIAT() const; + virtual double EstimatedClockDriftPpm() const; // Returns true if peak-mode is active. That is, delay peaks were observed // recently. This method simply asks for the same information from the @@ -91,7 +91,9 @@ class DelayManager { // includes any extra delay set through the set_extra_delay_ms() method. virtual int TargetLevel() const; - virtual void LastDecoderType(NetEqDecoder decoder_type); + // Informs the delay manager whether or not the last decoded packet contained + // speech. + virtual void LastDecodedWasCngOrDtmf(bool it_was); // Accessors and mutators. // Assuming |delay| is in valid range. diff --git a/include/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h b/include/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h index 36d902a..9abd03e 100644 --- a/include/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h +++ b/include/webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h @@ -38,7 +38,7 @@ class DtmfToneGenerator { static const int kCoeff2[4][16]; // 2nd oscillator model coefficient table. static const int kInitValue1[4][16]; // Initialization for 1st oscillator. static const int kInitValue2[4][16]; // Initialization for 2nd oscillator. - static const int kAmplitude[37]; // Amplitude for 0 through -36 dBm0. + static const int kAmplitude[64]; // Amplitude for 0 through -63 dBm0. static const int16_t kAmpMultiplier = 23171; // 3 dB attenuation (in Q15). bool initialized_; // True if generator is initialized properly. diff --git a/include/webrtc/modules/audio_coding/neteq/include/neteq.h b/include/webrtc/modules/audio_coding/neteq/include/neteq.h index 3a9de1d..ea05940 100644 --- a/include/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/include/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -17,6 +17,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/optional.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include "webrtc/typedefs.h" @@ -26,6 +27,7 @@ namespace webrtc { // Forward declarations. class AudioFrame; struct WebRtcRTPHeader; +class AudioDecoderFactory; struct NetEqNetworkStatistics { uint16_t current_buffer_size_ms; // Current jitter buffer size in ms. @@ -74,7 +76,6 @@ class NetEq { struct Config { Config() : sample_rate_hz(16000), - enable_audio_classifier(false), enable_post_decode_vad(false), max_packets_in_buffer(50), // |max_delay_ms| has the same effect as calling SetMaximumDelay(). @@ -86,7 +87,6 @@ class NetEq { std::string ToString() const; int sample_rate_hz; // Initial value. Will change with input data. - bool enable_audio_classifier; bool enable_post_decode_vad; size_t max_packets_in_buffer; int max_delay_ms; @@ -124,16 +124,16 @@ class NetEq { kStereoNotSupported, kSampleUnderrun, kDecodedTooMuch, - kFrameSplitError, kRedundancySplitError, - kPacketBufferCorruption, - kSyncPacketNotAccepted + kPacketBufferCorruption }; // Creates a new NetEq object, with parameters set in |config|. The |config| // object will only have to be valid for the duration of the call to this // method. - static NetEq* Create(const NetEq::Config& config); + static NetEq* Create( + const NetEq::Config& config, + const rtc::scoped_refptr& decoder_factory); virtual ~NetEq() {} @@ -145,23 +145,11 @@ class NetEq { rtc::ArrayView payload, uint32_t receive_timestamp) = 0; - // Inserts a sync-packet into packet queue. Sync-packets are decoded to - // silence and are intended to keep AV-sync intact in an event of long packet - // losses when Video NACK is enabled but Audio NACK is not. Clients of NetEq - // might insert sync-packet when they observe that buffer level of NetEq is - // decreasing below a certain threshold, defined by the application. - // Sync-packets should have the same payload type as the last audio payload - // type, i.e. they cannot have DTMF or CNG payload type, nor a codec change - // can be implied by inserting a sync-packet. - // Returns kOk on success, kFail on failure. - virtual int InsertSyncPacket(const WebRtcRTPHeader& rtp_header, - uint32_t receive_timestamp) = 0; - // Instructs NetEq to deliver 10 ms of audio data. The data is written to // |audio_frame|. All data in |audio_frame| is wiped; |data_|, |speech_type_|, // |num_channels_|, |sample_rate_hz_|, |samples_per_channel_|, and // |vad_activity_| are updated upon success. If an error is returned, some - // fields may not have been updated. + // fields may not have been updated, or may contain inconsistent values. // If muted state is enabled (through Config::enable_muted_state), |muted| // may be set to true after a prolonged expand period. When this happens, the // |data_| in |audio_frame| is not written, but should be interpreted as being @@ -179,21 +167,27 @@ class NetEq { // Provides an externally created decoder object |decoder| to insert in the // decoder database. The decoder implements a decoder of type |codec| and - // associates it with |rtp_payload_type| and |codec_name|. The decoder will - // produce samples at the rate |sample_rate_hz|. Returns kOK on success, kFail - // on failure. - // The name is only used to provide information back to the caller about the - // decoders. Hence, the name is arbitrary, and may be empty. + // associates it with |rtp_payload_type| and |codec_name|. Returns kOK on + // success, kFail on failure. The name is only used to provide information + // back to the caller about the decoders. Hence, the name is arbitrary, and + // may be empty. virtual int RegisterExternalDecoder(AudioDecoder* decoder, NetEqDecoder codec, const std::string& codec_name, - uint8_t rtp_payload_type, - int sample_rate_hz) = 0; + uint8_t rtp_payload_type) = 0; + + // Associates |rtp_payload_type| with the given codec, which NetEq will + // instantiate when it needs it. Returns true iff successful. + virtual bool RegisterPayloadType(int rtp_payload_type, + const SdpAudioFormat& audio_format) = 0; // Removes |rtp_payload_type| from the codec database. Returns 0 on success, // -1 on failure. virtual int RemovePayloadType(uint8_t rtp_payload_type) = 0; + // Removes all payload types from the codec database. + virtual void RemoveAllPayloadTypes() = 0; + // Sets a minimum delay in millisecond for packet buffer. The minimum is // maintained unless a higher latency is dictated by channel condition. // Returns true if the minimum is successfully applied, otherwise false is @@ -221,6 +215,11 @@ class NetEq { // Returns the current total delay (packet buffer and sync buffer) in ms. virtual int CurrentDelayMs() const = 0; + // Returns the current total delay (packet buffer and sync buffer) in ms, + // with smoothing applied to even out short-time fluctuations due to jitter. + // The packet buffer part of the delay is not updated during DTX/CNG periods. + virtual int FilteredCurrentDelayMs() const = 0; + // Sets the playout mode to |mode|. // Deprecated. Set the mode in the Config struct passed to the constructor. // TODO(henrik.lundin) Delete. @@ -258,6 +257,15 @@ class NetEq { // (Config::sample_rate_hz) is returned. virtual int last_output_sample_rate_hz() const = 0; + // Returns info about the decoder for the given payload type, or an empty + // value if we have no decoder for that payload type. + virtual rtc::Optional GetDecoder(int payload_type) const = 0; + + // Returns the decoder format for the given payload type. Returns empty if no + // such payload type was registered. + virtual rtc::Optional GetDecoderFormat( + int payload_type) const = 0; + // Not implemented. virtual int SetTargetNumberOfChannels() = 0; diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h index c1cc09c..f5b343d 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h @@ -11,9 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_AUDIO_DECODER_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_AUDIO_DECODER_H_ -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" - -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -32,8 +31,7 @@ class MockAudioDecoder : public AudioDecoder { MOCK_METHOD0(ErrorCode, int()); MOCK_CONST_METHOD2(PacketDuration, int(const uint8_t*, size_t)); MOCK_CONST_METHOD0(Channels, size_t()); - MOCK_CONST_METHOD0(codec_type, NetEqDecoder()); - MOCK_METHOD1(CodecSupported, bool(NetEqDecoder)); + MOCK_CONST_METHOD0(SampleRateHz, int()); }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_vector.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_vector.h deleted file mode 100644 index a35a26a..0000000 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_audio_vector.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_AUDIO_VECTOR_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_AUDIO_VECTOR_H_ - -#include "webrtc/modules/audio_coding/neteq/audio_vector.h" - -#include "testing/gmock/include/gmock/gmock.h" - -namespace webrtc { - -class MockAudioVector : public AudioVector { - public: - MOCK_METHOD0(Clear, - void()); - MOCK_CONST_METHOD1(CopyFrom, - void(AudioVector* copy_to)); - MOCK_METHOD1(PushFront, - void(const AudioVector& prepend_this)); - MOCK_METHOD2(PushFront, - void(const T* prepend_this, size_t length)); - MOCK_METHOD1(PushBack, - void(const AudioVector& append_this)); - MOCK_METHOD2(PushBack, - void(const T* append_this, size_t length)); - MOCK_METHOD1(PopFront, - void(size_t length)); - MOCK_METHOD1(PopBack, - void(size_t length)); - MOCK_METHOD1(Extend, - void(size_t extra_length)); - MOCK_METHOD3(InsertAt, - void(const T* insert_this, size_t length, size_t position)); - MOCK_METHOD3(OverwriteAt, - void(const T* insert_this, size_t length, size_t position)); - MOCK_CONST_METHOD0(Size, - size_t()); - MOCK_CONST_METHOD0(Empty, - bool()); -}; - -} // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_AUDIO_VECTOR_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h index 82dee2a..da22845 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/buffer_level_filter.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h index 60ae0f6..4018879 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h @@ -15,13 +15,15 @@ #include "webrtc/modules/audio_coding/neteq/decoder_database.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { class MockDecoderDatabase : public DecoderDatabase { public: - MockDecoderDatabase() : DecoderDatabase(nullptr) {} + explicit MockDecoderDatabase( + rtc::scoped_refptr factory = nullptr) + : DecoderDatabase(factory) {} virtual ~MockDecoderDatabase() { Die(); } MOCK_METHOD0(Die, void()); MOCK_CONST_METHOD0(Empty, @@ -33,36 +35,26 @@ class MockDecoderDatabase : public DecoderDatabase { MOCK_METHOD3(RegisterPayload, int(uint8_t rtp_payload_type, NetEqDecoder codec_type, const std::string& name)); - MOCK_METHOD5(InsertExternal, - int(uint8_t rtp_payload_type, NetEqDecoder codec_type, - const std::string& codec_name, int fs_hz, - AudioDecoder* decoder)); + MOCK_METHOD2(RegisterPayload, + int(int rtp_payload_type, const SdpAudioFormat& audio_format)); + MOCK_METHOD4(InsertExternal, + int(uint8_t rtp_payload_type, + NetEqDecoder codec_type, + const std::string& codec_name, + AudioDecoder* decoder)); MOCK_METHOD1(Remove, int(uint8_t rtp_payload_type)); + MOCK_METHOD0(RemoveAll, void()); MOCK_CONST_METHOD1(GetDecoderInfo, const DecoderInfo*(uint8_t rtp_payload_type)); - MOCK_CONST_METHOD1(GetRtpPayloadType, - uint8_t(NetEqDecoder codec_type)); - MOCK_METHOD1(GetDecoder, - AudioDecoder*(uint8_t rtp_payload_type)); - MOCK_CONST_METHOD2(IsType, - bool(uint8_t rtp_payload_type, NetEqDecoder codec_type)); - MOCK_CONST_METHOD1(IsComfortNoise, - bool(uint8_t rtp_payload_type)); - MOCK_CONST_METHOD1(IsDtmf, - bool(uint8_t rtp_payload_type)); - MOCK_CONST_METHOD1(IsRed, - bool(uint8_t rtp_payload_type)); MOCK_METHOD2(SetActiveDecoder, int(uint8_t rtp_payload_type, bool* new_decoder)); - MOCK_METHOD0(GetActiveDecoder, + MOCK_CONST_METHOD0(GetActiveDecoder, AudioDecoder*()); MOCK_METHOD1(SetActiveCngDecoder, int(uint8_t rtp_payload_type)); - MOCK_METHOD0(GetActiveCngDecoder, + MOCK_CONST_METHOD0(GetActiveCngDecoder, ComfortNoiseDecoder*()); - MOCK_CONST_METHOD1(CheckPayloadTypes, - int(const PacketList& packet_list)); }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h index 7ceea70..7a66b68 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_manager.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/delay_manager.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -35,8 +35,6 @@ class MockDelayManager : public DelayManager { int(int length_ms)); MOCK_METHOD0(Reset, void()); - MOCK_CONST_METHOD0(AverageIAT, - int()); MOCK_CONST_METHOD0(PeakFound, bool()); MOCK_METHOD1(UpdateCounters, @@ -47,8 +45,6 @@ class MockDelayManager : public DelayManager { void(int* lower_limit, int* higher_limit)); MOCK_CONST_METHOD0(TargetLevel, int()); - MOCK_METHOD1(LastDecoderType, - void(NetEqDecoder decoder_type)); MOCK_METHOD1(set_extra_delay_ms, void(int16_t delay)); MOCK_CONST_METHOD0(base_target_level, diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h index 5564fba..3a80cb4 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/delay_peak_detector.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_buffer.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_buffer.h index c76ffaf..0aac22c 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_buffer.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_buffer.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/dtmf_buffer.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h index a1c370e..bb0a535 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_dtmf_tone_generator.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_expand.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_expand.h index f5ca077..9465f6f 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_expand.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_expand.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/expand.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h index 42c17ae..a8919f2 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h @@ -11,11 +11,10 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_ -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" - -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" #include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -23,11 +22,11 @@ namespace webrtc { using ::testing::_; using ::testing::Invoke; -// Implement an external version of the PCM16b decoder. This is a copy from -// audio_decoder_impl.{cc, h}. +// Implement an external version of the PCM16b decoder. class ExternalPcm16B : public AudioDecoder { public: - ExternalPcm16B() {} + explicit ExternalPcm16B(int sample_rate_hz) + : sample_rate_hz_(sample_rate_hz) {} void Reset() override {} int DecodeInternal(const uint8_t* encoded, @@ -35,21 +34,24 @@ class ExternalPcm16B : public AudioDecoder { int sample_rate_hz, int16_t* decoded, SpeechType* speech_type) override { + EXPECT_EQ(sample_rate_hz_, sample_rate_hz); size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len, decoded); *speech_type = ConvertSpeechType(1); return static_cast(ret); } + int SampleRateHz() const override { return sample_rate_hz_; } size_t Channels() const override { return 1; } private: + const int sample_rate_hz_; RTC_DISALLOW_COPY_AND_ASSIGN(ExternalPcm16B); }; // Create a mock of ExternalPcm16B which delegates all calls to the real object. // The reason is that we can then track that the correct calls are being made. -class MockExternalPcm16B : public ExternalPcm16B { +class MockExternalPcm16B : public AudioDecoder { public: - MockExternalPcm16B() { + explicit MockExternalPcm16B(int sample_rate_hz) : real_(sample_rate_hz) { // By default, all calls are delegated to the real object. ON_CALL(*this, DecodeInternal(_, _, _, _, _)) .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal)); @@ -85,6 +87,9 @@ class MockExternalPcm16B : public ExternalPcm16B { MOCK_METHOD0(ErrorCode, int()); + int SampleRateHz() const /* override */ { return real_.SampleRateHz(); } + size_t Channels() const /* override */ { return real_.Channels(); } + private: ExternalPcm16B real_; }; diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_packet_buffer.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_packet_buffer.h index 6bb9590..5a2f7e1 100644 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_packet_buffer.h +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_packet_buffer.h @@ -13,7 +13,7 @@ #include "webrtc/modules/audio_coding/neteq/packet_buffer.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -27,21 +27,27 @@ class MockPacketBuffer : public PacketBuffer { void()); MOCK_CONST_METHOD0(Empty, bool()); - MOCK_METHOD1(InsertPacket, + int InsertPacket(Packet&& packet) { + return InsertPacketWrapped(&packet); + } + // Since gtest does not properly support move-only types, InsertPacket is + // implemented as a wrapper. You'll have to implement InsertPacketWrapped + // instead and move from |*packet|. + MOCK_METHOD1(InsertPacketWrapped, int(Packet* packet)); MOCK_METHOD4(InsertPacketList, int(PacketList* packet_list, const DecoderDatabase& decoder_database, - uint8_t* current_rtp_payload_type, - uint8_t* current_cng_rtp_payload_type)); + rtc::Optional* current_rtp_payload_type, + rtc::Optional* current_cng_rtp_payload_type)); MOCK_CONST_METHOD1(NextTimestamp, int(uint32_t* next_timestamp)); MOCK_CONST_METHOD2(NextHigherTimestamp, int(uint32_t timestamp, uint32_t* next_timestamp)); - MOCK_CONST_METHOD0(NextRtpHeader, - const RTPHeader*()); - MOCK_METHOD1(GetNextPacket, - Packet*(size_t* discard_count)); + MOCK_CONST_METHOD0(PeekNextPacket, + const Packet*()); + MOCK_METHOD0(GetNextPacket, + rtc::Optional()); MOCK_METHOD0(DiscardNextPacket, int()); MOCK_METHOD2(DiscardOldPackets, diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_payload_splitter.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_payload_splitter.h deleted file mode 100644 index 9fa05e9..0000000 --- a/include/webrtc/modules/audio_coding/neteq/mock/mock_payload_splitter.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_PAYLOAD_SPLITTER_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_PAYLOAD_SPLITTER_H_ - -#include "webrtc/modules/audio_coding/neteq/payload_splitter.h" - -#include "testing/gmock/include/gmock/gmock.h" - -namespace webrtc { - -class MockPayloadSplitter : public PayloadSplitter { - public: - MOCK_METHOD1(SplitRed, - int(PacketList* packet_list)); - MOCK_METHOD2(SplitFec, - int(PacketList* packet_list, DecoderDatabase* decoder_database)); - MOCK_METHOD2(CheckRedPayloads, - int(PacketList* packet_list, const DecoderDatabase& decoder_database)); - MOCK_METHOD2(SplitAudio, - int(PacketList* packet_list, const DecoderDatabase& decoder_database)); - MOCK_METHOD4(SplitBySamples, - void(const Packet* packet, size_t bytes_per_ms, - uint32_t timestamps_per_ms, PacketList* new_packets)); - MOCK_METHOD4(SplitByFrames, - int(const Packet* packet, size_t bytes_per_frame, - uint32_t timestamps_per_frame, PacketList* new_packets)); -}; - -} // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_PAYLOAD_SPLITTER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/mock/mock_red_payload_splitter.h b/include/webrtc/modules/audio_coding/neteq/mock/mock_red_payload_splitter.h new file mode 100644 index 0000000..8c6e939 --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/mock/mock_red_payload_splitter.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_RED_PAYLOAD_SPLITTER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_RED_PAYLOAD_SPLITTER_H_ + +#include "webrtc/modules/audio_coding/neteq/red_payload_splitter.h" + +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRedPayloadSplitter : public RedPayloadSplitter { + public: + MOCK_METHOD1(SplitRed, bool(PacketList* packet_list)); + MOCK_METHOD2(CheckRedPayloads, + int(PacketList* packet_list, + const DecoderDatabase& decoder_database)); +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_RED_PAYLOAD_SPLITTER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/nack.h b/include/webrtc/modules/audio_coding/neteq/nack_tracker.h similarity index 88% rename from include/webrtc/modules/audio_coding/neteq/nack.h rename to include/webrtc/modules/audio_coding/neteq/nack_tracker.h index c46a85a..de97d91 100644 --- a/include/webrtc/modules/audio_coding/neteq/nack.h +++ b/include/webrtc/modules/audio_coding/neteq/nack_tracker.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_ +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_ #include #include @@ -18,8 +18,8 @@ #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" // -// The Nack class keeps track of the lost packets, an estimate of time-to-play -// for each packet is also given. +// The NackTracker class keeps track of the lost packets, an estimate of +// time-to-play for each packet is also given. // // Every time a packet is pushed into NetEq, LastReceivedPacket() has to be // called to update the NACK list. @@ -34,12 +34,12 @@ // "late." A "late" packet with sequence number K is changed to "missing" any // time a packet with sequence number newer than |K + NackList| is arrived. // -// The Nack class has to know about the sample rate of the packets to compute -// time-to-play. So sample rate should be set as soon as the first packet is -// received. If there is a change in the receive codec (sender changes codec) -// then Nack should be reset. This is because NetEQ would flush its buffer and -// re-transmission is meaning less for old packet. Therefore, in that case, -// after reset the sampling rate has to be updated. +// The NackTracker class has to know about the sample rate of the packets to +// compute time-to-play. So sample rate should be set as soon as the first +// packet is received. If there is a change in the receive codec (sender changes +// codec) then NackTracker should be reset. This is because NetEQ would flush +// its buffer and re-transmission is meaning less for old packet. Therefore, in +// that case, after reset the sampling rate has to be updated. // // Thread Safety // ============= @@ -48,15 +48,15 @@ // namespace webrtc { -class Nack { +class NackTracker { public: // A limit for the size of the NACK list. static const size_t kNackListSizeLimit = 500; // 10 seconds for 20 ms frame // packets. // Factory method. - static Nack* Create(int nack_threshold_packets); + static NackTracker* Create(int nack_threshold_packets); - ~Nack(); + ~NackTracker(); // Set a maximum for the size of the NACK list. If the last received packet // has sequence number of N, then NACK list will not contain any element @@ -92,7 +92,7 @@ class Nack { private: // This test need to access the private method GetNackList(). - FRIEND_TEST_ALL_PREFIXES(NackTest, EstimateTimestampAndTimeToPlay); + FRIEND_TEST_ALL_PREFIXES(NackTrackerTest, EstimateTimestampAndTimeToPlay); struct NackElement { NackElement(int64_t initial_time_to_play_ms, @@ -130,7 +130,7 @@ class Nack { typedef std::map NackList; // Constructor. - explicit Nack(int nack_threshold_packets); + explicit NackTracker(int nack_threshold_packets); // This API is used only for testing to assess whether time-to-play is // computed correctly. @@ -205,4 +205,4 @@ class Nack { } // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_ +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/neteq_impl.h b/include/webrtc/modules/audio_coding/neteq/neteq_impl.h index cc55504..505f0f2 100644 --- a/include/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/include/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -16,6 +16,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/base/optional.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h" #include "webrtc/modules/audio_coding/neteq/defines.h" @@ -42,10 +43,10 @@ class DtmfBuffer; class DtmfToneGenerator; class Expand; class Merge; -class Nack; +class NackTracker; class Normal; class PacketBuffer; -class PayloadSplitter; +class RedPayloadSplitter; class PostDecodeVad; class PreemptiveExpand; class RandomVector; @@ -72,7 +73,9 @@ class NetEqImpl : public webrtc::NetEq { // before sending the struct to the NetEqImpl constructor. However, there // are dependencies between some of the classes inside the struct, so // swapping out one may make it necessary to re-create another one. - explicit Dependencies(const NetEq::Config& config); + explicit Dependencies( + const NetEq::Config& config, + const rtc::scoped_refptr& decoder_factory); ~Dependencies(); std::unique_ptr tick_timer; @@ -83,7 +86,7 @@ class NetEqImpl : public webrtc::NetEq { std::unique_ptr dtmf_buffer; std::unique_ptr dtmf_tone_generator; std::unique_ptr packet_buffer; - std::unique_ptr payload_splitter; + std::unique_ptr red_payload_splitter; std::unique_ptr timestamp_scaler; std::unique_ptr accelerate_factory; std::unique_ptr expand_factory; @@ -105,18 +108,6 @@ class NetEqImpl : public webrtc::NetEq { rtc::ArrayView payload, uint32_t receive_timestamp) override; - // Inserts a sync-packet into packet queue. Sync-packets are decoded to - // silence and are intended to keep AV-sync intact in an event of long packet - // losses when Video NACK is enabled but Audio NACK is not. Clients of NetEq - // might insert sync-packet when they observe that buffer level of NetEq is - // decreasing below a certain threshold, defined by the application. - // Sync-packets should have the same payload type as the last audio payload - // type, i.e. they cannot have DTMF or CNG payload type, nor a codec change - // can be implied by inserting a sync-packet. - // Returns kOk on success, kFail on failure. - int InsertSyncPacket(const WebRtcRTPHeader& rtp_header, - uint32_t receive_timestamp) override; - int GetAudio(AudioFrame* audio_frame, bool* muted) override; int RegisterPayloadType(NetEqDecoder codec, @@ -126,13 +117,17 @@ class NetEqImpl : public webrtc::NetEq { int RegisterExternalDecoder(AudioDecoder* decoder, NetEqDecoder codec, const std::string& codec_name, - uint8_t rtp_payload_type, - int sample_rate_hz) override; + uint8_t rtp_payload_type) override; + + bool RegisterPayloadType(int rtp_payload_type, + const SdpAudioFormat& audio_format) override; // Removes |rtp_payload_type| from the codec database. Returns 0 on success, // -1 on failure. int RemovePayloadType(uint8_t rtp_payload_type) override; + void RemoveAllPayloadTypes() override; + bool SetMinimumDelay(int delay_ms) override; bool SetMaximumDelay(int delay_ms) override; @@ -145,6 +140,8 @@ class NetEqImpl : public webrtc::NetEq { int CurrentDelayMs() const override; + int FilteredCurrentDelayMs() const override; + // Sets the playout mode to |mode|. // Deprecated. // TODO(henrik.lundin) Delete. @@ -177,6 +174,11 @@ class NetEqImpl : public webrtc::NetEq { int last_output_sample_rate_hz() const override; + rtc::Optional GetDecoder(int payload_type) const override; + + rtc::Optional GetDecoderFormat( + int payload_type) const override; + int SetTargetNumberOfChannels() override; int SetTargetSampleRate() override; @@ -219,8 +221,7 @@ class NetEqImpl : public webrtc::NetEq { // TODO(hlundin): Merge this with InsertPacket above? int InsertPacketInternal(const WebRtcRTPHeader& rtp_header, rtc::ArrayView payload, - uint32_t receive_timestamp, - bool is_sync_packet) + uint32_t receive_timestamp) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); // Delivers 10 ms of audio data. The data is written to |audio_frame|. @@ -356,7 +357,7 @@ class NetEqImpl : public webrtc::NetEq { const std::unique_ptr dtmf_tone_generator_ GUARDED_BY(crit_sect_); const std::unique_ptr packet_buffer_ GUARDED_BY(crit_sect_); - const std::unique_ptr payload_splitter_ + const std::unique_ptr red_payload_splitter_ GUARDED_BY(crit_sect_); const std::unique_ptr timestamp_scaler_ GUARDED_BY(crit_sect_); @@ -394,8 +395,8 @@ class NetEqImpl : public webrtc::NetEq { bool new_codec_ GUARDED_BY(crit_sect_); uint32_t timestamp_ GUARDED_BY(crit_sect_); bool reset_decoder_ GUARDED_BY(crit_sect_); - uint8_t current_rtp_payload_type_ GUARDED_BY(crit_sect_); - uint8_t current_cng_rtp_payload_type_ GUARDED_BY(crit_sect_); + rtc::Optional current_rtp_payload_type_ GUARDED_BY(crit_sect_); + rtc::Optional current_cng_rtp_payload_type_ GUARDED_BY(crit_sect_); uint32_t ssrc_ GUARDED_BY(crit_sect_); bool first_packet_ GUARDED_BY(crit_sect_); int error_code_ GUARDED_BY(crit_sect_); // Store last error code. @@ -403,7 +404,7 @@ class NetEqImpl : public webrtc::NetEq { const BackgroundNoiseMode background_noise_mode_ GUARDED_BY(crit_sect_); NetEqPlayoutMode playout_mode_ GUARDED_BY(crit_sect_); bool enable_fast_accelerate_ GUARDED_BY(crit_sect_); - std::unique_ptr nack_ GUARDED_BY(crit_sect_); + std::unique_ptr nack_ GUARDED_BY(crit_sect_); bool nack_enabled_ GUARDED_BY(crit_sect_); const bool enable_muted_state_ GUARDED_BY(crit_sect_); AudioFrame::VADActivity last_vad_activity_ GUARDED_BY(crit_sect_) = diff --git a/include/webrtc/modules/audio_coding/neteq/packet.h b/include/webrtc/modules/audio_coding/neteq/packet.h index d6f64c7..7d91f25 100644 --- a/include/webrtc/modules/audio_coding/neteq/packet.h +++ b/include/webrtc/modules/audio_coding/neteq/packet.h @@ -14,72 +14,111 @@ #include #include +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/base/buffer.h" #include "webrtc/modules/audio_coding/neteq/tick_timer.h" -#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { // Struct for holding RTP packets. struct Packet { - RTPHeader header; + struct Priority { + Priority() : codec_level(0), red_level(0) {} + Priority(int codec_level, int red_level) + : codec_level(codec_level), red_level(red_level) { + CheckInvariant(); + } + + int codec_level; + int red_level; + + // Priorities are sorted low-to-high, first on the level the codec + // prioritizes it, then on the level of RED packet it is; i.e. if it is a + // primary or secondary payload of a RED packet. For example: with Opus, an + // Fec packet (which the decoder prioritizes lower than a regular packet) + // will not be used if there is _any_ RED payload for the same + // timeframe. The highest priority packet will have levels {0, 0}. Negative + // priorities are not allowed. + bool operator<(const Priority& b) const { + CheckInvariant(); + b.CheckInvariant(); + if (codec_level == b.codec_level) + return red_level < b.red_level; + + return codec_level < b.codec_level; + } + bool operator==(const Priority& b) const { + CheckInvariant(); + b.CheckInvariant(); + return codec_level == b.codec_level && red_level == b.red_level; + } + bool operator!=(const Priority& b) const { return !(*this == b); } + bool operator>(const Priority& b) const { return b < *this; } + bool operator<=(const Priority& b) const { return !(b > *this); } + bool operator>=(const Priority& b) const { return !(b < *this); } + + private: + void CheckInvariant() const { + RTC_DCHECK_GE(codec_level, 0); + RTC_DCHECK_GE(red_level, 0); + } + }; + + uint32_t timestamp; + uint16_t sequence_number; + uint8_t payload_type; // Datagram excluding RTP header and header extension. - uint8_t* payload = nullptr; - size_t payload_length = 0; - bool primary = true; // Primary, i.e., not redundant payload. - bool sync_packet = false; + rtc::Buffer payload; + Priority priority; std::unique_ptr waiting_time; + std::unique_ptr frame; Packet(); + Packet(Packet&& b); ~Packet(); + // Packets should generally be moved around but sometimes it's useful to make + // a copy, for example for testing purposes. NOTE: Will only work for + // un-parsed packets, i.e. |frame| must be unset. The payload will, however, + // be copied. |waiting_time| will also not be copied. + Packet Clone() const; + + Packet& operator=(Packet&& b); + // Comparison operators. Establish a packet ordering based on (1) timestamp, - // (2) sequence number, (3) regular packet vs sync-packet and (4) redundancy. + // (2) sequence number and (3) redundancy. // Timestamp and sequence numbers are compared taking wrap-around into - // account. If both timestamp and sequence numbers are identical and one of - // the packets is sync-packet, the regular packet is considered earlier. For - // two regular packets with the same sequence number and timestamp a primary - // payload is considered "smaller" than a secondary. + // account. For two packets with the same sequence number and timestamp a + // primary payload is considered "smaller" than a secondary. bool operator==(const Packet& rhs) const { - return (this->header.timestamp == rhs.header.timestamp && - this->header.sequenceNumber == rhs.header.sequenceNumber && - this->primary == rhs.primary && - this->sync_packet == rhs.sync_packet); + return (this->timestamp == rhs.timestamp && + this->sequence_number == rhs.sequence_number && + this->priority == rhs.priority); } bool operator!=(const Packet& rhs) const { return !operator==(rhs); } bool operator<(const Packet& rhs) const { - if (this->header.timestamp == rhs.header.timestamp) { - if (this->header.sequenceNumber == rhs.header.sequenceNumber) { - // Timestamp and sequence numbers are identical. A sync packet should - // be recognized "larger" (i.e. "later") compared to a "network packet" - // (regular packet from network not sync-packet). If none of the packets - // are sync-packets, then deem the left hand side to be "smaller" - // (i.e., "earlier") if it is primary, and right hand side is not. - // - // The condition on sync packets to be larger than "network packets," - // given same RTP sequence number and timestamp, guarantees that a - // "network packet" to be inserted in an earlier position into - // |packet_buffer_| compared to a sync packet of same timestamp and - // sequence number. - if (rhs.sync_packet) - return true; - if (this->sync_packet) - return false; - return (this->primary && !rhs.primary); + if (this->timestamp == rhs.timestamp) { + if (this->sequence_number == rhs.sequence_number) { + // Timestamp and sequence numbers are identical - deem the left hand + // side to be "smaller" (i.e., "earlier") if it has higher priority. + return this->priority < rhs.priority; } - return (static_cast(rhs.header.sequenceNumber - - this->header.sequenceNumber) < 0xFFFF / 2); + return (static_cast(rhs.sequence_number - + this->sequence_number) < 0xFFFF / 2); } - return (static_cast(rhs.header.timestamp - - this->header.timestamp) < 0xFFFFFFFF / 2); + return (static_cast(rhs.timestamp - this->timestamp) < + 0xFFFFFFFF / 2); } bool operator>(const Packet& rhs) const { return rhs.operator<(*this); } bool operator<=(const Packet& rhs) const { return !operator>(rhs); } bool operator>=(const Packet& rhs) const { return !operator<(rhs); } + + bool empty() const { return !frame && payload.empty(); } }; // A list of packets. -typedef std::list PacketList; +typedef std::list PacketList; } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_PACKET_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/packet_buffer.h b/include/webrtc/modules/audio_coding/neteq/packet_buffer.h index 6867b4c..a26d6c5 100644 --- a/include/webrtc/modules/audio_coding/neteq/packet_buffer.h +++ b/include/webrtc/modules/audio_coding/neteq/packet_buffer.h @@ -12,7 +12,9 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_PACKET_BUFFER_H_ #include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" #include "webrtc/modules/audio_coding/neteq/packet.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -49,7 +51,7 @@ class PacketBuffer { // the packet object. // Returns PacketBuffer::kOK on success, PacketBuffer::kFlushed if the buffer // was flushed due to overfilling. - virtual int InsertPacket(Packet* packet); + virtual int InsertPacket(Packet&& packet); // Inserts a list of packets into the buffer. The buffer will take over // ownership of the packet objects. @@ -59,10 +61,11 @@ class PacketBuffer { // The last three parameters are included for legacy compatibility. // TODO(hlundin): Redesign to not use current_*_payload_type and // decoder_database. - virtual int InsertPacketList(PacketList* packet_list, - const DecoderDatabase& decoder_database, - uint8_t* current_rtp_payload_type, - uint8_t* current_cng_rtp_payload_type); + virtual int InsertPacketList( + PacketList* packet_list, + const DecoderDatabase& decoder_database, + rtc::Optional* current_rtp_payload_type, + rtc::Optional* current_cng_rtp_payload_type); // Gets the timestamp for the first packet in the buffer and writes it to the // output variable |next_timestamp|. @@ -78,17 +81,13 @@ class PacketBuffer { virtual int NextHigherTimestamp(uint32_t timestamp, uint32_t* next_timestamp) const; - // Returns a (constant) pointer the RTP header of the first packet in the - // buffer. Returns NULL if the buffer is empty. - virtual const RTPHeader* NextRtpHeader() const; + // Returns a (constant) pointer to the first packet in the buffer. Returns + // NULL if the buffer is empty. + virtual const Packet* PeekNextPacket() const; - // Extracts the first packet in the buffer and returns a pointer to it. - // Returns NULL if the buffer is empty. The caller is responsible for deleting - // the packet. - // Subsequent packets with the same timestamp as the one extracted will be - // discarded and properly deleted. The number of discarded packets will be - // written to the output variable |discard_count|. - virtual Packet* GetNextPacket(size_t* discard_count); + // Extracts the first packet in the buffer and returns it. + // Returns an empty optional if the buffer is empty. + virtual rtc::Optional GetNextPacket(); // Discards the first packet in the buffer. The packet is deleted. // Returns PacketBuffer::kBufferEmpty if the buffer is empty, @@ -107,26 +106,19 @@ class PacketBuffer { // Discards all packets that are (strictly) older than timestamp_limit. virtual int DiscardAllOldPackets(uint32_t timestamp_limit); + // Removes all packets with a specific payload type from the buffer. + virtual void DiscardPacketsWithPayloadType(uint8_t payload_type); + // Returns the number of packets in the buffer, including duplicates and // redundant packets. virtual size_t NumPacketsInBuffer() const; // Returns the number of samples in the buffer, including samples carried in // duplicate and redundant packets. - virtual size_t NumSamplesInBuffer(DecoderDatabase* decoder_database, - size_t last_decoded_length) const; + virtual size_t NumSamplesInBuffer(size_t last_decoded_length) const; virtual void BufferStat(int* num_packets, int* max_num_packets) const; - // Static method that properly deletes the first packet, and its payload - // array, in |packet_list|. Returns false if |packet_list| already was empty, - // otherwise true. - static bool DeleteFirstPacket(PacketList* packet_list); - - // Static method that properly deletes all packets, and their payload arrays, - // in |packet_list|. - static void DeleteAllPackets(PacketList* packet_list); - // Static method returning true if |timestamp| is older than |timestamp_limit| // but less than |horizon_samples| behind |timestamp_limit|. For instance, // with timestamp_limit = 100 and horizon_samples = 10, a timestamp in the diff --git a/include/webrtc/modules/audio_coding/neteq/payload_splitter.h b/include/webrtc/modules/audio_coding/neteq/payload_splitter.h deleted file mode 100644 index b0c4b5f..0000000 --- a/include/webrtc/modules/audio_coding/neteq/payload_splitter.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_PAYLOAD_SPLITTER_H_ -#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_PAYLOAD_SPLITTER_H_ - -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/neteq/packet.h" - -namespace webrtc { - -// Forward declarations. -class DecoderDatabase; - -// This class handles splitting of payloads into smaller parts. -// The class does not have any member variables, and the methods could have -// been made static. The reason for not making them static is testability. -// With this design, the splitting functionality can be mocked during testing -// of the NetEqImpl class. -class PayloadSplitter { - public: - enum SplitterReturnCodes { - kOK = 0, - kNoSplit = 1, - kTooLargePayload = -1, - kFrameSplitError = -2, - kUnknownPayloadType = -3, - kRedLengthMismatch = -4, - kFecSplitError = -5, - }; - - PayloadSplitter() {} - - virtual ~PayloadSplitter() {} - - // Splits each packet in |packet_list| into its separate RED payloads. Each - // RED payload is packetized into a Packet. The original elements in - // |packet_list| are properly deleted, and replaced by the new packets. - // Note that all packets in |packet_list| must be RED payloads, i.e., have - // RED headers according to RFC 2198 at the very beginning of the payload. - // Returns kOK or an error. - virtual int SplitRed(PacketList* packet_list); - - // Iterates through |packet_list| and, duplicate each audio payload that has - // FEC as new packet for redundant decoding. The decoder database is needed to - // get information about which payload type each packet contains. - virtual int SplitFec(PacketList* packet_list, - DecoderDatabase* decoder_database); - - // Checks all packets in |packet_list|. Packets that are DTMF events or - // comfort noise payloads are kept. Except that, only one single payload type - // is accepted. Any packet with another payload type is discarded. - virtual int CheckRedPayloads(PacketList* packet_list, - const DecoderDatabase& decoder_database); - - // Iterates through |packet_list| and, if possible, splits each audio payload - // into suitable size chunks. The result is written back to |packet_list| as - // new packets. The decoder database is needed to get information about which - // payload type each packet contains. - virtual int SplitAudio(PacketList* packet_list, - const DecoderDatabase& decoder_database); - - private: - // Splits the payload in |packet|. The payload is assumed to be from a - // sample-based codec. - virtual void SplitBySamples(const Packet* packet, - size_t bytes_per_ms, - uint32_t timestamps_per_ms, - PacketList* new_packets); - - // Splits the payload in |packet|. The payload will be split into chunks of - // size |bytes_per_frame|, corresponding to a |timestamps_per_frame| - // RTP timestamps. - virtual int SplitByFrames(const Packet* packet, - size_t bytes_per_frame, - uint32_t timestamps_per_frame, - PacketList* new_packets); - - RTC_DISALLOW_COPY_AND_ASSIGN(PayloadSplitter); -}; - -} // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_PAYLOAD_SPLITTER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/post_decode_vad.h b/include/webrtc/modules/audio_coding/neteq/post_decode_vad.h index 7bf5ad1..dd64818 100644 --- a/include/webrtc/modules/audio_coding/neteq/post_decode_vad.h +++ b/include/webrtc/modules/audio_coding/neteq/post_decode_vad.h @@ -13,10 +13,10 @@ #include // size_t +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/base/constructormagic.h" #include "webrtc/common_audio/vad/include/webrtc_vad.h" #include "webrtc/common_types.h" // NULL -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/neteq/defines.h" #include "webrtc/modules/audio_coding/neteq/packet.h" #include "webrtc/typedefs.h" diff --git a/include/webrtc/modules/audio_coding/neteq/red_payload_splitter.h b/include/webrtc/modules/audio_coding/neteq/red_payload_splitter.h new file mode 100644 index 0000000..deb86eb --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/red_payload_splitter.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_RED_PAYLOAD_SPLITTER_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_RED_PAYLOAD_SPLITTER_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_coding/neteq/packet.h" + +namespace webrtc { + +// Forward declarations. +class DecoderDatabase; + +// This class handles splitting of RED payloads into smaller parts. +// Codec-specific packet splitting can be performed by +// AudioDecoder::ParsePayload. +class RedPayloadSplitter { + public: + RedPayloadSplitter() {} + + virtual ~RedPayloadSplitter() {} + + // Splits each packet in |packet_list| into its separate RED payloads. Each + // RED payload is packetized into a Packet. The original elements in + // |packet_list| are properly deleted, and replaced by the new packets. + // Note that all packets in |packet_list| must be RED payloads, i.e., have + // RED headers according to RFC 2198 at the very beginning of the payload. + // Returns kOK or an error. + virtual bool SplitRed(PacketList* packet_list); + + // Checks all packets in |packet_list|. Packets that are DTMF events or + // comfort noise payloads are kept. Except that, only one single payload type + // is accepted. Any packet with another payload type is discarded. Returns + // the number of discarded packets. + virtual int CheckRedPayloads(PacketList* packet_list, + const DecoderDatabase& decoder_database); + + private: + RTC_DISALLOW_COPY_AND_ASSIGN(RedPayloadSplitter); +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_RED_PAYLOAD_SPLITTER_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/rtcp.h b/include/webrtc/modules/audio_coding/neteq/rtcp.h index eacb328..d222cea 100644 --- a/include/webrtc/modules/audio_coding/neteq/rtcp.h +++ b/include/webrtc/modules/audio_coding/neteq/rtcp.h @@ -48,7 +48,7 @@ class Rtcp { // report was generated. uint32_t expected_prior_; // Expected number of packets, at the time of the // last report. - uint32_t jitter_; // Current jitter value. + int64_t jitter_; // Current jitter value in Q4. int32_t transit_; // Clock difference for previous packet. RTC_DISALLOW_COPY_AND_ASSIGN(Rtcp); diff --git a/include/webrtc/modules/audio_coding/neteq/tools/audio_sink.h b/include/webrtc/modules/audio_coding/neteq/tools/audio_sink.h index 489a8b2..8a5479e 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/audio_sink.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/audio_sink.h @@ -47,10 +47,7 @@ class AudioSinkFork : public AudioSink { AudioSinkFork(AudioSink* left, AudioSink* right) : left_sink_(left), right_sink_(right) {} - bool WriteArray(const int16_t* audio, size_t num_samples) override { - return left_sink_->WriteArray(audio, num_samples) && - right_sink_->WriteArray(audio, num_samples); - } + bool WriteArray(const int16_t* audio, size_t num_samples) override; private: AudioSink* left_sink_; @@ -58,6 +55,7 @@ class AudioSinkFork : public AudioSink { RTC_DISALLOW_COPY_AND_ASSIGN(AudioSinkFork); }; + } // namespace test } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h b/include/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h index 6972303..d1f8877 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h @@ -31,9 +31,7 @@ class ConstantPcmPacketSource : public PacketSource { int sample_rate_hz, int payload_type); - // Returns a pointer to the next packet. Will never return NULL. That is, - // the source is infinite. - Packet* NextPacket() override; + std::unique_ptr NextPacket() override; private: void WriteHeader(uint8_t* packet_memory); diff --git a/include/webrtc/modules/audio_coding/neteq/tools/encode_neteq_input.h b/include/webrtc/modules/audio_coding/neteq/tools/encode_neteq_input.h new file mode 100644 index 0000000..7c165a8 --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/encode_neteq_input.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_ENCODE_NETEQ_INPUT_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_ENCODE_NETEQ_INPUT_H_ + +#include + +#include "webrtc/modules/audio_coding/codecs/audio_encoder.h" +#include "webrtc/modules/audio_coding/neteq/tools/neteq_input.h" +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { +namespace test { + +// This class provides a NetEqInput that takes audio from a generator object and +// encodes it using a given audio encoder. +class EncodeNetEqInput : public NetEqInput { + public: + // Generator class, to be provided to the EncodeNetEqInput constructor. + class Generator { + public: + virtual ~Generator() = default; + // Returns the next num_samples values from the signal generator. + virtual rtc::ArrayView Generate(size_t num_samples) = 0; + }; + + // The source will end after the given input duration. + EncodeNetEqInput(std::unique_ptr generator, + std::unique_ptr encoder, + int64_t input_duration_ms); + + rtc::Optional NextPacketTime() const override; + + rtc::Optional NextOutputEventTime() const override; + + std::unique_ptr PopPacket() override; + + void AdvanceOutputEvent() override; + + bool ended() const override { + return next_output_event_ms_ <= input_duration_ms_; + } + + rtc::Optional NextHeader() const override; + + private: + static constexpr int64_t kOutputPeriodMs = 10; + + void CreatePacket(); + + std::unique_ptr generator_; + std::unique_ptr encoder_; + std::unique_ptr packet_data_; + uint32_t rtp_timestamp_ = 0; + int16_t sequence_number_ = 0; + int64_t next_packet_time_ms_ = 0; + int64_t next_output_event_ms_ = 0; + const int64_t input_duration_ms_; +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_ENCODE_NETEQ_INPUT_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/fake_decode_from_file.h b/include/webrtc/modules/audio_coding/neteq/tools/fake_decode_from_file.h new file mode 100644 index 0000000..9f91c81 --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/fake_decode_from_file.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_FAKE_DECODE_FROM_FILE_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_FAKE_DECODE_FROM_FILE_H_ + +#include + +#include "webrtc/api/audio_codecs/audio_decoder.h" +#include "webrtc/base/array_view.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" + +namespace webrtc { +namespace test { + +// Provides an AudioDecoder implementation that delivers audio data from a file. +// The "encoded" input should contain information about what RTP timestamp the +// encoding represents, and how many samples the decoder should produce for that +// encoding. A helper method PrepareEncoded is provided to prepare such +// encodings. If packets are missing, as determined from the timestamps, the +// file reading will skip forward to match the loss. +class FakeDecodeFromFile : public AudioDecoder { + public: + FakeDecodeFromFile(std::unique_ptr input, + int sample_rate_hz, + bool stereo) + : input_(std::move(input)), + sample_rate_hz_(sample_rate_hz), + stereo_(stereo) {} + + ~FakeDecodeFromFile() = default; + + void Reset() override {} + + int SampleRateHz() const override { return sample_rate_hz_; } + + size_t Channels() const override { return stereo_ ? 2 : 1; } + + int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int sample_rate_hz, + int16_t* decoded, + SpeechType* speech_type) override; + + // Helper method. Writes |timestamp|, |samples| and + // |original_payload_size_bytes| to |encoded| in a format that the + // FakeDecodeFromFile decoder will understand. |encoded| must be at least 12 + // bytes long. + static void PrepareEncoded(uint32_t timestamp, + size_t samples, + size_t original_payload_size_bytes, + rtc::ArrayView encoded); + + private: + std::unique_ptr input_; + rtc::Optional next_timestamp_from_input_; + const int sample_rate_hz_; + const bool stereo_; + size_t last_decoded_length_ = 0; + bool cng_mode_ = false; +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_FAKE_DECODE_FROM_FILE_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h index 8999d02..208d8da 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h @@ -14,7 +14,7 @@ #include #include -#include "webrtc/modules/audio_coding/codecs/audio_decoder.h" +#include "webrtc/api/audio_codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/include/module_common_types.h" @@ -27,7 +27,9 @@ class NetEqExternalDecoderTest { static const int kOutputLengthMs = 10; // The external decoder |decoder| is suppose to be of type |codec|. - NetEqExternalDecoderTest(NetEqDecoder codec, AudioDecoder* decoder); + NetEqExternalDecoderTest(NetEqDecoder codec, + int sample_rate_hz, + AudioDecoder* decoder); virtual ~NetEqExternalDecoderTest() { } diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_input.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_input.h new file mode 100644 index 0000000..be08a79 --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_input.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_INPUT_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_INPUT_H_ + +#include +#include + +#include "webrtc/base/buffer.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet.h" +#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { +namespace test { + +// Interface class for input to the NetEqTest class. +class NetEqInput { + public: + struct PacketData { + WebRtcRTPHeader header; + rtc::Buffer payload; + double time_ms; + }; + + virtual ~NetEqInput() = default; + + // Returns at what time (in ms) NetEq::InsertPacket should be called next, or + // empty if the source is out of packets. + virtual rtc::Optional NextPacketTime() const = 0; + + // Returns at what time (in ms) NetEq::GetAudio should be called next, or + // empty if no more output events are available. + virtual rtc::Optional NextOutputEventTime() const = 0; + + // Returns the time (in ms) for the next event from either NextPacketTime() + // or NextOutputEventTime(), or empty if both are out of events. + rtc::Optional NextEventTime() const { + const auto a = NextPacketTime(); + const auto b = NextOutputEventTime(); + // Return the minimum of non-empty |a| and |b|, or empty if both are empty. + if (a) { + return b ? rtc::Optional(std::min(*a, *b)) : a; + } + return b ? b : rtc::Optional(); + } + + // Returns the next packet to be inserted into NetEq. The packet following the + // returned one is pre-fetched in the NetEqInput object, such that future + // calls to NextPacketTime() or NextHeader() will return information from that + // packet. + virtual std::unique_ptr PopPacket() = 0; + + // Move to the next output event. This will make NextOutputEventTime() return + // a new value (potentially the same if several output events share the same + // time). + virtual void AdvanceOutputEvent() = 0; + + // Returns true if the source has come to an end. An implementation must + // eventually return true from this method, or the test will end up in an + // infinite loop. + virtual bool ended() const = 0; + + // Returns the RTP header for the next packet, i.e., the packet that will be + // delivered next by PopPacket(). + virtual rtc::Optional NextHeader() const = 0; +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_INPUT_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_packet_source_input.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_packet_source_input.h new file mode 100644 index 0000000..35b54fa --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_packet_source_input.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PACKET_SOURCE_INPUT_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PACKET_SOURCE_INPUT_H_ + +#include +#include + +#include "webrtc/modules/audio_coding/neteq/tools/neteq_input.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" + +namespace webrtc { +namespace test { + +class RtpFileSource; +class RtcEventLogSource; + +// An adapter class to dress up a PacketSource object as a NetEqInput. +class NetEqPacketSourceInput : public NetEqInput { + public: + using RtpHeaderExtensionMap = std::map; + + NetEqPacketSourceInput(); + rtc::Optional NextPacketTime() const override; + std::unique_ptr PopPacket() override; + rtc::Optional NextHeader() const override; + bool ended() const override { return !next_output_event_ms_; } + + protected: + virtual PacketSource* source() = 0; + void LoadNextPacket(); + + rtc::Optional next_output_event_ms_; + + private: + std::unique_ptr packet_; +}; + +// Implementation of NetEqPacketSourceInput to be used with an RtpFileSource. +class NetEqRtpDumpInput final : public NetEqPacketSourceInput { + public: + NetEqRtpDumpInput(const std::string& file_name, + const RtpHeaderExtensionMap& hdr_ext_map); + + rtc::Optional NextOutputEventTime() const override; + void AdvanceOutputEvent() override; + + protected: + PacketSource* source() override; + + private: + static constexpr int64_t kOutputPeriodMs = 10; + + std::unique_ptr source_; +}; + +// Implementation of NetEqPacketSourceInput to be used with an +// RtcEventLogSource. +class NetEqEventLogInput final : public NetEqPacketSourceInput { + public: + NetEqEventLogInput(const std::string& file_name, + const RtpHeaderExtensionMap& hdr_ext_map); + + rtc::Optional NextOutputEventTime() const override; + void AdvanceOutputEvent() override; + + protected: + PacketSource* source() override; + + private: + std::unique_ptr source_; +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PACKET_SOURCE_INPUT_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h index 11afe68..0ed7dfb 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h @@ -14,12 +14,13 @@ #include #include #include -#include "testing/gtest/include/gtest/gtest.h" + #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" #include "webrtc/modules/include/module_common_types.h" +#include "webrtc/test/gtest.h" #include "webrtc/typedefs.h" using google::RegisterFlagValidator; @@ -51,6 +52,7 @@ class UniformLoss : public LossModel { class GilbertElliotLoss : public LossModel { public: GilbertElliotLoss(double prob_trans_11, double prob_trans_01); + ~GilbertElliotLoss() override; bool Lost() override; private: @@ -68,7 +70,7 @@ class NetEqQualityTest : public ::testing::Test { int in_sampling_khz, int out_sampling_khz, NetEqDecoder decoder_type); - virtual ~NetEqQualityTest(); + ~NetEqQualityTest() override; void SetUp() override; diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.h new file mode 100644 index 0000000..ee1e4ae --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_replacement_input.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_REPLACEMENT_INPUT_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_REPLACEMENT_INPUT_H_ + +#include +#include + +#include "webrtc/modules/audio_coding/neteq/tools/neteq_input.h" + +namespace webrtc { +namespace test { + +// This class converts the packets from a NetEqInput to fake encodings to be +// decoded by a FakeDecodeFromFile decoder. +class NetEqReplacementInput : public NetEqInput { + public: + NetEqReplacementInput(std::unique_ptr source, + uint8_t replacement_payload_type, + const std::set& comfort_noise_types, + const std::set& forbidden_types); + + rtc::Optional NextPacketTime() const override; + rtc::Optional NextOutputEventTime() const override; + std::unique_ptr PopPacket() override; + void AdvanceOutputEvent() override; + bool ended() const override; + rtc::Optional NextHeader() const override; + + private: + void ReplacePacket(); + + std::unique_ptr source_; + const uint8_t replacement_payload_type_; + const std::set comfort_noise_types_; + const std::set forbidden_types_; + std::unique_ptr packet_; // The next packet to deliver. + uint32_t last_frame_size_timestamps_ = 960; // Initial guess: 20 ms @ 48 kHz. +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_REPLACEMENT_INPUT_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/neteq_test.h b/include/webrtc/modules/audio_coding/neteq/tools/neteq_test.h new file mode 100644 index 0000000..619626c --- /dev/null +++ b/include/webrtc/modules/audio_coding/neteq/tools/neteq_test.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_ +#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_ + +#include +#include +#include +#include + +#include "webrtc/modules/audio_coding/neteq/include/neteq.h" +#include "webrtc/modules/audio_coding/neteq/tools/audio_sink.h" +#include "webrtc/modules/audio_coding/neteq/tools/neteq_input.h" + +namespace webrtc { +namespace test { + +class NetEqTestErrorCallback { + public: + virtual ~NetEqTestErrorCallback() = default; + virtual void OnInsertPacketError(int error_code, + const NetEqInput::PacketData& packet) {} + virtual void OnGetAudioError(int error_code) {} +}; + +class DefaultNetEqTestErrorCallback : public NetEqTestErrorCallback { + void OnInsertPacketError(int error_code, + const NetEqInput::PacketData& packet) override; + void OnGetAudioError(int error_code) override; +}; + +// Class that provides an input--output test for NetEq. The input (both packets +// and output events) is provided by a NetEqInput object, while the output is +// directed to an AudioSink object. +class NetEqTest { + public: + using DecoderMap = std::map >; + + struct ExternalDecoderInfo { + AudioDecoder* decoder; + NetEqDecoder codec; + std::string codec_name; + }; + + using ExtDecoderMap = std::map; + + // Sets up the test with given configuration, codec mappings, input, ouput, + // and callback objects for error reporting. + NetEqTest(const NetEq::Config& config, + const DecoderMap& codecs, + const ExtDecoderMap& ext_codecs, + std::unique_ptr input, + std::unique_ptr output, + NetEqTestErrorCallback* error_callback); + + ~NetEqTest() = default; + + // Runs the test. Returns the duration of the produced audio in ms. + int64_t Run(); + + // Returns the statistics from NetEq. + NetEqNetworkStatistics SimulationStats(); + + private: + void RegisterDecoders(const DecoderMap& codecs); + void RegisterExternalDecoders(const ExtDecoderMap& codecs); + + std::unique_ptr neteq_; + std::unique_ptr input_; + std::unique_ptr output_; + NetEqTestErrorCallback* error_callback_ = nullptr; + int sample_rate_hz_; +}; + +} // namespace test +} // namespace webrtc +#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_ diff --git a/include/webrtc/modules/audio_coding/neteq/tools/packet.h b/include/webrtc/modules/audio_coding/neteq/tools/packet.h index 86eedc0..d150805 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/packet.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/packet.h @@ -62,7 +62,7 @@ class Packet { size_t virtual_packet_length_bytes, double time_ms); - virtual ~Packet() {} + virtual ~Packet(); // Parses the first bytes of the RTP payload, interpreting them as RED headers // according to RFC 2198. The headers will be inserted into |headers|. The diff --git a/include/webrtc/modules/audio_coding/neteq/tools/packet_source.h b/include/webrtc/modules/audio_coding/neteq/tools/packet_source.h index 804a94d..caae4ae 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/packet_source.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/packet_source.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_PACKET_SOURCE_H_ #include +#include #include "webrtc/base/constructormagic.h" #include "webrtc/modules/audio_coding/neteq/tools/packet.h" @@ -23,21 +24,16 @@ namespace test { // Interface class for an object delivering RTP packets to test applications. class PacketSource { public: - PacketSource() : use_ssrc_filter_(false), ssrc_(0) {} - virtual ~PacketSource() {} + PacketSource(); + virtual ~PacketSource(); - // Returns a pointer to the next packet. Returns NULL if the source is - // depleted, or if an error occurred. - virtual Packet* NextPacket() = 0; + // Returns next packet. Returns nullptr if the source is depleted, or if an + // error occurred. + virtual std::unique_ptr NextPacket() = 0; - virtual void FilterOutPayloadType(uint8_t payload_type) { - filter_.set(payload_type, true); - } + virtual void FilterOutPayloadType(uint8_t payload_type); - virtual void SelectSsrc(uint32_t ssrc) { - use_ssrc_filter_ = true; - ssrc_ = ssrc; - } + virtual void SelectSsrc(uint32_t ssrc); protected: std::bitset<128> filter_; // Payload type is 7 bits in the RFC. diff --git a/include/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/include/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h index ad7add1..fad491e 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h @@ -15,7 +15,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/call/rtc_event_log_parser.h" +#include "webrtc/logging/rtc_event_log/rtc_event_log_parser.h" #include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" @@ -38,9 +38,7 @@ class RtcEventLogSource : public PacketSource { // Registers an RTP header extension and binds it to |id|. virtual bool RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); - // Returns a pointer to the next packet. Returns NULL if end of file was - // reached. - Packet* NextPacket() override; + std::unique_ptr NextPacket() override; // Returns the timestamp of the next audio output event, in milliseconds. The // maximum value of int64_t is returned if there are no more audio output diff --git a/include/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h b/include/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h index b02e16a..1b98d6c 100644 --- a/include/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h +++ b/include/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h @@ -44,9 +44,7 @@ class RtpFileSource : public PacketSource { // Registers an RTP header extension and binds it to |id|. virtual bool RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); - // Returns a pointer to the next packet. Returns NULL if end of file was - // reached, or if a the data was corrupt. - Packet* NextPacket() override; + std::unique_ptr NextPacket() override; private: static const int kFirstLineLength = 40; diff --git a/include/webrtc/modules/audio_coding/test/APITest.h b/include/webrtc/modules/audio_coding/test/APITest.h index af2a3a1..99a7201 100644 --- a/include/webrtc/modules/audio_coding/test/APITest.h +++ b/include/webrtc/modules/audio_coding/test/APITest.h @@ -23,8 +23,6 @@ namespace webrtc { -class Config; - enum APITESTAction { TEST_CHANGE_CODEC_ONLY = 0, DTX_TEST = 1 @@ -32,7 +30,7 @@ enum APITESTAction { class APITest : public ACMTest { public: - explicit APITest(const Config& config); + APITest(); ~APITest(); void Perform(); diff --git a/include/webrtc/modules/audio_coding/test/Channel.h b/include/webrtc/modules/audio_coding/test/Channel.h index 5910fad..c45864a 100644 --- a/include/webrtc/modules/audio_coding/test/Channel.h +++ b/include/webrtc/modules/audio_coding/test/Channel.h @@ -47,7 +47,7 @@ class Channel : public AudioPacketizationCallback { public: Channel(int16_t chID = -1); - ~Channel(); + ~Channel() override; int32_t SendData(FrameType frameType, uint8_t payloadType, diff --git a/include/webrtc/modules/audio_coding/test/PCMFile.h b/include/webrtc/modules/audio_coding/test/PCMFile.h index 840933a..b5ced0b 100644 --- a/include/webrtc/modules/audio_coding/test/PCMFile.h +++ b/include/webrtc/modules/audio_coding/test/PCMFile.h @@ -26,11 +26,7 @@ class PCMFile { public: PCMFile(); PCMFile(uint32_t timestamp); - ~PCMFile() { - if (pcm_file_ != NULL) { - fclose(pcm_file_); - } - } + ~PCMFile(); void Open(const std::string& filename, uint16_t frequency, const char* mode, bool auto_rewind = false); diff --git a/include/webrtc/modules/audio_coding/test/TestAllCodecs.h b/include/webrtc/modules/audio_coding/test/TestAllCodecs.h index 6d6f380..7df139b 100644 --- a/include/webrtc/modules/audio_coding/test/TestAllCodecs.h +++ b/include/webrtc/modules/audio_coding/test/TestAllCodecs.h @@ -20,8 +20,6 @@ namespace webrtc { -class Config; - class TestPack : public AudioPacketizationCallback { public: TestPack(); diff --git a/include/webrtc/modules/audio_coding/test/TestRedFec.h b/include/webrtc/modules/audio_coding/test/TestRedFec.h index e936f75..09d9259 100644 --- a/include/webrtc/modules/audio_coding/test/TestRedFec.h +++ b/include/webrtc/modules/audio_coding/test/TestRedFec.h @@ -20,8 +20,6 @@ namespace webrtc { -class Config; - class TestRedFec : public ACMTest { public: explicit TestRedFec(); diff --git a/include/webrtc/modules/audio_coding/test/TestVADDTX.h b/include/webrtc/modules/audio_coding/test/TestVADDTX.h index 893babc..b7e9871 100644 --- a/include/webrtc/modules/audio_coding/test/TestVADDTX.h +++ b/include/webrtc/modules/audio_coding/test/TestVADDTX.h @@ -72,6 +72,7 @@ class TestVadDtx : public ACMTest { std::unique_ptr acm_receive_; std::unique_ptr channel_; std::unique_ptr monitor_; + uint32_t time_stamp_ = 0x12345678; }; // TestWebRtcVadDtx is to verify that the WebRTC VAD/DTX perform as they should. diff --git a/include/webrtc/modules/audio_coding/test/TimedTrace.h b/include/webrtc/modules/audio_coding/test/TimedTrace.h deleted file mode 100644 index 0793eb0..0000000 --- a/include/webrtc/modules/audio_coding/test/TimedTrace.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_CODING_TEST_TIMEDTRACE_H_ -#define WEBRTC_MODULES_AUDIO_CODING_TEST_TIMEDTRACE_H_ - -#include "webrtc/typedefs.h" - -#include -#include - -class TimedTrace { - public: - TimedTrace(); - ~TimedTrace(); - - void SetTimeEllapsed(double myTime); - double TimeEllapsed(); - void Tick10Msec(); - int16_t SetUp(char* fileName); - void TimedLogg(char* message); - - private: - static double _timeEllapsedSec; - static FILE* _timedTraceFile; - -}; - -#endif // WEBRTC_MODULES_AUDIO_CODING_TEST_TIMEDTRACE_H_ diff --git a/include/webrtc/modules/audio_coding/test/utility.h b/include/webrtc/modules/audio_coding/test/utility.h index 23869be..8af3675 100644 --- a/include/webrtc/modules/audio_coding/test/utility.h +++ b/include/webrtc/modules/audio_coding/test/utility.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_TEST_UTILITY_H_ #define WEBRTC_MODULES_AUDIO_CODING_TEST_UTILITY_H_ -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_coding/include/audio_coding_module.h" +#include "webrtc/test/gtest.h" namespace webrtc { @@ -83,6 +83,9 @@ class ACMTestTimer { unsigned long _hour; }; +// To avoid clashes with CircularBuffer in APM. +namespace test { + class CircularBuffer { public: CircularBuffer(uint32_t len); @@ -109,6 +112,8 @@ class CircularBuffer { double _sumSqr; }; +} // namespace test + int16_t ChooseCodec(CodecInst& codecInst); void PrintCodecs(); @@ -118,10 +123,8 @@ bool FixedPayloadTypeCodec(const char* payloadName); class VADCallback : public ACMVADCallback { public: VADCallback(); - ~VADCallback() { - } - int32_t InFrameType(FrameType frame_type); + int32_t InFrameType(FrameType frame_type) override; void PrintFrameTypes(); void Reset(); @@ -130,10 +133,6 @@ class VADCallback : public ACMVADCallback { uint32_t _numFrameTypes[5]; }; -void UseLegacyAcm(webrtc::Config* config); - -void UseNewAcm(webrtc::Config* config); - } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_CODING_TEST_UTILITY_H_ diff --git a/include/webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h b/include/webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h index e726c08..c2fbe98 100644 --- a/include/webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h +++ b/include/webrtc/modules/audio_conference_mixer/source/audio_conference_mixer_impl.h @@ -15,11 +15,11 @@ #include #include -#include "webrtc/engine_configurations.h" #include "webrtc/modules/audio_conference_mixer/include/audio_conference_mixer.h" #include "webrtc/modules/audio_conference_mixer/source/memory_pool.h" #include "webrtc/modules/audio_conference_mixer/source/time_scheduler.h" #include "webrtc/modules/include/module_common_types.h" +#include "webrtc/typedefs.h" namespace webrtc { class AudioProcessing; diff --git a/include/webrtc/modules/audio_conference_mixer/source/memory_pool.h b/include/webrtc/modules/audio_conference_mixer/source/memory_pool.h index 3c7e1b7..c0a8131 100644 --- a/include/webrtc/modules/audio_conference_mixer/source/memory_pool.h +++ b/include/webrtc/modules/audio_conference_mixer/source/memory_pool.h @@ -15,7 +15,7 @@ #include "webrtc/typedefs.h" -#if _WIN32 +#ifdef _WIN32 #include "webrtc/modules/audio_conference_mixer/source/memory_pool_win.h" #else #include "webrtc/modules/audio_conference_mixer/source/memory_pool_posix.h" diff --git a/include/webrtc/modules/audio_device/android/audio_common.h b/include/webrtc/modules/audio_device/android/audio_common.h index 4eecae4..5361865 100644 --- a/include/webrtc/modules/audio_device/android/audio_common.h +++ b/include/webrtc/modules/audio_device/android/audio_common.h @@ -14,10 +14,6 @@ namespace webrtc { const int kDefaultSampleRate = 44100; -const int kNumChannels = 1; -// Number of bytes per audio frame. -// Example: 16-bit PCM in mono => 1*(16/8)=2 [bytes/frame] -const size_t kBytesPerFrame = kNumChannels * (16 / 8); // Delay estimates for the two different supported modes. These values are based // on real-time round-trip delay estimates on a large set of devices and they // are lower bounds since the filter length is 128 ms, so the AEC works for diff --git a/include/webrtc/modules/audio_device/android/audio_device_template.h b/include/webrtc/modules/audio_device/android/audio_device_template.h index 719b4bd..f8307f5 100644 --- a/include/webrtc/modules/audio_device/android/audio_device_template.h +++ b/include/webrtc/modules/audio_device/android/audio_device_template.h @@ -11,16 +11,11 @@ #ifndef WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_AUDIO_DEVICE_TEMPLATE_H_ #define WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_AUDIO_DEVICE_TEMPLATE_H_ -#include - #include "webrtc/base/checks.h" +#include "webrtc/base/logging.h" #include "webrtc/base/thread_checker.h" #include "webrtc/modules/audio_device/android/audio_manager.h" #include "webrtc/modules/audio_device/audio_device_generic.h" -#include "webrtc/system_wrappers/include/trace.h" - -#define TAG "AudioDeviceTemplate" -#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) namespace webrtc { @@ -44,38 +39,42 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { output_(audio_manager_), input_(audio_manager_), initialized_(false) { + LOG(INFO) << __FUNCTION__; RTC_CHECK(audio_manager); audio_manager_->SetActiveAudioLayer(audio_layer); } - virtual ~AudioDeviceTemplate() { - } + virtual ~AudioDeviceTemplate() { LOG(INFO) << __FUNCTION__; } int32_t ActiveAudioLayer( AudioDeviceModule::AudioLayer& audioLayer) const override { + LOG(INFO) << __FUNCTION__; audioLayer = audio_layer_; return 0; } - int32_t Init() override { + InitStatus Init() override { + LOG(INFO) << __FUNCTION__; RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(!initialized_); - if (!audio_manager_->Init()) - return -1; + if (!audio_manager_->Init()) { + return InitStatus::OTHER_ERROR; + } if (output_.Init() != 0) { audio_manager_->Close(); - return -1; + return InitStatus::PLAYOUT_ERROR; } if (input_.Init() != 0) { output_.Terminate(); audio_manager_->Close(); - return -1; + return InitStatus::RECORDING_ERROR; } initialized_ = true; - return 0; + return InitStatus::OK; } int32_t Terminate() override { + LOG(INFO) << __FUNCTION__; RTC_DCHECK(thread_checker_.CalledOnValidThread()); int32_t err = input_.Terminate(); err |= output_.Terminate(); @@ -86,15 +85,18 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } bool Initialized() const override { + LOG(INFO) << __FUNCTION__; RTC_DCHECK(thread_checker_.CalledOnValidThread()); return initialized_; } int16_t PlayoutDevices() override { + LOG(INFO) << __FUNCTION__; return 1; } int16_t RecordingDevices() override { + LOG(INFO) << __FUNCTION__; return 1; } @@ -117,6 +119,7 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { int32_t SetPlayoutDevice(uint16_t index) override { // OK to use but it has no effect currently since device selection is // done using Andoid APIs instead. + LOG(INFO) << __FUNCTION__; return 0; } @@ -129,6 +132,7 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { int32_t SetRecordingDevice(uint16_t index) override { // OK to use but it has no effect currently since device selection is // done using Andoid APIs instead. + LOG(INFO) << __FUNCTION__; return 0; } @@ -139,34 +143,42 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } int32_t PlayoutIsAvailable(bool& available) override { + LOG(INFO) << __FUNCTION__; available = true; return 0; } int32_t InitPlayout() override { + LOG(INFO) << __FUNCTION__; return output_.InitPlayout(); } bool PlayoutIsInitialized() const override { + LOG(INFO) << __FUNCTION__; return output_.PlayoutIsInitialized(); } int32_t RecordingIsAvailable(bool& available) override { + LOG(INFO) << __FUNCTION__; available = true; return 0; } int32_t InitRecording() override { + LOG(INFO) << __FUNCTION__; return input_.InitRecording(); } bool RecordingIsInitialized() const override { + LOG(INFO) << __FUNCTION__; return input_.RecordingIsInitialized(); } int32_t StartPlayout() override { + LOG(INFO) << __FUNCTION__; if (!audio_manager_->IsCommunicationModeEnabled()) { - ALOGW("The application should use MODE_IN_COMMUNICATION audio mode!"); + LOG(WARNING) + << "The application should use MODE_IN_COMMUNICATION audio mode!"; } return output_.StartPlayout(); } @@ -175,23 +187,28 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { // Avoid using audio manger (JNI/Java cost) if playout was inactive. if (!Playing()) return 0; + LOG(INFO) << __FUNCTION__; int32_t err = output_.StopPlayout(); return err; } bool Playing() const override { + LOG(INFO) << __FUNCTION__; return output_.Playing(); } int32_t StartRecording() override { + LOG(INFO) << __FUNCTION__; if (!audio_manager_->IsCommunicationModeEnabled()) { - ALOGW("The application should use MODE_IN_COMMUNICATION audio mode!"); + LOG(WARNING) + << "The application should use MODE_IN_COMMUNICATION audio mode!"; } return input_.StartRecording(); } int32_t StopRecording() override { // Avoid using audio manger (JNI/Java cost) if recording was inactive. + LOG(INFO) << __FUNCTION__; if (!Recording()) return 0; int32_t err = input_.StopRecording(); @@ -210,6 +227,7 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } bool AGC() const override { + LOG(INFO) << __FUNCTION__; return false; } @@ -226,38 +244,47 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } int32_t InitSpeaker() override { + LOG(INFO) << __FUNCTION__; return 0; } bool SpeakerIsInitialized() const override { + LOG(INFO) << __FUNCTION__; return true; } int32_t InitMicrophone() override { + LOG(INFO) << __FUNCTION__; return 0; } bool MicrophoneIsInitialized() const override { + LOG(INFO) << __FUNCTION__; return true; } int32_t SpeakerVolumeIsAvailable(bool& available) override { + LOG(INFO) << __FUNCTION__; return output_.SpeakerVolumeIsAvailable(available); } int32_t SetSpeakerVolume(uint32_t volume) override { + LOG(INFO) << __FUNCTION__; return output_.SetSpeakerVolume(volume); } int32_t SpeakerVolume(uint32_t& volume) const override { + LOG(INFO) << __FUNCTION__; return output_.SpeakerVolume(volume); } int32_t MaxSpeakerVolume(uint32_t& maxVolume) const override { + LOG(INFO) << __FUNCTION__; return output_.MaxSpeakerVolume(maxVolume); } int32_t MinSpeakerVolume(uint32_t& minVolume) const override { + LOG(INFO) << __FUNCTION__; return output_.MinSpeakerVolume(minVolume); } @@ -268,7 +295,6 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { int32_t MicrophoneVolumeIsAvailable(bool& available) override{ available = false; - FATAL() << "Should never be called"; return -1; } @@ -343,12 +369,14 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } int32_t StereoPlayoutIsAvailable(bool& available) override { + LOG(INFO) << __FUNCTION__; available = false; return 0; } // TODO(henrika): add support. int32_t SetStereoPlayout(bool enable) override { + LOG(INFO) << __FUNCTION__; return -1; } @@ -360,15 +388,18 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { } int32_t StereoRecordingIsAvailable(bool& available) override { + LOG(INFO) << __FUNCTION__; available = false; return 0; } int32_t SetStereoRecording(bool enable) override { + LOG(INFO) << __FUNCTION__; return -1; } int32_t StereoRecording(bool& enabled) const override { + LOG(INFO) << __FUNCTION__; enabled = false; return 0; } @@ -394,6 +425,7 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { int32_t RecordingDelay(uint16_t& delay_ms) const override { // Best guess we can do is to use half of the estimated total delay. + LOG(INFO) << __FUNCTION__; delay_ms = audio_manager_->GetDelayEstimateInMilliseconds() / 2; RTC_DCHECK_GT(delay_ms, 0); return 0; @@ -420,15 +452,16 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { return false; } - void ClearPlayoutWarning() override {} + void ClearPlayoutWarning() override { LOG(INFO) << __FUNCTION__; } - void ClearPlayoutError() override {} + void ClearPlayoutError() override { LOG(INFO) << __FUNCTION__; } - void ClearRecordingWarning() override {} + void ClearRecordingWarning() override { LOG(INFO) << __FUNCTION__; } - void ClearRecordingError() override {} + void ClearRecordingError() override { LOG(INFO) << __FUNCTION__; } void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override { + LOG(INFO) << __FUNCTION__; output_.AttachAudioBuffer(audioBuffer); input_.AttachAudioBuffer(audioBuffer); } @@ -451,33 +484,56 @@ class AudioDeviceTemplate : public AudioDeviceGeneric { // Returns true if the device both supports built in AEC and the device // is not blacklisted. + // Currently, if OpenSL ES is used in both directions, this method will still + // report the correct value and it has the correct effect. As an example: + // a device supports built in AEC and this method returns true. Libjingle + // will then disable the WebRTC based AEC and that will work for all devices + // (mainly Nexus) even when OpenSL ES is used for input since our current + // implementation will enable built-in AEC by default also for OpenSL ES. + // The only "bad" thing that happens today is that when Libjingle calls + // OpenSLESRecorder::EnableBuiltInAEC() it will not have any real effect and + // a "Not Implemented" log will be filed. This non-perfect state will remain + // until I have added full support for audio effects based on OpenSL ES APIs. bool BuiltInAECIsAvailable() const override { + LOG(INFO) << __FUNCTION__; return audio_manager_->IsAcousticEchoCancelerSupported(); } + // TODO(henrika): add implementation for OpenSL ES based audio as well. int32_t EnableBuiltInAEC(bool enable) override { + LOG(INFO) << __FUNCTION__ << "(" << enable << ")"; RTC_CHECK(BuiltInAECIsAvailable()) << "HW AEC is not available"; return input_.EnableBuiltInAEC(enable); } // Returns true if the device both supports built in AGC and the device // is not blacklisted. + // TODO(henrika): add implementation for OpenSL ES based audio as well. + // In addition, see comments for BuiltInAECIsAvailable(). bool BuiltInAGCIsAvailable() const override { + LOG(INFO) << __FUNCTION__; return audio_manager_->IsAutomaticGainControlSupported(); } + // TODO(henrika): add implementation for OpenSL ES based audio as well. int32_t EnableBuiltInAGC(bool enable) override { + LOG(INFO) << __FUNCTION__ << "(" << enable << ")"; RTC_CHECK(BuiltInAGCIsAvailable()) << "HW AGC is not available"; return input_.EnableBuiltInAGC(enable); } // Returns true if the device both supports built in NS and the device // is not blacklisted. + // TODO(henrika): add implementation for OpenSL ES based audio as well. + // In addition, see comments for BuiltInAECIsAvailable(). bool BuiltInNSIsAvailable() const override { + LOG(INFO) << __FUNCTION__; return audio_manager_->IsNoiseSuppressorSupported(); } + // TODO(henrika): add implementation for OpenSL ES based audio as well. int32_t EnableBuiltInNS(bool enable) override { + LOG(INFO) << __FUNCTION__ << "(" << enable << ")"; RTC_CHECK(BuiltInNSIsAvailable()) << "HW NS is not available"; return input_.EnableBuiltInNS(enable); } diff --git a/include/webrtc/modules/audio_device/android/audio_manager.h b/include/webrtc/modules/audio_device/android/audio_manager.h index b4264a6..6540cc5 100644 --- a/include/webrtc/modules/audio_device/android/audio_manager.h +++ b/include/webrtc/modules/audio_device/android/audio_manager.h @@ -14,11 +14,13 @@ #include #include +#include #include "webrtc/base/thread_checker.h" #include "webrtc/modules/audio_device/android/audio_common.h" #include "webrtc/modules/audio_device/audio_device_config.h" #include "webrtc/modules/audio_device/include/audio_device_defines.h" +#include "webrtc/modules/audio_device/android/opensles_common.h" #include "webrtc/modules/audio_device/audio_device_generic.h" #include "webrtc/modules/utility/include/helpers_android.h" #include "webrtc/modules/utility/include/jvm_android.h" @@ -63,6 +65,18 @@ class AudioManager { // Init(). void SetActiveAudioLayer(AudioDeviceModule::AudioLayer audio_layer); + // Creates and realizes the main (global) Open SL engine object and returns + // a reference to it. The engine object is only created at the first call + // since OpenSL ES for Android only supports a single engine per application. + // Subsequent calls returns the already created engine. The SL engine object + // is destroyed when the AudioManager object is deleted. It means that the + // engine object will be the first OpenSL ES object to be created and last + // object to be destroyed. + // Note that NULL will be returned unless the audio layer is specified as + // AudioDeviceModule::kAndroidOpenSLESAudio or + // AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio. + SLObjectItf GetOpenSLEngine(); + // Initializes the audio manager and stores the current audio mode. bool Init(); // Revert any setting done by Init(). @@ -87,6 +101,11 @@ class AudioManager { // Returns true if the device supports the low-latency audio paths in // combination with OpenSL ES. bool IsLowLatencyPlayoutSupported() const; + bool IsLowLatencyRecordSupported() const; + + // Returns true if the device supports pro-audio features in combination with + // OpenSL ES. + bool IsProAudioSupported() const; // Returns the estimated total delay of this device. Unit is in milliseconds. // The vaule is set once at construction and never changes after that. @@ -101,21 +120,27 @@ class AudioManager { static void JNICALL CacheAudioParameters(JNIEnv* env, jobject obj, jint sample_rate, - jint channels, + jint output_channels, + jint input_channels, jboolean hardware_aec, jboolean hardware_agc, jboolean hardware_ns, jboolean low_latency_output, + jboolean low_latency_input, + jboolean pro_audio, jint output_buffer_size, jint input_buffer_size, jlong native_audio_manager); void OnCacheAudioParameters(JNIEnv* env, jint sample_rate, - jint channels, + jint output_channels, + jint input_channels, jboolean hardware_aec, jboolean hardware_agc, jboolean hardware_ns, jboolean low_latency_output, + jboolean low_latency_input, + jboolean pro_audio, jint output_buffer_size, jint input_buffer_size); @@ -137,8 +162,17 @@ class AudioManager { // Wraps the Java specific parts of the AudioManager. std::unique_ptr j_audio_manager_; + // Contains the selected audio layer specified by the AudioLayer enumerator + // in the AudioDeviceModule class. AudioDeviceModule::AudioLayer audio_layer_; + // This object is the global entry point of the OpenSL ES API. + // After creating the engine object, the application can obtain this object‘s + // SLEngineItf interface. This interface contains creation methods for all + // the other object types in the API. None of these interface are realized + // by this class. It only provides access to the global engine object. + webrtc::ScopedSLObjectItf engine_object_; + // Set to true by Init() and false by Close(). bool initialized_; @@ -149,9 +183,15 @@ class AudioManager { // True if device supports hardware (or built-in) NS. bool hardware_ns_; - // True if device supports the low-latency OpenSL ES audio path. + // True if device supports the low-latency OpenSL ES audio path for output. bool low_latency_playout_; + // True if device supports the low-latency OpenSL ES audio path for input. + bool low_latency_record_; + + // True if device supports the low-latency OpenSL ES pro-audio path. + bool pro_audio_; + // The delay estimate can take one of two fixed values depending on if the // device supports low-latency output or not. int delay_estimate_in_milliseconds_; diff --git a/include/webrtc/modules/audio_device/android/audio_record_jni.h b/include/webrtc/modules/audio_device/android/audio_record_jni.h index de58468..3a1a94a 100644 --- a/include/webrtc/modules/audio_device/android/audio_record_jni.h +++ b/include/webrtc/modules/audio_device/android/audio_record_jni.h @@ -55,7 +55,6 @@ class AudioRecordJni { bool StartRecording(); bool StopRecording(); bool EnableBuiltInAEC(bool enable); - bool EnableBuiltInAGC(bool enable); bool EnableBuiltInNS(bool enable); private: @@ -64,7 +63,6 @@ class AudioRecordJni { jmethodID start_recording_; jmethodID stop_recording_; jmethodID enable_built_in_aec_; - jmethodID enable_built_in_agc_; jmethodID enable_built_in_ns_; }; diff --git a/include/webrtc/modules/audio_device/android/build_info.h b/include/webrtc/modules/audio_device/android/build_info.h index 4a4c30e..d9640dd 100644 --- a/include/webrtc/modules/audio_device/android/build_info.h +++ b/include/webrtc/modules/audio_device/android/build_info.h @@ -19,6 +19,22 @@ namespace webrtc { +// This enumeration maps to the values returned by BuildInfo::GetSdkVersion(), +// indicating the Android release associated with a given SDK version. +// See https://developer.android.com/guide/topics/manifest/uses-sdk-element.html +// for details. +enum SdkCode { + SDK_CODE_JELLY_BEAN = 16, // Android 4.1 + SDK_CODE_JELLY_BEAN_MR1 = 17, // Android 4.2 + SDK_CODE_JELLY_BEAN_MR2 = 18, // Android 4.3 + SDK_CODE_KITKAT = 19, // Android 4.4 + SDK_CODE_WATCH = 20, // Android 4.4W + SDK_CODE_LOLLIPOP = 21, // Android 5.0 + SDK_CODE_LOLLIPOP_MR1 = 22, // Android 5.1 + SDK_CODE_MARSHMALLOW = 23, // Android 6.0 + SDK_CODE_N = 24, +}; + // Utility class used to query the Java class (org/webrtc/voiceengine/BuildInfo) // for device and Android build information. // The calling thread is attached to the JVM at construction if needed and a @@ -42,8 +58,9 @@ class BuildInfo { std::string GetBuildType(); // The user-visible version string (e.g. "5.1"). std::string GetBuildRelease(); - // The user-visible SDK version of the framework (e.g. 21). - std::string GetSdkVersion(); + // The user-visible SDK version of the framework (e.g. 21). See SdkCode enum + // for translation. + SdkCode GetSdkVersion(); private: // Helper method which calls a static getter method with |name| and returns diff --git a/include/webrtc/modules/audio_device/android/opensles_common.h b/include/webrtc/modules/audio_device/android/opensles_common.h index a4487b0..b0859c2 100644 --- a/include/webrtc/modules/audio_device/android/opensles_common.h +++ b/include/webrtc/modules/audio_device/android/opensles_common.h @@ -11,13 +11,19 @@ #ifndef WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_COMMON_H_ #define WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_COMMON_H_ +#include #include -#include "webrtc/base/checks.h" - namespace webrtc { -SLDataFormat_PCM CreatePcmConfiguration(int sample_rate); +// Returns a string representation given an integer SL_RESULT_XXX code. +// The mapping can be found in . +const char* GetSLErrorString(size_t code); + +// Configures an SL_DATAFORMAT_PCM structure based on native audio parameters. +SLDataFormat_PCM CreatePCMConfiguration(size_t channels, + int sample_rate, + size_t bits_per_sample); // Helper class for using SLObjectItf interfaces. template @@ -49,6 +55,6 @@ class ScopedSLObject { typedef ScopedSLObject ScopedSLObjectItf; -} // namespace webrtc_opensl +} // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_COMMON_H_ diff --git a/include/webrtc/modules/audio_device/android/opensles_player.h b/include/webrtc/modules/audio_device/android/opensles_player.h index 4058ff9..62de50e 100644 --- a/include/webrtc/modules/audio_device/android/opensles_player.h +++ b/include/webrtc/modules/audio_device/android/opensles_player.h @@ -11,8 +11,6 @@ #ifndef WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_PLAYER_H_ #define WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_PLAYER_H_ -#include - #include #include #include @@ -49,17 +47,13 @@ class FineAudioBuffer; // the output latency may be higher. class OpenSLESPlayer { public: - // The lower output latency path is used only if the application requests a - // buffer count of 2 or more, and a buffer size and sample rate that are - // compatible with the device's native output configuration provided via the - // audio manager at construction. - static const int kNumOfOpenSLESBuffers = 4; - - // There is no need for this class to use JNI. - static int32_t SetAndroidAudioDeviceObjects(void* javaVM, void* context) { - return 0; - } - static void ClearAndroidAudioDeviceObjects() {} + // Beginning with API level 17 (Android 4.2), a buffer count of 2 or more is + // required for lower latency. Beginning with API level 18 (Android 4.3), a + // buffer count of 1 is sufficient for lower latency. In addition, the buffer + // size and sample rate must be compatible with the device's native output + // configuration provided via the audio manager at construction. + // TODO(henrika): perhaps set this value dynamically based on OS version. + static const int kNumOfOpenSLESBuffers = 2; explicit OpenSLESPlayer(AudioManager* audio_manager); ~OpenSLESPlayer(); @@ -92,20 +86,19 @@ class OpenSLESPlayer { // Reads audio data in PCM format using the AudioDeviceBuffer. // Can be called both on the main thread (during Start()) and from the // internal audio thread while output streaming is active. - void EnqueuePlayoutData(); - - // Configures the SL_DATAFORMAT_PCM structure. - SLDataFormat_PCM CreatePCMConfiguration(size_t channels, - int sample_rate, - size_t bits_per_sample); + // If the |silence| flag is set, the audio is filled with zeros instead of + // asking the WebRTC layer for real audio data. This procedure is also known + // as audio priming. + void EnqueuePlayoutData(bool silence); // Allocate memory for audio buffers which will be used to render audio // via the SLAndroidSimpleBufferQueueItf interface. void AllocateDataBuffers(); - // Creates/destroys the main engine object and the SLEngineItf interface. - bool CreateEngine(); - void DestroyEngine(); + // Obtaines the SL Engine Interface from the existing global Engine object. + // The interface exposes creation methods of all the OpenSL ES object types. + // This method defines the |engine_| member variable. + bool ObtainEngineInterface(); // Creates/destroys the output mix object. bool CreateMix(); @@ -127,6 +120,12 @@ class OpenSLESPlayer { // Detached during construction of this object. rtc::ThreadChecker thread_checker_opensles_; + // Raw pointer to the audio manager injected at construction. Used to cache + // audio parameters and to access the global SL engine object needed by the + // ObtainEngineInterface() method. The audio manager outlives any instance of + // this class. + AudioManager* audio_manager_; + // Contains audio parameters provided to this class at construction by the // AudioManager. const AudioParameters audio_parameters_; @@ -143,11 +142,6 @@ class OpenSLESPlayer { // 32-bit float representation is needed. SLDataFormat_PCM pcm_format_; - // Number of bytes per audio buffer in each |audio_buffers_[i]|. - // Typical sizes are 480 or 512 bytes corresponding to native output buffer - // sizes of 240 or 256 audio frames respectively. - size_t bytes_per_buffer_; - // Queue of audio buffers to be used by the player object for rendering // audio. They will be used in a Round-robin way and the size of each buffer // is given by FineAudioBuffer::RequiredBufferSizeBytes(). @@ -158,21 +152,17 @@ class OpenSLESPlayer { // a finer or coarser granularity. I.e. interacting with this class instead // of directly with the AudioDeviceBuffer one can ask for any number of // audio data samples. - // Example: native buffer size is 240 audio frames at 48kHz sample rate. - // WebRTC will provide 480 audio frames per 10ms but OpenSL ES asks for 240 - // in each callback (one every 5ms). This class can then ask for 240 and the - // FineAudioBuffer will ask WebRTC for new data only every second callback - // and also cach non-utilized audio. - std::unique_ptr fine_buffer_; + // Example: native buffer size can be 192 audio frames at 48kHz sample rate. + // WebRTC will provide 480 audio frames per 10ms but OpenSL ES asks for 192 + // in each callback (one every 4th ms). This class can then ask for 192 and + // the FineAudioBuffer will ask WebRTC for new data approximately only every + // second callback and also cache non-utilized audio. + std::unique_ptr fine_audio_buffer_; // Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue. // Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ... int buffer_index_; - // The engine object which provides the SLEngineItf interface. - // Created by the global Open SL ES constructor slCreateEngine(). - webrtc::ScopedSLObjectItf engine_object_; - // This interface exposes creation methods for all the OpenSL ES object types. // It is the OpenSL ES API entry point. SLEngineItf engine_; diff --git a/include/webrtc/modules/audio_device/android/opensles_recorder.h b/include/webrtc/modules/audio_device/android/opensles_recorder.h new file mode 100644 index 0000000..952371a --- /dev/null +++ b/include/webrtc/modules/audio_device/android/opensles_recorder.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ +#define WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ + +#include +#include +#include + +#include + +#include "webrtc/base/thread_checker.h" +#include "webrtc/modules/audio_device/android/audio_common.h" +#include "webrtc/modules/audio_device/android/audio_manager.h" +#include "webrtc/modules/audio_device/android/opensles_common.h" +#include "webrtc/modules/audio_device/include/audio_device_defines.h" +#include "webrtc/modules/audio_device/audio_device_generic.h" +#include "webrtc/modules/utility/include/helpers_android.h" + +namespace webrtc { + +class FineAudioBuffer; + +// Implements 16-bit mono PCM audio input support for Android using the +// C based OpenSL ES API. No calls from C/C++ to Java using JNI is done. +// +// An instance must be created and destroyed on one and the same thread. +// All public methods must also be called on the same thread. A thread checker +// will RTC_DCHECK if any method is called on an invalid thread. Recorded audio +// buffers are provided on a dedicated internal thread managed by the OpenSL +// ES layer. +// +// The existing design forces the user to call InitRecording() after +// StopRecording() to be able to call StartRecording() again. This is inline +// with how the Java-based implementation works. +// +// As of API level 21, lower latency audio input is supported on select devices. +// To take advantage of this feature, first confirm that lower latency output is +// available. The capability for lower latency output is a prerequisite for the +// lower latency input feature. Then, create an AudioRecorder with the same +// sample rate and buffer size as would be used for output. OpenSL ES interfaces +// for input effects preclude the lower latency path. +// See https://developer.android.com/ndk/guides/audio/opensl-prog-notes.html +// for more details. +class OpenSLESRecorder { + public: + // Beginning with API level 17 (Android 4.2), a buffer count of 2 or more is + // required for lower latency. Beginning with API level 18 (Android 4.3), a + // buffer count of 1 is sufficient for lower latency. In addition, the buffer + // size and sample rate must be compatible with the device's native input + // configuration provided via the audio manager at construction. + // TODO(henrika): perhaps set this value dynamically based on OS version. + static const int kNumOfOpenSLESBuffers = 2; + + explicit OpenSLESRecorder(AudioManager* audio_manager); + ~OpenSLESRecorder(); + + int Init(); + int Terminate(); + + int InitRecording(); + bool RecordingIsInitialized() const { return initialized_; } + + int StartRecording(); + int StopRecording(); + bool Recording() const { return recording_; } + + void AttachAudioBuffer(AudioDeviceBuffer* audio_buffer); + + // TODO(henrika): add support using OpenSL ES APIs when available. + int EnableBuiltInAEC(bool enable); + int EnableBuiltInAGC(bool enable); + int EnableBuiltInNS(bool enable); + + private: + // Obtaines the SL Engine Interface from the existing global Engine object. + // The interface exposes creation methods of all the OpenSL ES object types. + // This method defines the |engine_| member variable. + bool ObtainEngineInterface(); + + // Creates/destroys the audio recorder and the simple-buffer queue object. + bool CreateAudioRecorder(); + void DestroyAudioRecorder(); + + // Allocate memory for audio buffers which will be used to capture audio + // via the SLAndroidSimpleBufferQueueItf interface. + void AllocateDataBuffers(); + + // These callback methods are called when data has been written to the input + // buffer queue. They are both called from an internal "OpenSL ES thread" + // which is not attached to the Dalvik VM. + static void SimpleBufferQueueCallback(SLAndroidSimpleBufferQueueItf caller, + void* context); + void ReadBufferQueue(); + + // Wraps calls to SLAndroidSimpleBufferQueueState::Enqueue() and it can be + // called both on the main thread (but before recording has started) and from + // the internal audio thread while input streaming is active. It uses + // |simple_buffer_queue_| but no lock is needed since the initial calls from + // the main thread and the native callback thread are mutually exclusive. + bool EnqueueAudioBuffer(); + + // Returns the current recorder state. + SLuint32 GetRecordState() const; + + // Returns the current buffer queue state. + SLAndroidSimpleBufferQueueState GetBufferQueueState() const; + + // Number of buffers currently in the queue. + SLuint32 GetBufferCount(); + + // Prints a log message of the current queue state. Can be used for debugging + // purposes. + void LogBufferState() const; + + // Ensures that methods are called from the same thread as this object is + // created on. + rtc::ThreadChecker thread_checker_; + + // Stores thread ID in first call to SimpleBufferQueueCallback() from internal + // non-application thread which is not attached to the Dalvik JVM. + // Detached during construction of this object. + rtc::ThreadChecker thread_checker_opensles_; + + // Raw pointer to the audio manager injected at construction. Used to cache + // audio parameters and to access the global SL engine object needed by the + // ObtainEngineInterface() method. The audio manager outlives any instance of + // this class. + AudioManager* const audio_manager_; + + // Contains audio parameters provided to this class at construction by the + // AudioManager. + const AudioParameters audio_parameters_; + + // Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the + // AudioDeviceModuleImpl class and called by AudioDeviceModule::Create(). + AudioDeviceBuffer* audio_device_buffer_; + + // PCM-type format definition. + // TODO(henrika): add support for SLAndroidDataFormat_PCM_EX (android-21) if + // 32-bit float representation is needed. + SLDataFormat_PCM pcm_format_; + + bool initialized_; + bool recording_; + + // This interface exposes creation methods for all the OpenSL ES object types. + // It is the OpenSL ES API entry point. + SLEngineItf engine_; + + // The audio recorder media object records audio to the destination specified + // by the data sink capturing it from the input specified by the data source. + webrtc::ScopedSLObjectItf recorder_object_; + + // This interface is supported on the audio recorder object and it controls + // the state of the audio recorder. + SLRecordItf recorder_; + + // The Android Simple Buffer Queue interface is supported on the audio + // recorder. For recording, an app should enqueue empty buffers. When a + // registered callback sends notification that the system has finished writing + // data to the buffer, the app can read the buffer. + SLAndroidSimpleBufferQueueItf simple_buffer_queue_; + + // Consumes audio of native buffer size and feeds the WebRTC layer with 10ms + // chunks of audio. + std::unique_ptr fine_audio_buffer_; + + // Queue of audio buffers to be used by the recorder object for capturing + // audio. They will be used in a Round-robin way and the size of each buffer + // is given by AudioParameters::GetBytesPerBuffer(), i.e., it corresponds to + // the native OpenSL ES buffer size. + std::unique_ptr[]> audio_buffers_; + + // Keeps track of active audio buffer 'n' in the audio_buffers_[n] queue. + // Example (kNumOfOpenSLESBuffers = 2): counts 0, 1, 0, 1, ... + int buffer_index_; + + // Last time the OpenSL ES layer delivered recorded audio data. + uint32_t last_rec_time_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_DEVICE_ANDROID_OPENSLES_RECORDER_H_ diff --git a/include/webrtc/modules/audio_device/audio_device_buffer.h b/include/webrtc/modules/audio_device/audio_device_buffer.h index 1095971..1466e69 100644 --- a/include/webrtc/modules/audio_device/audio_device_buffer.h +++ b/include/webrtc/modules/audio_device/audio_device_buffer.h @@ -8,116 +8,251 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H -#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H +#ifndef WEBRTC_MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ +#define WEBRTC_MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ +#include "webrtc/base/buffer.h" +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/task_queue.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/thread_checker.h" #include "webrtc/modules/audio_device/include/audio_device.h" #include "webrtc/system_wrappers/include/file_wrapper.h" #include "webrtc/typedefs.h" namespace webrtc { -class CriticalSectionWrapper; - -const uint32_t kPulsePeriodMs = 1000; -const size_t kMaxBufferSizeBytes = 3840; // 10ms in stereo @ 96kHz +// Delta times between two successive playout callbacks are limited to this +// value before added to an internal array. +const size_t kMaxDeltaTimeInMs = 500; +// TODO(henrika): remove when no longer used by external client. +const size_t kMaxBufferSizeBytes = 3840; // 10ms in stereo @ 96kHz class AudioDeviceObserver; -class AudioDeviceBuffer -{ -public: - AudioDeviceBuffer(); - virtual ~AudioDeviceBuffer(); +class AudioDeviceBuffer { + public: + enum LogState { + LOG_START = 0, + LOG_STOP, + LOG_ACTIVE, + }; + + struct Stats { + void ResetRecStats() { + rec_callbacks = 0; + rec_samples = 0; + max_rec_level = 0; + } + + void ResetPlayStats() { + play_callbacks = 0; + play_samples = 0; + max_play_level = 0; + } + + // Total number of recording callbacks where the source provides 10ms audio + // data each time. + uint64_t rec_callbacks = 0; + + // Total number of playback callbacks where the sink asks for 10ms audio + // data each time. + uint64_t play_callbacks = 0; + + // Total number of recorded audio samples. + uint64_t rec_samples = 0; + + // Total number of played audio samples. + uint64_t play_samples = 0; + + // Contains max level (max(abs(x))) of recorded audio packets over the last + // 10 seconds where a new measurement is done twice per second. The level + // is reset to zero at each call to LogStats(). + int16_t max_rec_level = 0; + + // Contains max level of recorded audio packets over the last 10 seconds + // where a new measurement is done twice per second. + int16_t max_play_level = 0; + }; + + AudioDeviceBuffer(); + virtual ~AudioDeviceBuffer(); + + void SetId(uint32_t id) {}; + int32_t RegisterAudioCallback(AudioTransport* audio_callback); + + void StartPlayout(); + void StartRecording(); + void StopPlayout(); + void StopRecording(); + + int32_t SetRecordingSampleRate(uint32_t fsHz); + int32_t SetPlayoutSampleRate(uint32_t fsHz); + int32_t RecordingSampleRate() const; + int32_t PlayoutSampleRate() const; + + int32_t SetRecordingChannels(size_t channels); + int32_t SetPlayoutChannels(size_t channels); + size_t RecordingChannels() const; + size_t PlayoutChannels() const; + int32_t SetRecordingChannel(const AudioDeviceModule::ChannelType channel); + int32_t RecordingChannel(AudioDeviceModule::ChannelType& channel) const; + + virtual int32_t SetRecordedBuffer(const void* audio_buffer, + size_t samples_per_channel); + int32_t SetCurrentMicLevel(uint32_t level); + virtual void SetVQEData(int play_delay_ms, int rec_delay_ms, int clock_drift); + virtual int32_t DeliverRecordedData(); + uint32_t NewMicLevel() const; + + virtual int32_t RequestPlayoutData(size_t samples_per_channel); + virtual int32_t GetPlayoutData(void* audio_buffer); + + // TODO(henrika): these methods should not be used and does not contain any + // valid implementation. Investigate the possibility to either remove them + // or add a proper implementation if needed. + int32_t StartInputFileRecording(const char fileName[kAdmMaxFileNameSize]); + int32_t StopInputFileRecording(); + int32_t StartOutputFileRecording(const char fileName[kAdmMaxFileNameSize]); + int32_t StopOutputFileRecording(); + + int32_t SetTypingStatus(bool typing_status); + + private: + // Starts/stops periodic logging of audio stats. + void StartPeriodicLogging(); + void StopPeriodicLogging(); + + // Called periodically on the internal thread created by the TaskQueue. + // Updates some stats but dooes it on the task queue to ensure that access of + // members is serialized hence avoiding usage of locks. + // state = LOG_START => members are initialized and the timer starts. + // state = LOG_STOP => no logs are printed and the timer stops. + // state = LOG_ACTIVE => logs are printed and the timer is kept alive. + void LogStats(LogState state); + + // Updates counters in each play/record callback. These counters are later + // (periodically) read by LogStats() using a lock. + void UpdateRecStats(int16_t max_abs, size_t samples_per_channel); + void UpdatePlayStats(int16_t max_abs, size_t samples_per_channel); + + // Clears all members tracking stats for recording and playout. + // These methods both run on the task queue. + void ResetRecStats(); + void ResetPlayStats(); + + // This object lives on the main (creating) thread and most methods are + // called on that same thread. When audio has started some methods will be + // called on either a native audio thread for playout or a native thread for + // recording. Some members are not annotated since they are "protected by + // design" and adding e.g. a race checker can cause failuries for very few + // edge cases and it is IMHO not worth the risk to use them in this class. + // TODO(henrika): see if it is possible to refactor and annotate all members. + + // Main thread on which this object is created. + rtc::ThreadChecker main_thread_checker_; + + // Native (platform specific) audio thread driving the playout side. + rtc::ThreadChecker playout_thread_checker_; - void SetId(uint32_t id); - int32_t RegisterAudioCallback(AudioTransport* audioCallback); + // Native (platform specific) audio thread driving the recording side. + rtc::ThreadChecker recording_thread_checker_; - int32_t InitPlayout(); - int32_t InitRecording(); + rtc::CriticalSection lock_; - virtual int32_t SetRecordingSampleRate(uint32_t fsHz); - virtual int32_t SetPlayoutSampleRate(uint32_t fsHz); - int32_t RecordingSampleRate() const; - int32_t PlayoutSampleRate() const; + // Task queue used to invoke LogStats() periodically. Tasks are executed on a + // worker thread but it does not necessarily have to be the same thread for + // each task. + rtc::TaskQueue task_queue_; - virtual int32_t SetRecordingChannels(size_t channels); - virtual int32_t SetPlayoutChannels(size_t channels); - size_t RecordingChannels() const; - size_t PlayoutChannels() const; - int32_t SetRecordingChannel( - const AudioDeviceModule::ChannelType channel); - int32_t RecordingChannel( - AudioDeviceModule::ChannelType& channel) const; + // Raw pointer to AudioTransport instance. Supplied to RegisterAudioCallback() + // and it must outlive this object. It is not possible to change this member + // while any media is active. It is possible to start media without calling + // RegisterAudioCallback() but that will lead to ignored audio callbacks in + // both directions where native audio will be acive but no audio samples will + // be transported. + AudioTransport* audio_transport_cb_; - virtual int32_t SetRecordedBuffer(const void* audioBuffer, - size_t nSamples); - int32_t SetCurrentMicLevel(uint32_t level); - virtual void SetVQEData(int playDelayMS, - int recDelayMS, - int clockDrift); - virtual int32_t DeliverRecordedData(); - uint32_t NewMicLevel() const; + // The members below that are not annotated are protected by design. They are + // all set on the main thread (verified by |main_thread_checker_|) and then + // read on either the playout or recording audio thread. But, media will never + // be active when the member is set; hence no conflict exists. It is too + // complex to ensure and verify that this is actually the case. - virtual int32_t RequestPlayoutData(size_t nSamples); - virtual int32_t GetPlayoutData(void* audioBuffer); + // Sample rate in Hertz. + uint32_t rec_sample_rate_; + uint32_t play_sample_rate_; - int32_t StartInputFileRecording( - const char fileName[kAdmMaxFileNameSize]); - int32_t StopInputFileRecording(); - int32_t StartOutputFileRecording( - const char fileName[kAdmMaxFileNameSize]); - int32_t StopOutputFileRecording(); + // Number of audio channels. + size_t rec_channels_; + size_t play_channels_; - int32_t SetTypingStatus(bool typingStatus); + // Keeps track of if playout/recording are active or not. A combination + // of these states are used to determine when to start and stop the timer. + // Only used on the creating thread and not used to control any media flow. + bool playing_ ACCESS_ON(main_thread_checker_); + bool recording_ ACCESS_ON(main_thread_checker_); -private: - int32_t _id; - CriticalSectionWrapper& _critSect; - CriticalSectionWrapper& _critSectCb; + // Buffer used for audio samples to be played out. Size can be changed + // dynamically. The 16-bit samples are interleaved, hence the size is + // proportional to the number of channels. + rtc::BufferT play_buffer_ ACCESS_ON(playout_thread_checker_); - AudioTransport* _ptrCbAudioTransport; + // Byte buffer used for recorded audio samples. Size can be changed + // dynamically. + rtc::BufferT rec_buffer_ ACCESS_ON(recording_thread_checker_); - uint32_t _recSampleRate; - uint32_t _playSampleRate; + // AGC parameters. +#if !defined(WEBRTC_WIN) + uint32_t current_mic_level_ ACCESS_ON(recording_thread_checker_); +#else + // Windows uses a dedicated thread for volume APIs. + uint32_t current_mic_level_; +#endif + uint32_t new_mic_level_ ACCESS_ON(recording_thread_checker_); - size_t _recChannels; - size_t _playChannels; + // Contains true of a key-press has been detected. + bool typing_status_ ACCESS_ON(recording_thread_checker_); - // selected recording channel (left/right/both) - AudioDeviceModule::ChannelType _recChannel; + // Delay values used by the AEC. + int play_delay_ms_ ACCESS_ON(recording_thread_checker_); + int rec_delay_ms_ ACCESS_ON(recording_thread_checker_); - // 2 or 4 depending on mono or stereo - size_t _recBytesPerSample; - size_t _playBytesPerSample; + // Contains a clock-drift measurement. + int clock_drift_ ACCESS_ON(recording_thread_checker_); - // 10ms in stereo @ 96kHz - int8_t _recBuffer[kMaxBufferSizeBytes]; + // Counts number of times LogStats() has been called. + size_t num_stat_reports_ ACCESS_ON(task_queue_); - // one sample <=> 2 or 4 bytes - size_t _recSamples; - size_t _recSize; // in bytes + // Time stamp of last timer task (drives logging). + int64_t last_timer_task_time_ ACCESS_ON(task_queue_); - // 10ms in stereo @ 96kHz - int8_t _playBuffer[kMaxBufferSizeBytes]; + // Counts number of audio callbacks modulo 50 to create a signal when + // a new storage of audio stats shall be done. + int16_t rec_stat_count_ ACCESS_ON(recording_thread_checker_); + int16_t play_stat_count_ ACCESS_ON(playout_thread_checker_); - // one sample <=> 2 or 4 bytes - size_t _playSamples; - size_t _playSize; // in bytes + // Time stamps of when playout and recording starts. + int64_t play_start_time_ ACCESS_ON(main_thread_checker_); + int64_t rec_start_time_ ACCESS_ON(main_thread_checker_); - FileWrapper& _recFile; - FileWrapper& _playFile; + // Contains counters for playout and recording statistics. + Stats stats_ GUARDED_BY(lock_); - uint32_t _currentMicLevel; - uint32_t _newMicLevel; + // Stores current stats at each timer task. Used to calculate differences + // between two successive timer events. + Stats last_stats_ ACCESS_ON(task_queue_); - bool _typingStatus; + // Set to true at construction and modified to false as soon as one audio- + // level estimate larger than zero is detected. + bool only_silence_recorded_; - int _playDelayMS; - int _recDelayMS; - int _clockDrift; - int high_delay_counter_; + // Set to true when logging of audio stats is enabled for the first time in + // StartPeriodicLogging() and set to false by StopPeriodicLogging(). + // Setting this member to false prevents (possiby invalid) log messages from + // being printed in the LogStats() task. + bool log_stats_ ACCESS_ON(task_queue_); }; } // namespace webrtc -#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H +#endif // WEBRTC_MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_ diff --git a/include/webrtc/modules/audio_device/audio_device_generic.h b/include/webrtc/modules/audio_device/audio_device_generic.h index c76ea52..4807c63 100644 --- a/include/webrtc/modules/audio_device/audio_device_generic.h +++ b/include/webrtc/modules/audio_device/audio_device_generic.h @@ -18,12 +18,22 @@ namespace webrtc { class AudioDeviceGeneric { public: + // For use with UMA logging. Must be kept in sync with histograms.xml in + // Chrome, located at + // https://cs.chromium.org/chromium/src/tools/metrics/histograms/histograms.xml + enum class InitStatus { + OK = 0, + PLAYOUT_ERROR = 1, + RECORDING_ERROR = 2, + OTHER_ERROR = 3, + NUM_STATUSES = 4 + }; // Retrieve the currently utilized audio layer virtual int32_t ActiveAudioLayer( AudioDeviceModule::AudioLayer& audioLayer) const = 0; // Main initializaton and termination - virtual int32_t Init() = 0; + virtual InitStatus Init() = 0; virtual int32_t Terminate() = 0; virtual bool Initialized() const = 0; @@ -154,13 +164,12 @@ class AudioDeviceGeneric { virtual int32_t EnableBuiltInAGC(bool enable); virtual int32_t EnableBuiltInNS(bool enable); - // Windows Core Audio only. - virtual bool BuiltInAECIsEnabled() const; - // iOS only. // TODO(henrika): add Android support. +#if defined(WEBRTC_IOS) virtual int GetPlayoutAudioParameters(AudioParameters* params) const; virtual int GetRecordAudioParameters(AudioParameters* params) const; +#endif // WEBRTC_IOS virtual bool PlayoutWarning() const = 0; virtual bool PlayoutError() const = 0; diff --git a/include/webrtc/modules/audio_device/audio_device_impl.h b/include/webrtc/modules/audio_device/audio_device_impl.h index 044ec4e..034690f 100644 --- a/include/webrtc/modules/audio_device/audio_device_impl.h +++ b/include/webrtc/modules/audio_device/audio_device_impl.h @@ -42,7 +42,7 @@ class AudioDeviceModuleImpl : public AudioDeviceModule { int32_t AttachAudioBuffer(); AudioDeviceModuleImpl(const int32_t id, const AudioLayer audioLayer); - virtual ~AudioDeviceModuleImpl(); + ~AudioDeviceModuleImpl() override; int64_t TimeUntilNextProcess() override; void Process() override; @@ -178,7 +178,6 @@ class AudioDeviceModuleImpl : public AudioDeviceModule { int32_t SetLoudspeakerStatus(bool enable) override; int32_t GetLoudspeakerStatus(bool* enabled) const override; - bool BuiltInAECIsEnabled() const override; bool BuiltInAECIsAvailable() const override; int32_t EnableBuiltInAEC(bool enable) override; bool BuiltInAGCIsAvailable() const override; @@ -186,8 +185,10 @@ class AudioDeviceModuleImpl : public AudioDeviceModule { bool BuiltInNSIsAvailable() const override; int32_t EnableBuiltInNS(bool enable) override; +#if defined(WEBRTC_IOS) int GetPlayoutAudioParameters(AudioParameters* params) const override; int GetRecordAudioParameters(AudioParameters* params) const override; +#endif // WEBRTC_IOS int32_t Id() { return _id; } #if defined(WEBRTC_ANDROID) diff --git a/include/webrtc/modules/audio_device/dummy/audio_device_dummy.h b/include/webrtc/modules/audio_device/dummy/audio_device_dummy.h index 75c599e..72a0eb1 100644 --- a/include/webrtc/modules/audio_device/dummy/audio_device_dummy.h +++ b/include/webrtc/modules/audio_device/dummy/audio_device_dummy.h @@ -27,7 +27,7 @@ class AudioDeviceDummy : public AudioDeviceGeneric { AudioDeviceModule::AudioLayer& audioLayer) const override; // Main initializaton and termination - int32_t Init() override; + InitStatus Init() override; int32_t Terminate() override; bool Initialized() const override; diff --git a/include/webrtc/modules/audio_device/dummy/file_audio_device.h b/include/webrtc/modules/audio_device/dummy/file_audio_device.h index be6fa3d..2065f21 100644 --- a/include/webrtc/modules/audio_device/dummy/file_audio_device.h +++ b/include/webrtc/modules/audio_device/dummy/file_audio_device.h @@ -16,10 +16,10 @@ #include #include +#include "webrtc/base/timeutils.h" #include "webrtc/modules/audio_device/audio_device_generic.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/system_wrappers/include/file_wrapper.h" -#include "webrtc/system_wrappers/include/clock.h" namespace rtc { class PlatformThread; @@ -48,7 +48,7 @@ class FileAudioDevice : public AudioDeviceGeneric { AudioDeviceModule::AudioLayer& audioLayer) const override; // Main initializaton and termination - int32_t Init() override; + InitStatus Init() override; int32_t Terminate() override; bool Initialized() const override; @@ -188,15 +188,13 @@ class FileAudioDevice : public AudioDeviceGeneric { bool _playing; bool _recording; - uint64_t _lastCallPlayoutMillis; - uint64_t _lastCallRecordMillis; + int64_t _lastCallPlayoutMillis; + int64_t _lastCallRecordMillis; FileWrapper& _outputFile; FileWrapper& _inputFile; std::string _outputFilename; std::string _inputFilename; - - Clock* _clock; }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_device/fine_audio_buffer.h b/include/webrtc/modules/audio_device/fine_audio_buffer.h index 478e0c6..306f9d2 100644 --- a/include/webrtc/modules/audio_device/fine_audio_buffer.h +++ b/include/webrtc/modules/audio_device/fine_audio_buffer.h @@ -13,6 +13,7 @@ #include +#include "webrtc/base/buffer.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -41,10 +42,6 @@ class FineAudioBuffer { int sample_rate); ~FineAudioBuffer(); - // Returns the required size of |buffer| when calling GetPlayoutData(). If - // the buffer is smaller memory trampling will happen. - size_t RequiredPlayoutBufferSizeBytes(); - // Clears buffers and counters dealing with playour and/or recording. void ResetPlayout(); void ResetRecord(); @@ -59,8 +56,7 @@ class FineAudioBuffer { // They can be fixed values on most platforms and they are ignored if an // external (hardware/built-in) AEC is used. // The size of |buffer| is given by |size_in_bytes| and must be equal to - // |desired_frame_size_bytes_|. A RTC_CHECK will be hit if this is not the - // case. + // |desired_frame_size_bytes_|. // Example: buffer size is 5ms => call #1 stores 5ms of data, call #2 stores // 5ms of data and sends a total of 10ms to WebRTC and clears the intenal // cache. Call #3 restarts the scheme above. @@ -86,22 +82,10 @@ class FineAudioBuffer { const size_t samples_per_10_ms_; // Number of audio bytes per 10ms. const size_t bytes_per_10_ms_; - // Storage for output samples that are not yet asked for. - std::unique_ptr playout_cache_buffer_; - // Location of first unread output sample. - size_t playout_cached_buffer_start_; - // Number of bytes stored in output (contain samples to be played out) cache. - size_t playout_cached_bytes_; + rtc::BufferT playout_buffer_; // Storage for input samples that are about to be delivered to the WebRTC // ADB or remains from the last successful delivery of a 10ms audio buffer. - std::unique_ptr record_cache_buffer_; - // Required (max) size in bytes of the |record_cache_buffer_|. - const size_t required_record_buffer_size_bytes_; - // Number of bytes in input (contains recorded samples) cache. - size_t record_cached_bytes_; - // Read and write pointers used in the buffering scheme on the recording side. - size_t record_read_pos_; - size_t record_write_pos_; + rtc::BufferT record_buffer_; }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_device/include/audio_device.h b/include/webrtc/modules/audio_device/include/audio_device.h index 8457a6b..dfa58aa 100644 --- a/include/webrtc/modules/audio_device/include/audio_device.h +++ b/include/webrtc/modules/audio_device/include/audio_device.h @@ -26,12 +26,12 @@ class AudioDeviceModule : public RefCountedModule { enum AudioLayer { kPlatformDefaultAudio = 0, - kWindowsWaveAudio = 1, kWindowsCoreAudio = 2, kLinuxAlsaAudio = 3, kLinuxPulseAudio = 4, kAndroidJavaAudio = 5, - kAndroidJavaInputAndOpenSLESOutputAudio = 6, + kAndroidOpenSLESAudio = 6, + kAndroidJavaInputAndOpenSLESOutputAudio = 7, kDummyAudio = 8 }; @@ -191,30 +191,23 @@ class AudioDeviceModule : public RefCountedModule { virtual int32_t GetLoudspeakerStatus(bool* enabled) const = 0; // Only supported on Android. - // TODO(henrika): Make pure virtual after updating Chromium. - virtual bool BuiltInAECIsAvailable() const { return false; } - virtual bool BuiltInAGCIsAvailable() const { return false; } - virtual bool BuiltInNSIsAvailable() const { return false; } + virtual bool BuiltInAECIsAvailable() const = 0; + virtual bool BuiltInAGCIsAvailable() const = 0; + virtual bool BuiltInNSIsAvailable() const = 0; // Enables the built-in audio effects. Only supported on Android. - // TODO(henrika): Make pure virtual after updating Chromium. - virtual int32_t EnableBuiltInAEC(bool enable) { return -1; } - virtual int32_t EnableBuiltInAGC(bool enable) { return -1; } - virtual int32_t EnableBuiltInNS(bool enable) { return -1; } - // Don't use. - virtual bool BuiltInAECIsEnabled() const { return false; } - - // Only supported on iOS. - // TODO(henrika): Make pure virtual after updating Chromium. - virtual int GetPlayoutAudioParameters(AudioParameters* params) const { - return -1; - } - virtual int GetRecordAudioParameters(AudioParameters* params) const { - return -1; - } + virtual int32_t EnableBuiltInAEC(bool enable) = 0; + virtual int32_t EnableBuiltInAGC(bool enable) = 0; + virtual int32_t EnableBuiltInNS(bool enable) = 0; + +// Only supported on iOS. +#if defined(WEBRTC_IOS) + virtual int GetPlayoutAudioParameters(AudioParameters* params) const = 0; + virtual int GetRecordAudioParameters(AudioParameters* params) const = 0; +#endif // WEBRTC_IOS protected: - virtual ~AudioDeviceModule() {} + ~AudioDeviceModule() override {} }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_device/include/audio_device_defines.h b/include/webrtc/modules/audio_device/include/audio_device_defines.h index b847729..ccc263c 100644 --- a/include/webrtc/modules/audio_device/include/audio_device_defines.h +++ b/include/webrtc/modules/audio_device/include/audio_device_defines.h @@ -66,58 +66,16 @@ class AudioTransport { int64_t* elapsed_time_ms, int64_t* ntp_time_ms) = 0; - // Method to pass captured data directly and unmixed to network channels. - // |channel_ids| contains a list of VoE channels which are the - // sinks to the capture data. |audio_delay_milliseconds| is the sum of - // recording delay and playout delay of the hardware. |current_volume| is - // in the range of [0, 255], representing the current microphone analog - // volume. |key_pressed| is used by the typing detection. - // |need_audio_processing| specify if the data needs to be processed by APM. - // Currently WebRtc supports only one APM, and Chrome will make sure only - // one stream goes through APM. When |need_audio_processing| is false, the - // values of |audio_delay_milliseconds|, |current_volume| and |key_pressed| - // will be ignored. - // The return value is the new microphone volume, in the range of |0, 255]. - // When the volume does not need to be updated, it returns 0. - // TODO(xians): Remove this interface after Chrome and Libjingle switches - // to OnData(). - virtual int OnDataAvailable(const int voe_channels[], - size_t number_of_voe_channels, - const int16_t* audio_data, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames, - int audio_delay_milliseconds, - int current_volume, - bool key_pressed, - bool need_audio_processing) { - return 0; - } - - // Method to pass the captured audio data to the specific VoE channel. - // |voe_channel| is the id of the VoE channel which is the sink to the - // capture data. - // TODO(xians): Remove this interface after Libjingle switches to - // PushCaptureData(). - virtual void OnData(int voe_channel, - const void* audio_data, - int bits_per_sample, - int sample_rate, - size_t number_of_channels, - size_t number_of_frames) {} - // Method to push the captured audio data to the specific VoE channel. // The data will not undergo audio processing. // |voe_channel| is the id of the VoE channel which is the sink to the // capture data. - // TODO(xians): Make the interface pure virtual after Libjingle - // has its implementation. virtual void PushCaptureData(int voe_channel, const void* audio_data, int bits_per_sample, int sample_rate, size_t number_of_channels, - size_t number_of_frames) {} + size_t number_of_frames) = 0; // Method to pull mixed render audio data from all active VoE channels. // The data will not be passed as reference for audio processing internally. @@ -129,7 +87,7 @@ class AudioTransport { size_t number_of_frames, void* audio_data, int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) {} + int64_t* ntp_time_ms) = 0; protected: virtual ~AudioTransport() {} diff --git a/include/webrtc/modules/audio_device/include/fake_audio_device.h b/include/webrtc/modules/audio_device/include/fake_audio_device.h index 45bf45c..1797dd5 100644 --- a/include/webrtc/modules/audio_device/include/fake_audio_device.h +++ b/include/webrtc/modules/audio_device/include/fake_audio_device.h @@ -8,6 +8,9 @@ * be found in the AUTHORS file in the root of the source tree. */ +#ifndef WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_FAKE_AUDIO_DEVICE_H_ +#define WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_FAKE_AUDIO_DEVICE_H_ + #include "webrtc/modules/audio_device/include/audio_device.h" namespace webrtc { @@ -18,6 +21,8 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual ~FakeAudioDeviceModule() {} virtual int32_t AddRef() const { return 0; } virtual int32_t Release() const { return 0; } + + private: virtual int32_t RegisterEventObserver(AudioDeviceObserver* eventCallback) { return 0; } @@ -36,8 +41,20 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual int32_t SetStereoRecording(bool enable) { return 0; } virtual int32_t SetAGC(bool enable) { return 0; } virtual int32_t StopRecording() { return 0; } - virtual int64_t TimeUntilNextProcess() { return 0; } - virtual void Process() {} + + // If the subclass doesn't override the ProcessThread implementation, + // we'll fall back on an implementation that doesn't eat too much CPU. + virtual int64_t TimeUntilNextProcess() { + if (turn_off_module_callbacks_) + return 7 * 24 * 60 * 60 * 1000; // call me next week. + uses_default_module_implementation_ = true; + return 10; + } + + virtual void Process() { + turn_off_module_callbacks_ = uses_default_module_implementation_; + } + virtual int32_t Terminate() { return 0; } virtual int32_t ActiveAudioLayer(AudioLayer* audioLayer) const { return 0; } @@ -118,7 +135,10 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual int32_t PlayoutBuffer(BufferType* type, uint16_t* sizeMS) const { return 0; } - virtual int32_t PlayoutDelay(uint16_t* delayMS) const { return 0; } + virtual int32_t PlayoutDelay(uint16_t* delayMS) const { + *delayMS = 0; + return 0; + } virtual int32_t RecordingDelay(uint16_t* delayMS) const { return 0; } virtual int32_t CPULoad(uint16_t* load) const { return 0; } virtual int32_t StartRawOutputFileRecording( @@ -146,11 +166,25 @@ class FakeAudioDeviceModule : public AudioDeviceModule { virtual int32_t GetLoudspeakerStatus(bool* enabled) const { return 0; } virtual bool BuiltInAECIsAvailable() const { return false; } virtual int32_t EnableBuiltInAEC(bool enable) { return -1; } - virtual bool BuiltInAECIsEnabled() const { return false; } virtual bool BuiltInAGCIsAvailable() const { return false; } virtual int32_t EnableBuiltInAGC(bool enable) { return -1; } virtual bool BuiltInNSIsAvailable() const { return false; } virtual int32_t EnableBuiltInNS(bool enable) { return -1; } + +#if defined(WEBRTC_IOS) + virtual int GetPlayoutAudioParameters(AudioParameters* params) const { + return -1; + } + virtual int GetRecordAudioParameters(AudioParameters* params) const { + return -1; + } +#endif // WEBRTC_IOS + + private: + bool uses_default_module_implementation_ = false; + bool turn_off_module_callbacks_ = false; }; } // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_FAKE_AUDIO_DEVICE_H_ diff --git a/include/webrtc/modules/audio_device/include/mock_audio_device.h b/include/webrtc/modules/audio_device/include/mock_audio_device.h index 8c1c758..2c44c65 100644 --- a/include/webrtc/modules/audio_device/include/mock_audio_device.h +++ b/include/webrtc/modules/audio_device/include/mock_audio_device.h @@ -12,8 +12,9 @@ #define WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_MOCK_AUDIO_DEVICE_H_ #include -#include "testing/gmock/include/gmock/gmock.h" + #include "webrtc/modules/audio_device/include/audio_device.h" +#include "webrtc/test/gmock.h" namespace webrtc { namespace test { @@ -125,9 +126,10 @@ class MockAudioDeviceModule : public AudioDeviceModule { MOCK_METHOD1(EnableBuiltInAEC, int32_t(bool enable)); MOCK_METHOD1(EnableBuiltInAGC, int32_t(bool enable)); MOCK_METHOD1(EnableBuiltInNS, int32_t(bool enable)); - MOCK_CONST_METHOD0(BuiltInAECIsEnabled, bool()); +#if defined(WEBRTC_IOS) MOCK_CONST_METHOD1(GetPlayoutAudioParameters, int(AudioParameters* params)); MOCK_CONST_METHOD1(GetRecordAudioParameters, int(AudioParameters* params)); +#endif // WEBRTC_IOS }; } // namespace test } // namespace webrtc diff --git a/include/webrtc/modules/audio_device/include/mock_audio_transport.h b/include/webrtc/modules/audio_device/include/mock_audio_transport.h new file mode 100644 index 0000000..a05e7ea --- /dev/null +++ b/include/webrtc/modules/audio_device/include/mock_audio_transport.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_MOCK_AUDIO_TRANSPORT_H_ +#define WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_MOCK_AUDIO_TRANSPORT_H_ + +#include "webrtc/modules/audio_device/include/audio_device_defines.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockAudioTransport : public AudioTransport { + public: + MockAudioTransport() {} + ~MockAudioTransport() {} + + MOCK_METHOD10(RecordedDataIsAvailable, + int32_t(const void* audioSamples, + const size_t nSamples, + const size_t nBytesPerSample, + const size_t nChannels, + const uint32_t samplesPerSec, + const uint32_t totalDelayMS, + const int32_t clockDrift, + const uint32_t currentMicLevel, + const bool keyPressed, + uint32_t& newMicLevel)); + + MOCK_METHOD8(NeedMorePlayData, + int32_t(const size_t nSamples, + const size_t nBytesPerSample, + const size_t nChannels, + const uint32_t samplesPerSec, + void* audioSamples, + size_t& nSamplesOut, + int64_t* elapsed_time_ms, + int64_t* ntp_time_ms)); + + MOCK_METHOD6(PushCaptureData, + void(int voe_channel, + const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames)); + + MOCK_METHOD7(PullRenderData, + void(int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames, + void* audio_data, + int64_t* elapsed_time_ms, + int64_t* ntp_time_ms)); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_DEVICE_INCLUDE_MOCK_AUDIO_TRANSPORT_H_ diff --git a/include/webrtc/modules/audio_device/ios/audio_device_ios.h b/include/webrtc/modules/audio_device/ios/audio_device_ios.h index 9616a28..5aa3b70 100644 --- a/include/webrtc/modules/audio_device/ios/audio_device_ios.h +++ b/include/webrtc/modules/audio_device/ios/audio_device_ios.h @@ -49,15 +49,15 @@ class AudioDeviceIOS : public AudioDeviceGeneric, void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; - int32_t Init() override; + InitStatus Init() override; int32_t Terminate() override; bool Initialized() const override { return initialized_; } int32_t InitPlayout() override; - bool PlayoutIsInitialized() const override { return play_is_initialized_; } + bool PlayoutIsInitialized() const override { return audio_is_initialized_; } int32_t InitRecording() override; - bool RecordingIsInitialized() const override { return rec_is_initialized_; } + bool RecordingIsInitialized() const override { return audio_is_initialized_; } int32_t StartPlayout() override; int32_t StopPlayout() override; @@ -92,7 +92,8 @@ class AudioDeviceIOS : public AudioDeviceGeneric, // See audio_device_not_implemented.cc for trivial implementations. int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const override; - int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; + int32_t ActiveAudioLayer( + AudioDeviceModule::AudioLayer& audioLayer) const override; int32_t ResetAudioDevice() override; int32_t PlayoutIsAvailable(bool& available) override; int32_t RecordingIsAvailable(bool& available) override; @@ -279,11 +280,9 @@ class AudioDeviceIOS : public AudioDeviceGeneric, // Set to true after successful call to Init(), false otherwise. bool initialized_; - // Set to true after successful call to InitRecording(), false otherwise. - bool rec_is_initialized_; - - // Set to true after successful call to InitPlayout(), false otherwise. - bool play_is_initialized_; + // Set to true after successful call to InitRecording() or InitPlayout(), + // false otherwise. + bool audio_is_initialized_; // Set to true if audio session is interrupted, false otherwise. bool is_interrupted_; diff --git a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h index cb506c3..36be014 100644 --- a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h +++ b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h @@ -31,6 +31,11 @@ NS_ASSUME_NONNULL_BEGIN /** Convenience BOOL that checks useManualAudio and isAudioEnebled. */ @property(readonly) BOOL canPlayOrRecord; +/** Tracks whether we have been sent an interruption event that hasn't been matched by either an + * interrupted end event or a foreground event. + */ +@property(nonatomic, assign) BOOL isInterrupted; + - (BOOL)checkLock:(NSError **)outError; /** Adds the delegate to the list of delegates, and places it at the front of diff --git a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h index 274cc2b..199fd17 100644 --- a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h +++ b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h @@ -11,6 +11,8 @@ #import #import +#import "WebRTC/RTCMacros.h" + NS_ASSUME_NONNULL_BEGIN extern NSString * const kRTCAudioSessionErrorDomain; @@ -25,6 +27,7 @@ extern NSInteger const kRTCAudioSessionErrorConfiguration; // Surfaces AVAudioSession events. WebRTC will listen directly for notifications // from AVAudioSession and handle them before calling these delegate methods, // at which point applications can perform additional processing if required. +RTC_EXPORT @protocol RTCAudioSessionDelegate @optional @@ -49,12 +52,12 @@ extern NSInteger const kRTCAudioSessionErrorConfiguration; /** Called on a system notification thread when AVAudioSession media server * terminates. */ -- (void)audioSessionMediaServicesWereLost:(RTCAudioSession *)session; +- (void)audioSessionMediaServerTerminated:(RTCAudioSession *)session; /** Called on a system notification thread when AVAudioSession media server * restarts. */ -- (void)audioSessionMediaServicesWereReset:(RTCAudioSession *)session; +- (void)audioSessionMediaServerReset:(RTCAudioSession *)session; // TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification. @@ -80,6 +83,7 @@ extern NSInteger const kRTCAudioSessionErrorConfiguration; * RTCAudioSession also coordinates activation so that the audio session is * activated only once. See |setActive:error:|. */ +RTC_EXPORT @interface RTCAudioSession : NSObject /** Convenience property to access the AVAudioSession singleton. Callers should diff --git a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h index 7832a82..6a02751 100644 --- a/include/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h +++ b/include/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h @@ -11,6 +11,8 @@ #import #import +#import "WebRTC/RTCMacros.h" + NS_ASSUME_NONNULL_BEGIN extern const int kRTCAudioSessionPreferredNumberOfChannels; @@ -20,6 +22,7 @@ extern const double kRTCAudioSessionHighPerformanceIOBufferDuration; extern const double kRTCAudioSessionLowComplexityIOBufferDuration; // Struct to hold configuration values. +RTC_EXPORT @interface RTCAudioSessionConfiguration : NSObject @property(nonatomic, strong) NSString *category; diff --git a/include/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h b/include/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h index 340e963..aba62e8 100644 --- a/include/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h +++ b/include/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h @@ -41,7 +41,7 @@ class AudioDeviceLinuxALSA : public AudioDeviceGeneric AudioDeviceModule::AudioLayer& audioLayer) const override; // Main initializaton and termination - int32_t Init() override; + InitStatus Init() override; int32_t Terminate() override; bool Initialized() const override; diff --git a/include/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h b/include/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h index a0a15e5..3aa1698 100644 --- a/include/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h +++ b/include/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h @@ -103,7 +103,7 @@ class AudioDeviceLinuxPulse: public AudioDeviceGeneric AudioDeviceModule::AudioLayer& audioLayer) const override; // Main initializaton and termination - int32_t Init() override; + InitStatus Init() override; int32_t Terminate() override; bool Initialized() const override; diff --git a/include/webrtc/modules/audio_device/mac/audio_device_mac.h b/include/webrtc/modules/audio_device/mac/audio_device_mac.h index 102c67e..ccde6f0 100644 --- a/include/webrtc/modules/audio_device/mac/audio_device_mac.h +++ b/include/webrtc/modules/audio_device/mac/audio_device_mac.h @@ -68,7 +68,7 @@ class AudioDeviceMac : public AudioDeviceGeneric { AudioDeviceModule::AudioLayer& audioLayer) const; // Main initializaton and termination - virtual int32_t Init(); + virtual InitStatus Init(); virtual int32_t Terminate(); virtual bool Initialized() const; diff --git a/include/webrtc/modules/audio_device/mock_audio_device_buffer.h b/include/webrtc/modules/audio_device/mock_audio_device_buffer.h index 07c9e29..bfef605 100644 --- a/include/webrtc/modules/audio_device/mock_audio_device_buffer.h +++ b/include/webrtc/modules/audio_device/mock_audio_device_buffer.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_DEVICE_MOCK_AUDIO_DEVICE_BUFFER_H_ #define WEBRTC_MODULES_AUDIO_DEVICE_MOCK_AUDIO_DEVICE_BUFFER_H_ -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/audio_device/audio_device_buffer.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_device/test/audio_device_test_defines.h b/include/webrtc/modules/audio_device/test/audio_device_test_defines.h index cc8e3e3..60f98f4 100644 --- a/include/webrtc/modules/audio_device/test/audio_device_test_defines.h +++ b/include/webrtc/modules/audio_device/test/audio_device_test_defines.h @@ -13,7 +13,6 @@ #include "webrtc/common_types.h" #include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/modules/utility/include/process_thread.h" #include "webrtc/system_wrappers/include/trace.h" #ifdef _WIN32 diff --git a/include/webrtc/modules/audio_device/test/func_test_manager.h b/include/webrtc/modules/audio_device/test/func_test_manager.h deleted file mode 100644 index 2b8a19b..0000000 --- a/include/webrtc/modules/audio_device/test/func_test_manager.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_AUDIO_DEVICE_FUNC_TEST_MANAGER_H -#define WEBRTC_AUDIO_DEVICE_FUNC_TEST_MANAGER_H - -#include -#include -#include - -#include "webrtc/common_audio/resampler/include/resampler.h" -#include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/modules/audio_device/test/audio_device_test_defines.h" -#include "webrtc/system_wrappers/include/file_wrapper.h" -#include "webrtc/typedefs.h" - - -#define ADM_AUDIO_LAYER AudioDeviceModule::kPlatformDefaultAudio -//#define ADM_AUDIO_LAYER AudioDeviceModule::kLinuxPulseAudio - -enum TestType -{ - TTInvalid = -1, - TTAll = 0, - TTAudioLayerSelection = 1, - TTDeviceEnumeration = 2, - TTDeviceSelection = 3, - TTAudioTransport = 4, - TTSpeakerVolume = 5, - TTMicrophoneVolume = 6, - TTSpeakerMute = 7, - TTMicrophoneMute = 8, - TTMicrophoneBoost = 9, - TTMicrophoneAGC = 10, - TTLoopback = 11, - TTDeviceRemoval = 13, - TTMobileAPI = 14, - TTTest = 66, -}; - -struct AudioPacket -{ - uint8_t dataBuffer[4 * 960]; - size_t nSamples; - size_t nBytesPerSample; - size_t nChannels; - uint32_t samplesPerSec; -}; - -class ProcessThread; - -namespace webrtc -{ - -class AudioDeviceModule; -class AudioEventObserver; -class AudioTransport; - -// ---------------------------------------------------------------------------- -// AudioEventObserver -// ---------------------------------------------------------------------------- - -class AudioEventObserver: public AudioDeviceObserver -{ -public: - virtual void OnErrorIsReported(const ErrorCode error); - virtual void OnWarningIsReported(const WarningCode warning); - AudioEventObserver(AudioDeviceModule* audioDevice); - ~AudioEventObserver(); -public: - ErrorCode _error; - WarningCode _warning; -}; - -// ---------------------------------------------------------------------------- -// AudioTransport -// ---------------------------------------------------------------------------- - -class AudioTransportImpl: public AudioTransport -{ -public: - int32_t RecordedDataIsAvailable(const void* audioSamples, - const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - const uint32_t totalDelayMS, - const int32_t clockDrift, - const uint32_t currentMicLevel, - const bool keyPressed, - uint32_t& newMicLevel) override; - - int32_t NeedMorePlayData(const size_t nSamples, - const size_t nBytesPerSample, - const size_t nChannels, - const uint32_t samplesPerSec, - void* audioSamples, - size_t& nSamplesOut, - int64_t* elapsed_time_ms, - int64_t* ntp_time_ms) override; - - AudioTransportImpl(AudioDeviceModule* audioDevice); - ~AudioTransportImpl(); - -public: - int32_t SetFilePlayout(bool enable, const char* fileName = NULL); - void SetFullDuplex(bool enable); - void SetSpeakerVolume(bool enable) - { - _speakerVolume = enable; - } - ; - void SetSpeakerMute(bool enable) - { - _speakerMute = enable; - } - ; - void SetMicrophoneMute(bool enable) - { - _microphoneMute = enable; - } - ; - void SetMicrophoneVolume(bool enable) - { - _microphoneVolume = enable; - } - ; - void SetMicrophoneBoost(bool enable) - { - _microphoneBoost = enable; - } - ; - void SetLoopbackMeasurements(bool enable) - { - _loopBackMeasurements = enable; - } - ; - void SetMicrophoneAGC(bool enable) - { - _microphoneAGC = enable; - } - ; - -private: - typedef std::list AudioPacketList; - AudioDeviceModule* _audioDevice; - - bool _playFromFile; - bool _fullDuplex; - bool _speakerVolume; - bool _speakerMute; - bool _microphoneVolume; - bool _microphoneMute; - bool _microphoneBoost; - bool _microphoneAGC; - bool _loopBackMeasurements; - - FileWrapper& _playFile; - - uint32_t _recCount; - uint32_t _playCount; - AudioPacketList _audioList; - - Resampler _resampler; -}; - -// ---------------------------------------------------------------------------- -// FuncTestManager -// ---------------------------------------------------------------------------- - -class FuncTestManager -{ -public: - FuncTestManager(); - ~FuncTestManager(); - int32_t Init(); - int32_t Close(); - int32_t DoTest(const TestType testType); -private: - int32_t TestAudioLayerSelection(); - int32_t TestDeviceEnumeration(); - int32_t TestDeviceSelection(); - int32_t TestAudioTransport(); - int32_t TestSpeakerVolume(); - int32_t TestMicrophoneVolume(); - int32_t TestSpeakerMute(); - int32_t TestMicrophoneMute(); - int32_t TestMicrophoneBoost(); - int32_t TestLoopback(); - int32_t TestDeviceRemoval(); - int32_t TestExtra(); - int32_t TestMicrophoneAGC(); - int32_t SelectPlayoutDevice(); - int32_t SelectRecordingDevice(); - int32_t TestAdvancedMBAPI(); -private: - // Paths to where the resource files to be used for this test are located. - std::string _playoutFile48; - std::string _playoutFile44; - std::string _playoutFile16; - std::string _playoutFile8; - - std::unique_ptr _processThread; - AudioDeviceModule* _audioDevice; - AudioEventObserver* _audioEventObserver; - AudioTransportImpl* _audioTransport; -}; - -} // namespace webrtc - -#endif // #ifndef WEBRTC_AUDIO_DEVICE_FUNC_TEST_MANAGER_H diff --git a/include/webrtc/modules/audio_device/win/audio_device_core_win.h b/include/webrtc/modules/audio_device/win/audio_device_core_win.h index 5c94cfd..0ff2474 100644 --- a/include/webrtc/modules/audio_device/win/audio_device_core_win.h +++ b/include/webrtc/modules/audio_device/win/audio_device_core_win.h @@ -91,7 +91,7 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric virtual int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; // Main initializaton and termination - virtual int32_t Init(); + virtual InitStatus Init(); virtual int32_t Terminate(); virtual bool Initialized() const; @@ -192,7 +192,6 @@ class AudioDeviceWindowsCore : public AudioDeviceGeneric virtual int32_t CPULoad(uint16_t& load) const; virtual int32_t EnableBuiltInAEC(bool enable); - virtual bool BuiltInAECIsEnabled() const; public: virtual bool PlayoutWarning() const; diff --git a/include/webrtc/modules/audio_device/win/audio_device_wave_win.h b/include/webrtc/modules/audio_device/win/audio_device_wave_win.h deleted file mode 100644 index 402d575..0000000 --- a/include/webrtc/modules/audio_device/win/audio_device_wave_win.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_WAVE_WIN_H -#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_WAVE_WIN_H - -#include - -#include "webrtc/base/platform_thread.h" -#include "webrtc/modules/audio_device/audio_device_generic.h" -#include "webrtc/modules/audio_device/win/audio_mixer_manager_win.h" - -#pragma comment( lib, "winmm.lib" ) - -namespace webrtc { -class EventTimerWrapper; -class EventWrapper; - -const uint32_t TIMER_PERIOD_MS = 2; -const uint32_t REC_CHECK_TIME_PERIOD_MS = 4; -const uint16_t REC_PUT_BACK_DELAY = 4; - -const uint32_t N_REC_SAMPLES_PER_SEC = 48000; -const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000; - -const uint32_t N_REC_CHANNELS = 1; // default is mono recording -const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout - -// NOTE - CPU load will not be correct for other sizes than 10ms -const uint32_t REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC/100); -const uint32_t PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC/100); - -enum { N_BUFFERS_IN = 200 }; -enum { N_BUFFERS_OUT = 200 }; - -class AudioDeviceWindowsWave : public AudioDeviceGeneric -{ -public: - AudioDeviceWindowsWave(const int32_t id); - ~AudioDeviceWindowsWave(); - - // Retrieve the currently utilized audio layer - virtual int32_t ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const; - - // Main initializaton and termination - virtual int32_t Init(); - virtual int32_t Terminate(); - virtual bool Initialized() const; - - // Device enumeration - virtual int16_t PlayoutDevices(); - virtual int16_t RecordingDevices(); - virtual int32_t PlayoutDeviceName( - uint16_t index, - char name[kAdmMaxDeviceNameSize], - char guid[kAdmMaxGuidSize]); - virtual int32_t RecordingDeviceName( - uint16_t index, - char name[kAdmMaxDeviceNameSize], - char guid[kAdmMaxGuidSize]); - - // Device selection - virtual int32_t SetPlayoutDevice(uint16_t index); - virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device); - virtual int32_t SetRecordingDevice(uint16_t index); - virtual int32_t SetRecordingDevice(AudioDeviceModule::WindowsDeviceType device); - - // Audio transport initialization - virtual int32_t PlayoutIsAvailable(bool& available); - virtual int32_t InitPlayout(); - virtual bool PlayoutIsInitialized() const; - virtual int32_t RecordingIsAvailable(bool& available); - virtual int32_t InitRecording(); - virtual bool RecordingIsInitialized() const; - - // Audio transport control - virtual int32_t StartPlayout(); - virtual int32_t StopPlayout(); - virtual bool Playing() const; - virtual int32_t StartRecording(); - virtual int32_t StopRecording(); - virtual bool Recording() const; - - // Microphone Automatic Gain Control (AGC) - virtual int32_t SetAGC(bool enable); - virtual bool AGC() const; - - // Volume control based on the Windows Wave API (Windows only) - virtual int32_t SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight); - virtual int32_t WaveOutVolume(uint16_t& volumeLeft, uint16_t& volumeRight) const; - - // Audio mixer initialization - virtual int32_t InitSpeaker(); - virtual bool SpeakerIsInitialized() const; - virtual int32_t InitMicrophone(); - virtual bool MicrophoneIsInitialized() const; - - // Speaker volume controls - virtual int32_t SpeakerVolumeIsAvailable(bool& available); - virtual int32_t SetSpeakerVolume(uint32_t volume); - virtual int32_t SpeakerVolume(uint32_t& volume) const; - virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const; - virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const; - virtual int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const; - - // Microphone volume controls - virtual int32_t MicrophoneVolumeIsAvailable(bool& available); - virtual int32_t SetMicrophoneVolume(uint32_t volume); - virtual int32_t MicrophoneVolume(uint32_t& volume) const; - virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const; - virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const; - virtual int32_t MicrophoneVolumeStepSize(uint16_t& stepSize) const; - - // Speaker mute control - virtual int32_t SpeakerMuteIsAvailable(bool& available); - virtual int32_t SetSpeakerMute(bool enable); - virtual int32_t SpeakerMute(bool& enabled) const; - - // Microphone mute control - virtual int32_t MicrophoneMuteIsAvailable(bool& available); - virtual int32_t SetMicrophoneMute(bool enable); - virtual int32_t MicrophoneMute(bool& enabled) const; - - // Microphone boost control - virtual int32_t MicrophoneBoostIsAvailable(bool& available); - virtual int32_t SetMicrophoneBoost(bool enable); - virtual int32_t MicrophoneBoost(bool& enabled) const; - - // Stereo support - virtual int32_t StereoPlayoutIsAvailable(bool& available); - virtual int32_t SetStereoPlayout(bool enable); - virtual int32_t StereoPlayout(bool& enabled) const; - virtual int32_t StereoRecordingIsAvailable(bool& available); - virtual int32_t SetStereoRecording(bool enable); - virtual int32_t StereoRecording(bool& enabled) const; - - // Delay information and control - virtual int32_t SetPlayoutBuffer(const AudioDeviceModule::BufferType type, uint16_t sizeMS); - virtual int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type, uint16_t& sizeMS) const; - virtual int32_t PlayoutDelay(uint16_t& delayMS) const; - virtual int32_t RecordingDelay(uint16_t& delayMS) const; - - // CPU load - virtual int32_t CPULoad(uint16_t& load) const; - -public: - virtual bool PlayoutWarning() const; - virtual bool PlayoutError() const; - virtual bool RecordingWarning() const; - virtual bool RecordingError() const; - virtual void ClearPlayoutWarning(); - virtual void ClearPlayoutError(); - virtual void ClearRecordingWarning(); - virtual void ClearRecordingError(); - -public: - virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer); - -private: - void Lock() { _critSect.Enter(); }; - void UnLock() { _critSect.Leave(); }; - int32_t Id() {return _id;} - bool IsUsingOutputDeviceIndex() const {return _usingOutputDeviceIndex;} - AudioDeviceModule::WindowsDeviceType OutputDevice() const {return _outputDevice;} - uint16_t OutputDeviceIndex() const {return _outputDeviceIndex;} - bool IsUsingInputDeviceIndex() const {return _usingInputDeviceIndex;} - AudioDeviceModule::WindowsDeviceType InputDevice() const {return _inputDevice;} - uint16_t InputDeviceIndex() const {return _inputDeviceIndex;} - -private: - inline int32_t InputSanityCheckAfterUnlockedPeriod() const; - inline int32_t OutputSanityCheckAfterUnlockedPeriod() const; - -private: - bool KeyPressed() const; - -private: - int32_t EnumeratePlayoutDevices(); - int32_t EnumerateRecordingDevices(); - void TraceSupportFlags(DWORD dwSupport) const; - void TraceWaveInError(MMRESULT error) const; - void TraceWaveOutError(MMRESULT error) const; - int32_t PrepareStartRecording(); - int32_t PrepareStartPlayout(); - - int32_t RecProc(LONGLONG& consumedTime); - int PlayProc(LONGLONG& consumedTime); - - int32_t GetPlayoutBufferDelay(uint32_t& writtenSamples, uint32_t& playedSamples); - int32_t GetRecordingBufferDelay(uint32_t& readSamples, uint32_t& recSamples); - int32_t Write(int8_t* data, uint16_t nSamples); - int32_t GetClockDrift(const uint32_t plSamp, const uint32_t rcSamp); - int32_t MonitorRecording(const uint32_t time); - int32_t RestartTimerIfNeeded(const uint32_t time); - -private: - static bool ThreadFunc(void*); - bool ThreadProcess(); - - static DWORD WINAPI GetCaptureVolumeThread(LPVOID context); - DWORD DoGetCaptureVolumeThread(); - - static DWORD WINAPI SetCaptureVolumeThread(LPVOID context); - DWORD DoSetCaptureVolumeThread(); - -private: - AudioDeviceBuffer* _ptrAudioBuffer; - - CriticalSectionWrapper& _critSect; - EventTimerWrapper& _timeEvent; - EventWrapper& _recStartEvent; - EventWrapper& _playStartEvent; - - HANDLE _hGetCaptureVolumeThread; - HANDLE _hShutdownGetVolumeEvent; - HANDLE _hSetCaptureVolumeThread; - HANDLE _hShutdownSetVolumeEvent; - HANDLE _hSetCaptureVolumeEvent; - - // TODO(pbos): Remove unique_ptr usage and use PlatformThread directly - std::unique_ptr _ptrThread; - - CriticalSectionWrapper& _critSectCb; - - int32_t _id; - - AudioMixerManager _mixerManager; - - bool _usingInputDeviceIndex; - bool _usingOutputDeviceIndex; - AudioDeviceModule::WindowsDeviceType _inputDevice; - AudioDeviceModule::WindowsDeviceType _outputDevice; - uint16_t _inputDeviceIndex; - uint16_t _outputDeviceIndex; - bool _inputDeviceIsSpecified; - bool _outputDeviceIsSpecified; - - WAVEFORMATEX _waveFormatIn; - WAVEFORMATEX _waveFormatOut; - - HWAVEIN _hWaveIn; - HWAVEOUT _hWaveOut; - - WAVEHDR _waveHeaderIn[N_BUFFERS_IN]; - WAVEHDR _waveHeaderOut[N_BUFFERS_OUT]; - - uint8_t _recChannels; - uint8_t _playChannels; - uint16_t _recBufCount; - uint16_t _recDelayCount; - uint16_t _recPutBackDelay; - - int8_t _recBuffer[N_BUFFERS_IN][4*REC_BUF_SIZE_IN_SAMPLES]; - int8_t _playBuffer[N_BUFFERS_OUT][4*PLAY_BUF_SIZE_IN_SAMPLES]; - - AudioDeviceModule::BufferType _playBufType; - -private: - bool _initialized; - bool _recording; - bool _playing; - bool _recIsInitialized; - bool _playIsInitialized; - bool _startRec; - bool _stopRec; - bool _startPlay; - bool _stopPlay; - bool _AGC; - -private: - uint32_t _prevPlayTime; - uint32_t _prevRecTime; - uint32_t _prevTimerCheckTime; - - uint16_t _playBufCount; // playout buffer index - uint16_t _dTcheckPlayBufDelay; // dT for check of play buffer, {2,5,10} [ms] - uint16_t _playBufDelay; // playback delay - uint16_t _playBufDelayFixed; // fixed playback delay - uint16_t _minPlayBufDelay; // minimum playback delay - uint16_t _MAX_minBuffer; // level of (adaptive) min threshold must be < _MAX_minBuffer - - int32_t _erZeroCounter; // counts "buffer-is-empty" events - int32_t _intro; - int32_t _waitCounter; - - uint32_t _writtenSamples; - uint32_t _writtenSamplesOld; - uint32_t _playedSamplesOld; - - uint32_t _sndCardPlayDelay; - uint32_t _sndCardRecDelay; - - uint32_t _plSampOld; - uint32_t _rcSampOld; - - uint32_t _read_samples; - uint32_t _read_samples_old; - uint32_t _rec_samples_old; - - // State that detects driver problems: - int32_t _dc_diff_mean; - int32_t _dc_y_prev; - int32_t _dc_penalty_counter; - int32_t _dc_prevtime; - uint32_t _dc_prevplay; - - uint32_t _recordedBytes; // accumulated #recorded bytes (reset periodically) - uint32_t _prevRecByteCheckTime; // time when we last checked the recording process - - // CPU load measurements - LARGE_INTEGER _perfFreq; - LONGLONG _playAcc; // accumulated time for playout callback - float _avgCPULoad; // average total (rec+play) CPU load - - int32_t _wrapCounter; - - int32_t _useHeader; - int16_t _timesdwBytes; - int32_t _no_of_msecleft_warnings; - int32_t _writeErrors; - int32_t _timerFaults; - int32_t _timerRestartAttempts; - - uint16_t _playWarning; - uint16_t _playError; - uint16_t _recWarning; - uint16_t _recError; - - uint32_t _newMicLevel; - uint32_t _minMicVolume; - uint32_t _maxMicVolume; -}; - -} // namespace webrtc - -#endif // WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_WAVE_WIN_H diff --git a/include/webrtc/modules/audio_device/win/audio_mixer_manager_win.h b/include/webrtc/modules/audio_device/win/audio_mixer_manager_win.h deleted file mode 100644 index 1e0ab47..0000000 --- a/include/webrtc/modules/audio_device/win/audio_mixer_manager_win.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_MIXER_MANAGER_WIN_H -#define WEBRTC_AUDIO_DEVICE_AUDIO_MIXER_MANAGER_WIN_H - -#include "webrtc/typedefs.h" -#include "webrtc/modules/audio_device/include/audio_device.h" -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#include -#include - -namespace webrtc { - -class AudioMixerManager -{ -public: - enum { MAX_NUMBER_MIXER_DEVICES = 40 }; - enum { MAX_NUMBER_OF_LINE_CONTROLS = 20 }; - enum { MAX_NUMBER_OF_MULTIPLE_ITEMS = 20 }; - struct SpeakerLineInfo - { - DWORD dwLineID; - bool speakerIsValid; - DWORD dwVolumeControlID; - bool volumeControlIsValid; - DWORD dwMuteControlID; - bool muteControlIsValid; - }; - struct MicrophoneLineInfo - { - DWORD dwLineID; - bool microphoneIsValid; - DWORD dwVolumeControlID; - bool volumeControlIsValid; - DWORD dwMuteControlID; - bool muteControlIsValid; - DWORD dwOnOffControlID; - bool onOffControlIsValid; - }; -public: - int32_t EnumerateAll(); - int32_t EnumerateSpeakers(); - int32_t EnumerateMicrophones(); - int32_t OpenSpeaker(AudioDeviceModule::WindowsDeviceType device); - int32_t OpenSpeaker(uint16_t index); - int32_t OpenMicrophone(AudioDeviceModule::WindowsDeviceType device); - int32_t OpenMicrophone(uint16_t index); - int32_t SetSpeakerVolume(uint32_t volume); - int32_t SpeakerVolume(uint32_t& volume) const; - int32_t MaxSpeakerVolume(uint32_t& maxVolume) const; - int32_t MinSpeakerVolume(uint32_t& minVolume) const; - int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const; - int32_t SpeakerVolumeIsAvailable(bool& available); - int32_t SpeakerMuteIsAvailable(bool& available); - int32_t SetSpeakerMute(bool enable); - int32_t SpeakerMute(bool& enabled) const; - int32_t MicrophoneMuteIsAvailable(bool& available); - int32_t SetMicrophoneMute(bool enable); - int32_t MicrophoneMute(bool& enabled) const; - int32_t MicrophoneBoostIsAvailable(bool& available); - int32_t SetMicrophoneBoost(bool enable); - int32_t MicrophoneBoost(bool& enabled) const; - int32_t MicrophoneVolumeIsAvailable(bool& available); - int32_t SetMicrophoneVolume(uint32_t volume); - int32_t MicrophoneVolume(uint32_t& volume) const; - int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const; - int32_t MinMicrophoneVolume(uint32_t& minVolume) const; - int32_t MicrophoneVolumeStepSize(uint16_t& stepSize) const; - int32_t Close(); - int32_t CloseSpeaker(); - int32_t CloseMicrophone(); - bool SpeakerIsInitialized() const; - bool MicrophoneIsInitialized() const; - UINT Devices() const; - -private: - UINT DestinationLines(UINT mixId) const; - UINT SourceLines(UINT mixId, DWORD destId) const; - bool GetCapabilities(UINT mixId, MIXERCAPS& caps, bool trace = false) const; - bool GetDestinationLineInfo(UINT mixId, DWORD destId, MIXERLINE& line, bool trace = false) const; - bool GetSourceLineInfo(UINT mixId, DWORD destId, DWORD srcId, MIXERLINE& line, bool trace = false) const; - - bool GetAllLineControls(UINT mixId, const MIXERLINE& line, MIXERCONTROL* controlArray, bool trace = false) const; - bool GetLineControl(UINT mixId, DWORD dwControlID, MIXERCONTROL& control) const; - bool GetControlDetails(UINT mixId, MIXERCONTROL& controlArray, bool trace = false) const; - bool GetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD& dwValue) const; - bool SetUnsignedControlValue(UINT mixId, DWORD dwControlID, DWORD dwValue) const; - bool SetBooleanControlValue(UINT mixId, DWORD dwControlID, bool value) const; - bool GetBooleanControlValue(UINT mixId, DWORD dwControlID, bool& value) const; - bool GetSelectedMuxSource(UINT mixId, DWORD dwControlID, DWORD cMultipleItems, UINT& index) const; - -private: - void ClearSpeakerState(); - void ClearSpeakerState(UINT idx); - void ClearMicrophoneState(); - void ClearMicrophoneState(UINT idx); - bool SpeakerIsValid(UINT idx) const; - UINT ValidSpeakers() const; - bool MicrophoneIsValid(UINT idx) const; - UINT ValidMicrophones() const; - - void TraceStatusAndSupportFlags(DWORD fdwLine) const; - void TraceTargetType(DWORD dwType) const; - void TraceComponentType(DWORD dwComponentType) const; - void TraceControlType(DWORD dwControlType) const; - void TraceControlStatusAndSupportFlags(DWORD fdwControl) const; - void TraceWaveInError(MMRESULT error) const; - void TraceWaveOutError(MMRESULT error) const; - // Converts from wide-char to UTF-8 if UNICODE is defined. - // Does nothing if UNICODE is undefined. - char* WideToUTF8(const TCHAR* src) const; - -public: - AudioMixerManager(const int32_t id); - ~AudioMixerManager(); - -private: - CriticalSectionWrapper& _critSect; - int32_t _id; - HMIXER _outputMixerHandle; - UINT _outputMixerID; - HMIXER _inputMixerHandle; - UINT _inputMixerID; - SpeakerLineInfo _speakerState[MAX_NUMBER_MIXER_DEVICES]; - MicrophoneLineInfo _microphoneState[MAX_NUMBER_MIXER_DEVICES]; - mutable char _str[MAXERRORLENGTH]; -}; - -} // namespace webrtc - -#endif // WEBRTC_AUDIO_DEVICE_AUDIO_MIXER_MANAGER_H diff --git a/include/webrtc/modules/audio_mixer/audio_frame_manipulator.h b/include/webrtc/modules/audio_mixer/audio_frame_manipulator.h new file mode 100644 index 0000000..20b66ca --- /dev/null +++ b/include/webrtc/modules/audio_mixer/audio_frame_manipulator.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_MIXER_AUDIO_FRAME_MANIPULATOR_H_ +#define WEBRTC_MODULES_AUDIO_MIXER_AUDIO_FRAME_MANIPULATOR_H_ + +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { + +// Updates the audioFrame's energy (based on its samples). +uint32_t AudioMixerCalculateEnergy(const AudioFrame& audio_frame); + +// Ramps up or down the provided audio frame. Ramp(0, 1, frame) will +// linearly increase the samples in the frame from 0 to full volume. +void Ramp(float start_gain, float target_gain, AudioFrame* audio_frame); + +// Downmixes or upmixes a frame between stereo and mono. +void RemixFrame(size_t target_number_of_channels, AudioFrame* frame); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_MIXER_AUDIO_FRAME_MANIPULATOR_H_ diff --git a/include/webrtc/modules/audio_mixer/audio_mixer_impl.h b/include/webrtc/modules/audio_mixer/audio_mixer_impl.h new file mode 100644 index 0000000..0a3319e --- /dev/null +++ b/include/webrtc/modules/audio_mixer/audio_mixer_impl.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_MIXER_AUDIO_MIXER_IMPL_H_ +#define WEBRTC_MODULES_AUDIO_MIXER_AUDIO_MIXER_IMPL_H_ + +#include +#include + +#include "webrtc/api/audio/audio_mixer.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/race_checker.h" +#include "webrtc/modules/audio_mixer/frame_combiner.h" +#include "webrtc/modules/audio_mixer/output_rate_calculator.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/system_wrappers/include/critical_section_wrapper.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +typedef std::vector AudioFrameList; + +class AudioMixerImpl : public AudioMixer { + public: + struct SourceStatus { + SourceStatus(Source* audio_source, bool is_mixed, float gain) + : audio_source(audio_source), is_mixed(is_mixed), gain(gain) {} + Source* audio_source = nullptr; + bool is_mixed = false; + float gain = 0.0f; + + // A frame that will be passed to audio_source->GetAudioFrameWithInfo. + AudioFrame audio_frame; + }; + + using SourceStatusList = std::vector>; + + // AudioProcessing only accepts 10 ms frames. + static const int kFrameDurationInMs = 10; + static const int kMaximumAmountOfMixedAudioSources = 3; + + static rtc::scoped_refptr Create(); + + // TODO(aleloi): remove this when dependencies have updated to + // use Create(rate_calculator, limiter) instead. See bugs.webrtc.org/7167. + RTC_DEPRECATED static rtc::scoped_refptr + CreateWithOutputRateCalculator( + std::unique_ptr output_rate_calculator); + + static rtc::scoped_refptr Create( + std::unique_ptr output_rate_calculator, + bool use_limiter); + + ~AudioMixerImpl() override; + + // AudioMixer functions + bool AddSource(Source* audio_source) override; + void RemoveSource(Source* audio_source) override; + + void Mix(size_t number_of_channels, + AudioFrame* audio_frame_for_mixing) override LOCKS_EXCLUDED(crit_); + + // Returns true if the source was mixed last round. Returns + // false and logs an error if the source was never added to the + // mixer. + bool GetAudioSourceMixabilityStatusForTest(Source* audio_source) const; + + protected: + AudioMixerImpl(std::unique_ptr output_rate_calculator, + bool use_limiter); + + private: + // Set mixing frequency through OutputFrequencyCalculator. + void CalculateOutputFrequency(); + // Get mixing frequency. + int OutputFrequency() const; + + // Compute what audio sources to mix from audio_source_list_. Ramp + // in and out. Update mixed status. Mixes up to + // kMaximumAmountOfMixedAudioSources audio sources. + AudioFrameList GetAudioFromSources() EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // Add/remove the MixerAudioSource to the specified + // MixerAudioSource list. + bool AddAudioSourceToList(Source* audio_source, + SourceStatusList* audio_source_list) const; + bool RemoveAudioSourceFromList(Source* remove_audio_source, + SourceStatusList* audio_source_list) const; + + // The critical section lock guards audio source insertion and + // removal, which can be done from any thread. The race checker + // checks that mixing is done sequentially. + rtc::CriticalSection crit_; + rtc::RaceChecker race_checker_; + + std::unique_ptr output_rate_calculator_; + // The current sample frequency and sample size when mixing. + int output_frequency_ GUARDED_BY(race_checker_); + size_t sample_size_ GUARDED_BY(race_checker_); + + // List of all audio sources. Note all lists are disjunct + SourceStatusList audio_source_list_ GUARDED_BY(crit_); // May be mixed. + + // Component that handles actual adding of audio frames. + FrameCombiner frame_combiner_ GUARDED_BY(race_checker_); + + RTC_DISALLOW_COPY_AND_ASSIGN(AudioMixerImpl); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_MIXER_AUDIO_MIXER_IMPL_H_ diff --git a/include/webrtc/modules/audio_mixer/default_output_rate_calculator.h b/include/webrtc/modules/audio_mixer/default_output_rate_calculator.h new file mode 100644 index 0000000..02c724d --- /dev/null +++ b/include/webrtc/modules/audio_mixer/default_output_rate_calculator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_MIXER_DEFAULT_OUTPUT_RATE_CALCULATOR_H_ +#define WEBRTC_MODULES_AUDIO_MIXER_DEFAULT_OUTPUT_RATE_CALCULATOR_H_ + +#include + +#include "webrtc/modules/audio_mixer/output_rate_calculator.h" + +namespace webrtc { + +class DefaultOutputRateCalculator : public OutputRateCalculator { + public: + static const int kDefaultFrequency = 48000; + + // Produces the least native rate greater or equal to the preferred + // sample rates. A native rate is one in + // AudioProcessing::NativeRate. If |preferred_sample_rates| is + // empty, returns |kDefaultFrequency|. + int CalculateOutputRate( + const std::vector& preferred_sample_rates) override; + ~DefaultOutputRateCalculator() override {} +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_MIXER_DEFAULT_OUTPUT_RATE_CALCULATOR_H_ diff --git a/include/webrtc/modules/audio_mixer/frame_combiner.h b/include/webrtc/modules/audio_mixer/frame_combiner.h new file mode 100644 index 0000000..11c2e68 --- /dev/null +++ b/include/webrtc/modules/audio_mixer/frame_combiner.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_MIXER_FRAME_COMBINER_H_ +#define WEBRTC_MODULES_AUDIO_MIXER_FRAME_COMBINER_H_ + +#include +#include + +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { + +class FrameCombiner { + public: + explicit FrameCombiner(bool use_apm_limiter); + ~FrameCombiner(); + + // Combine several frames into one. Assumes sample_rate, + // samples_per_channel of the input frames match the parameters. The + // extra parameters are needed because 'mix_list' can be empty. + void Combine(const std::vector& mix_list, + size_t number_of_channels, + int sample_rate, + AudioFrame* audio_frame_for_mixing) const; + + private: + // Lower-level helper function called from Combine(...) when there + // are several input frames. + // + // TODO(aleloi): change interface to ArrayView output_frame + // once we have gotten rid of the APM limiter. + // + // Only the 'data' field of output_frame should be modified. The + // rest are used for potentially sending the output to the APM + // limiter. + void CombineMultipleFrames( + const std::vector>& input_frames, + AudioFrame* audio_frame_for_mixing) const; + + const bool use_apm_limiter_; + std::unique_ptr limiter_; +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_MIXER_FRAME_COMBINER_H_ diff --git a/include/webrtc/modules/audio_mixer/output_rate_calculator.h b/include/webrtc/modules/audio_mixer/output_rate_calculator.h new file mode 100644 index 0000000..f9c7e1d --- /dev/null +++ b/include/webrtc/modules/audio_mixer/output_rate_calculator.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_MIXER_OUTPUT_RATE_CALCULATOR_H_ +#define WEBRTC_MODULES_AUDIO_MIXER_OUTPUT_RATE_CALCULATOR_H_ + +#include + +namespace webrtc { + +// Decides the sample rate of a mixing iteration given the preferred +// sample rates of the sources. +class OutputRateCalculator { + public: + virtual int CalculateOutputRate( + const std::vector& preferred_sample_rates) = 0; + virtual ~OutputRateCalculator() {} +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_MIXER_OUTPUT_RATE_CALCULATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec/aec_core.h b/include/webrtc/modules/audio_processing/aec/aec_core.h index 1ab2020..78cb787 100644 --- a/include/webrtc/modules/audio_processing/aec/aec_core.h +++ b/include/webrtc/modules/audio_processing/aec/aec_core.h @@ -26,6 +26,7 @@ extern "C" { #include "webrtc/common_audio/wav_file.h" #include "webrtc/modules/audio_processing/aec/aec_common.h" #include "webrtc/modules/audio_processing/utility/block_mean_calculator.h" +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -83,6 +84,21 @@ typedef struct PowerLevel { float minlevel; } PowerLevel; +class BlockBuffer { + public: + BlockBuffer(); + ~BlockBuffer(); + void ReInit(); + void Insert(const float block[PART_LEN]); + void ExtractExtendedBlock(float extended_block[PART_LEN]); + int AdjustSize(int buffer_size_decrease); + size_t Size(); + size_t AvaliableSpace(); + + private: + RingBuffer* buffer_; +}; + class DivergentFilterFraction { public: DivergentFilterFraction(); @@ -119,6 +135,7 @@ struct AecCore { ~AecCore(); std::unique_ptr data_dumper; + const OouraFft ooura_fft; CoherenceState coherence_state; @@ -128,16 +145,19 @@ struct AecCore { int inSamples, outSamples; int delayEstCtr; - RingBuffer* nearFrBuf; - RingBuffer* outFrBuf; + // Nearend buffer used for changing from FRAME_LEN to PART_LEN sample block + // sizes. The buffer stores all the incoming bands and for each band a maximum + // of PART_LEN - (FRAME_LEN - PART_LEN) values need to be buffered in order to + // change the block size from FRAME_LEN to PART_LEN. + float nearend_buffer[NUM_HIGH_BANDS_MAX + 1] + [PART_LEN - (FRAME_LEN - PART_LEN)]; + size_t nearend_buffer_size; + float output_buffer[NUM_HIGH_BANDS_MAX + 1][2 * PART_LEN]; + size_t output_buffer_size; - RingBuffer* nearFrBufH[NUM_HIGH_BANDS_MAX]; - RingBuffer* outFrBufH[NUM_HIGH_BANDS_MAX]; - - float dBuf[PART_LEN2]; // nearend float eBuf[PART_LEN2]; // error - float dBufH[NUM_HIGH_BANDS_MAX][PART_LEN2]; // nearend + float previous_nearend_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]; float xPow[PART_LEN1]; float dPow[PART_LEN1]; @@ -165,7 +185,7 @@ struct AecCore { int xfBufBlockPos; - RingBuffer* far_time_buf; + BlockBuffer farend_block_buffer_; int system_delay; // Current system delay buffered in AEC. @@ -208,7 +228,6 @@ struct AecCore { void* delay_estimator; // Variables associated with delay correction through signal based delay // estimation feedback. - int signal_delay_correction; int previous_delay; int delay_correction_count; int shift_offset; @@ -220,8 +239,7 @@ struct AecCore { int delay_agnostic_enabled; // 1 = extended filter mode enabled, 0 = disabled. int extended_filter_enabled; - // 1 = next generation aec mode enabled, 0 = disabled. - int aec3_enabled; + // 1 = refined filter adaptation aec mode enabled, 0 = disabled. bool refined_adaptive_filter_enabled; // Runtime selection of number of filter partitions. @@ -243,7 +261,7 @@ void WebRtcAec_InitAec_mips(void); void WebRtcAec_InitAec_neon(void); #endif -void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend); +void WebRtcAec_BufferFarendBlock(AecCore* aec, const float* farend); void WebRtcAec_ProcessFrames(AecCore* aec, const float* const* nearend, size_t num_bands, @@ -251,10 +269,11 @@ void WebRtcAec_ProcessFrames(AecCore* aec, int knownDelay, float* const* out); -// A helper function to call WebRtc_MoveReadPtr() for all far-end buffers. -// Returns the number of elements moved, and adjusts |system_delay| by the -// corresponding amount in ms. -int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements); +// A helper function to call adjust the farend buffer size. +// Returns the number of elements the size was decreased with, and adjusts +// |system_delay| by the corresponding amount in ms. +int WebRtcAec_AdjustFarendBufferSizeAndSystemDelay(AecCore* aec, + int size_decrease); // Calculates the median, standard deviation and amount of poor values among the // delay estimates aggregated up to the first call to the function. After that @@ -290,12 +309,6 @@ void WebRtcAec_enable_delay_agnostic(AecCore* self, int enable); // enabled and zero if disabled. int WebRtcAec_delay_agnostic_enabled(AecCore* self); -// Non-zero enables, zero disables. -void WebRtcAec_enable_aec3(AecCore* self, int enable); - -// Returns 1 if the next generation aec is enabled and zero if disabled. -int WebRtcAec_aec3_enabled(AecCore* self); - // Turns on/off the refined adaptive filter feature. void WebRtcAec_enable_refined_adaptive_filter(AecCore* self, bool enable); diff --git a/include/webrtc/modules/audio_processing/aec/aec_core_internal.h b/include/webrtc/modules/audio_processing/aec/aec_core_internal.h deleted file mode 100644 index d4fad9e..0000000 --- a/include/webrtc/modules/audio_processing/aec/aec_core_internal.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_INTERNAL_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_INTERNAL_H_ - -#include - -extern "C" { -#include "webrtc/common_audio/ring_buffer.h" -} -#include "webrtc/base/constructormagic.h" -#include "webrtc/common_audio/wav_file.h" -#include "webrtc/modules/audio_processing/aec/aec_common.h" -#include "webrtc/modules/audio_processing/aec/aec_core.h" -#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" -#include "webrtc/modules/audio_processing/utility/block_mean_calculator.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -// Number of partitions for the extended filter mode. The first one is an enum -// to be used in array declarations, as it represents the maximum filter length. -enum { kExtendedNumPartitions = 32 }; -static const int kNormalNumPartitions = 12; - -// Delay estimator constants, used for logging and delay compensation if -// if reported delays are disabled. -enum { kLookaheadBlocks = 15 }; -enum { - // 500 ms for 16 kHz which is equivalent with the limit of reported delays. - kHistorySizeBlocks = 125 -}; - -typedef struct PowerLevel { - PowerLevel(); - - BlockMeanCalculator framelevel; - BlockMeanCalculator averagelevel; - float minlevel; -} PowerLevel; - -class DivergentFilterFraction { - public: - DivergentFilterFraction(); - - // Reset. - void Reset(); - - void AddObservation(const PowerLevel& nearlevel, - const PowerLevel& linoutlevel, - const PowerLevel& nlpoutlevel); - - // Return the latest fraction. - float GetLatestFraction() const; - - private: - // Clear all values added. - void Clear(); - - size_t count_; - size_t occurrence_; - float fraction_; - - RTC_DISALLOW_COPY_AND_ASSIGN(DivergentFilterFraction); -}; - -typedef struct CoherenceState { - complex_t sde[PART_LEN1]; // cross-psd of nearend and error - complex_t sxd[PART_LEN1]; // cross-psd of farend and nearend - float sx[PART_LEN1], sd[PART_LEN1], se[PART_LEN1]; // far, near, error psd -} CoherenceState; - -struct AecCore { - explicit AecCore(int instance_index); - ~AecCore(); - - std::unique_ptr data_dumper; - - CoherenceState coherence_state; - - int farBufWritePos, farBufReadPos; - - int knownDelay; - int inSamples, outSamples; - int delayEstCtr; - - RingBuffer* nearFrBuf; - RingBuffer* outFrBuf; - - RingBuffer* nearFrBufH[NUM_HIGH_BANDS_MAX]; - RingBuffer* outFrBufH[NUM_HIGH_BANDS_MAX]; - - float dBuf[PART_LEN2]; // nearend - float eBuf[PART_LEN2]; // error - - float dBufH[NUM_HIGH_BANDS_MAX][PART_LEN2]; // nearend - - float xPow[PART_LEN1]; - float dPow[PART_LEN1]; - float dMinPow[PART_LEN1]; - float dInitMinPow[PART_LEN1]; - float* noisePow; - - float xfBuf[2][kExtendedNumPartitions * PART_LEN1]; // farend fft buffer - float wfBuf[2][kExtendedNumPartitions * PART_LEN1]; // filter fft - // Farend windowed fft buffer. - complex_t xfwBuf[kExtendedNumPartitions * PART_LEN1]; - - float hNs[PART_LEN1]; - float hNlFbMin, hNlFbLocalMin; - float hNlXdAvgMin; - int hNlNewMin, hNlMinCtr; - float overDrive; - float overdrive_scaling; - int nlp_mode; - float outBuf[PART_LEN]; - int delayIdx; - - short stNearState, echoState; - short divergeState; - - int xfBufBlockPos; - - RingBuffer* far_time_buf; - - int system_delay; // Current system delay buffered in AEC. - - int mult; // sampling frequency multiple - int sampFreq = 16000; - size_t num_bands; - uint32_t seed; - - float filter_step_size; // stepsize - float error_threshold; // error threshold - - int noiseEstCtr; - - PowerLevel farlevel; - PowerLevel nearlevel; - PowerLevel linoutlevel; - PowerLevel nlpoutlevel; - - int metricsMode; - int stateCounter; - Stats erl; - Stats erle; - Stats aNlp; - Stats rerl; - DivergentFilterFraction divergent_filter_fraction; - - // Quantities to control H band scaling for SWB input - int freq_avg_ic; // initial bin for averaging nlp gain - int flag_Hband_cn; // for comfort noise - float cn_scale_Hband; // scale for comfort noise in H band - - int delay_metrics_delivered; - int delay_histogram[kHistorySizeBlocks]; - int num_delay_values; - int delay_median; - int delay_std; - float fraction_poor_delays; - int delay_logging_enabled; - void* delay_estimator_farend; - void* delay_estimator; - // Variables associated with delay correction through signal based delay - // estimation feedback. - int signal_delay_correction; - int previous_delay; - int delay_correction_count; - int shift_offset; - float delay_quality_threshold; - int frame_count; - - // 0 = delay agnostic mode (signal based delay correction) disabled. - // Otherwise enabled. - int delay_agnostic_enabled; - // 1 = extended filter mode enabled, 0 = disabled. - int extended_filter_enabled; - // 1 = next generation aec mode enabled, 0 = disabled. - int aec3_enabled; - bool refined_adaptive_filter_enabled; - - // Runtime selection of number of filter partitions. - int num_partitions; - - // Flag that extreme filter divergence has been detected by the Echo - // Suppressor. - int extreme_filter_divergence; -}; - -typedef void (*WebRtcAecFilterFar)( - int num_partitions, - int x_fft_buf_block_pos, - float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], - float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1], - float y_fft[2][PART_LEN1]); -extern WebRtcAecFilterFar WebRtcAec_FilterFar; -typedef void (*WebRtcAecScaleErrorSignal)(float mu, - float error_threshold, - float x_pow[PART_LEN1], - float ef[2][PART_LEN1]); -extern WebRtcAecScaleErrorSignal WebRtcAec_ScaleErrorSignal; -typedef void (*WebRtcAecFilterAdaptation)( - int num_partitions, - int x_fft_buf_block_pos, - float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], - float e_fft[2][PART_LEN1], - float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]); -extern WebRtcAecFilterAdaptation WebRtcAec_FilterAdaptation; - -typedef void (*WebRtcAecOverdrive)(float overdrive_scaling, - const float hNlFb, - float hNl[PART_LEN1]); -extern WebRtcAecOverdrive WebRtcAec_Overdrive; - -typedef void (*WebRtcAecSuppress)(const float hNl[PART_LEN1], - float efw[2][PART_LEN1]); -extern WebRtcAecSuppress WebRtcAec_Suppress; - -typedef void (*WebRtcAecComputeCoherence)(const CoherenceState* coherence_state, - float* cohde, - float* cohxd); -extern WebRtcAecComputeCoherence WebRtcAec_ComputeCoherence; - -typedef void (*WebRtcAecUpdateCoherenceSpectra)(int mult, - bool extended_filter_enabled, - float efw[2][PART_LEN1], - float dfw[2][PART_LEN1], - float xfw[2][PART_LEN1], - CoherenceState* coherence_state, - short* filter_divergence_state, - int* extreme_filter_divergence); -extern WebRtcAecUpdateCoherenceSpectra WebRtcAec_UpdateCoherenceSpectra; - -typedef int (*WebRtcAecPartitionDelay)( - int num_partitions, - float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]); -extern WebRtcAecPartitionDelay WebRtcAec_PartitionDelay; - -typedef void (*WebRtcAecStoreAsComplex)(const float* data, - float data_complex[2][PART_LEN1]); -extern WebRtcAecStoreAsComplex WebRtcAec_StoreAsComplex; - -typedef void (*WebRtcAecWindowData)(float* x_windowed, const float* x); -extern WebRtcAecWindowData WebRtcAec_WindowData; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_INTERNAL_H_ diff --git a/include/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h b/include/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h index d1fb6e8..5e873c8 100644 --- a/include/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h +++ b/include/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h @@ -31,6 +31,7 @@ typedef void (*WebRtcAecScaleErrorSignal)(float mu, float ef[2][PART_LEN1]); extern WebRtcAecScaleErrorSignal WebRtcAec_ScaleErrorSignal; typedef void (*WebRtcAecFilterAdaptation)( + const OouraFft& ooura_fft, int num_partitions, int x_fft_buf_block_pos, float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], diff --git a/include/webrtc/modules/audio_processing/aec/aec_rdft.h b/include/webrtc/modules/audio_processing/aec/aec_rdft.h deleted file mode 100644 index d83eb27..0000000 --- a/include/webrtc/modules/audio_processing/aec/aec_rdft.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_ - -#include "webrtc/modules/audio_processing/aec/aec_common.h" - -// These intrinsics were unavailable before VS 2008. -// TODO(andrew): move to a common file. -#if defined(_MSC_VER) && _MSC_VER < 1500 -#include -static __inline __m128 _mm_castsi128_ps(__m128i a) { return *(__m128*)&a; } -static __inline __m128i _mm_castps_si128(__m128 a) { return *(__m128i*)&a; } -#endif - -// Constants shared by all paths (C, SSE2, NEON). -extern const float rdft_w[64]; -// Constants used by the C path. -extern const float rdft_wk3ri_first[16]; -extern const float rdft_wk3ri_second[16]; -// Constants used by SSE2 and NEON but initialized in the C path. -extern ALIGN16_BEG const float ALIGN16_END rdft_wk1r[32]; -extern ALIGN16_BEG const float ALIGN16_END rdft_wk2r[32]; -extern ALIGN16_BEG const float ALIGN16_END rdft_wk3r[32]; -extern ALIGN16_BEG const float ALIGN16_END rdft_wk1i[32]; -extern ALIGN16_BEG const float ALIGN16_END rdft_wk2i[32]; -extern ALIGN16_BEG const float ALIGN16_END rdft_wk3i[32]; -extern ALIGN16_BEG const float ALIGN16_END cftmdl_wk1r[4]; - -// code path selection function pointers -typedef void (*RftSub128)(float* a); -extern RftSub128 rftfsub_128; -extern RftSub128 rftbsub_128; -extern RftSub128 cft1st_128; -extern RftSub128 cftmdl_128; -extern RftSub128 cftfsub_128; -extern RftSub128 cftbsub_128; -extern RftSub128 bitrv2_128; - -// entry points -void aec_rdft_init(void); -void aec_rdft_init_sse2(void); -void aec_rdft_forward_128(float* a); -void aec_rdft_inverse_128(float* a); - -#if defined(MIPS_FPU_LE) -void aec_rdft_init_mips(void); -#endif -#if defined(WEBRTC_HAS_NEON) -void aec_rdft_init_neon(void); -#endif - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_RDFT_H_ diff --git a/include/webrtc/modules/audio_processing/aec/echo_cancellation.h b/include/webrtc/modules/audio_processing/aec/echo_cancellation.h index 8e5e52c..1047113 100644 --- a/include/webrtc/modules/audio_processing/aec/echo_cancellation.h +++ b/include/webrtc/modules/audio_processing/aec/echo_cancellation.h @@ -65,6 +65,9 @@ struct AecCore; class ApmDataDumper; typedef struct Aec { + Aec(); + ~Aec(); + std::unique_ptr data_dumper; int delayCtr; diff --git a/include/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h b/include/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h new file mode 100644 index 0000000..d927f14 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ADAPTIVE_FIR_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ADAPTIVE_FIR_FILTER_H_ + +#include +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec3_fft.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" +#include "webrtc/modules/audio_processing/aec3/fft_data.h" +#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" + +namespace webrtc { +namespace aec3 { +// Adapts the filter partitions. +void AdaptPartitions(const FftBuffer& X_buffer, + const FftData& G, + rtc::ArrayView H); +#if defined(WEBRTC_ARCH_X86_FAMILY) +void AdaptPartitions_SSE2(const FftBuffer& X_buffer, + const FftData& G, + rtc::ArrayView H); +#endif + +// Produces the filter output. +void ApplyFilter(const FftBuffer& X_buffer, + rtc::ArrayView H, + FftData* S); +#if defined(WEBRTC_ARCH_X86_FAMILY) +void ApplyFilter_SSE2(const FftBuffer& X_buffer, + rtc::ArrayView H, + FftData* S); +#endif + +} // namespace aec3 + +// Provides a frequency domain adaptive filter functionality. +class AdaptiveFirFilter { + public: + AdaptiveFirFilter(size_t size_partitions, + bool use_filter_statistics, + Aec3Optimization optimization, + ApmDataDumper* data_dumper); + + ~AdaptiveFirFilter(); + + // Produces the output of the filter. + void Filter(const FftBuffer& X_buffer, FftData* S) const; + + // Adapts the filter. + void Adapt(const FftBuffer& X_buffer, const FftData& G); + + // Receives reports that known echo path changes have occured and adjusts + // the filter adaptation accordingly. + void HandleEchoPathChange(); + + // Returns the filter size. + size_t SizePartitions() const { return H_.size(); } + + // Returns the filter based echo return loss. This method can only be used if + // the usage of filter statistics has been specified during the creation of + // the adaptive filter. + const std::array& Erl() const { + RTC_DCHECK(erl_) << "The filter must be created with use_filter_statistics " + "set to true in order to be able to call retrieve the " + "ERL."; + return *erl_; + } + + // Returns the frequency responses for the filter partitions. This method can + // only be used if the usage of filter statistics has been specified during + // the creation of the adaptive filter. + const std::vector>& + FilterFrequencyResponse() const { + RTC_DCHECK(H2_) << "The filter must be created with use_filter_statistics " + "set to true in order to be able to call retrieve the " + "filter frequency responde."; + return *H2_; + } + + void DumpFilter(const char* name) { + for (auto& H : H_) { + data_dumper_->DumpRaw(name, H.re); + data_dumper_->DumpRaw(name, H.im); + } + } + + private: + ApmDataDumper* const data_dumper_; + const Aec3Fft fft_; + const Aec3Optimization optimization_; + std::vector H_; + std::unique_ptr>> H2_; + std::unique_ptr> erl_; + size_t partition_to_constrain_ = 0; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AdaptiveFirFilter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ADAPTIVE_FIR_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/aec3_common.h b/include/webrtc/modules/audio_processing/aec3/aec3_common.h new file mode 100644 index 0000000..1d4a9fe --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/aec3_common.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_COMMON_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_COMMON_H_ + +#include +#include "webrtc/typedefs.h" + +namespace webrtc { + +#ifdef _MSC_VER /* visual c++ */ +#define ALIGN16_BEG __declspec(align(16)) +#define ALIGN16_END +#else /* gcc or icc */ +#define ALIGN16_BEG +#define ALIGN16_END __attribute__((aligned(16))) +#endif + +enum class Aec3Optimization { kNone, kSse2 }; + +constexpr int kMetricsReportingIntervalBlocks = 10 * 250; +constexpr int kMetricsComputationBlocks = 9; +constexpr int kMetricsCollectionBlocks = + kMetricsReportingIntervalBlocks - kMetricsComputationBlocks; + +constexpr size_t kFftLengthBy2 = 64; +constexpr size_t kFftLengthBy2Plus1 = kFftLengthBy2 + 1; +constexpr size_t kFftLengthBy2Minus1 = kFftLengthBy2 - 1; +constexpr size_t kFftLength = 2 * kFftLengthBy2; + +constexpr size_t kMaxNumBands = 3; +constexpr size_t kSubFrameLength = 80; + +constexpr size_t kBlockSize = kFftLengthBy2; +constexpr size_t kExtendedBlockSize = 2 * kFftLengthBy2; +constexpr size_t kSubBlockSize = 16; + +constexpr size_t NumBandsForRate(int sample_rate_hz) { + return static_cast(sample_rate_hz == 8000 ? 1 + : sample_rate_hz / 16000); +} +constexpr int LowestBandRate(int sample_rate_hz) { + return sample_rate_hz == 8000 ? sample_rate_hz : 16000; +} + +constexpr bool ValidFullBandRate(int sample_rate_hz) { + return sample_rate_hz == 8000 || sample_rate_hz == 16000 || + sample_rate_hz == 32000 || sample_rate_hz == 48000; +} + +// Detects what kind of optimizations to use for the code. +Aec3Optimization DetectOptimization(); + +static_assert(1 == NumBandsForRate(8000), "Number of bands for 8 kHz"); +static_assert(1 == NumBandsForRate(16000), "Number of bands for 16 kHz"); +static_assert(2 == NumBandsForRate(32000), "Number of bands for 32 kHz"); +static_assert(3 == NumBandsForRate(48000), "Number of bands for 48 kHz"); + +static_assert(8000 == LowestBandRate(8000), "Sample rate of band 0 for 8 kHz"); +static_assert(16000 == LowestBandRate(16000), + "Sample rate of band 0 for 16 kHz"); +static_assert(16000 == LowestBandRate(32000), + "Sample rate of band 0 for 32 kHz"); +static_assert(16000 == LowestBandRate(48000), + "Sample rate of band 0 for 48 kHz"); + +static_assert(ValidFullBandRate(8000), + "Test that 8 kHz is a valid sample rate"); +static_assert(ValidFullBandRate(16000), + "Test that 16 kHz is a valid sample rate"); +static_assert(ValidFullBandRate(32000), + "Test that 32 kHz is a valid sample rate"); +static_assert(ValidFullBandRate(48000), + "Test that 48 kHz is a valid sample rate"); +static_assert(!ValidFullBandRate(8001), + "Test that 8001 Hz is not a valid sample rate"); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_COMMON_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/aec3_fft.h b/include/webrtc/modules/audio_processing/aec3/aec3_fft.h new file mode 100644 index 0000000..6cfe3bd --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/aec3_fft.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_FFT_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_FFT_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_data.h" +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" + +namespace webrtc { + +// Wrapper class that provides 128 point real valued FFT functionality with the +// FftData type. +class Aec3Fft { + public: + Aec3Fft() = default; + // Computes the FFT. Note that both the input and output are modified. + void Fft(std::array* x, FftData* X) const { + RTC_DCHECK(x); + RTC_DCHECK(X); + ooura_fft_.Fft(x->data()); + X->CopyFromPackedArray(*x); + } + // Computes the inverse Fft. + void Ifft(const FftData& X, std::array* x) const { + RTC_DCHECK(x); + X.CopyToPackedArray(x); + ooura_fft_.InverseFft(x->data()); + } + + // Pads the input with kFftLengthBy2 initial zeros before computing the Fft. + void ZeroPaddedFft(rtc::ArrayView x, FftData* X) const; + + // Concatenates the kFftLengthBy2 values long x and x_old before computing the + // Fft. After that, x is copied to x_old. + void PaddedFft(rtc::ArrayView x, + rtc::ArrayView x_old, + FftData* X) const; + + private: + const OouraFft ooura_fft_; + + RTC_DISALLOW_COPY_AND_ASSIGN(Aec3Fft); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC3_FFT_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/aec_state.h b/include/webrtc/modules/audio_processing/aec3/aec_state.h new file mode 100644 index 0000000..56fee2c --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/aec_state.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_ + +#include +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" +#include "webrtc/modules/audio_processing/aec3/erle_estimator.h" +#include "webrtc/modules/audio_processing/aec3/erl_estimator.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { + +class ApmDataDumper; + +// Handles the state and the conditions for the echo removal functionality. +class AecState { + public: + AecState(); + ~AecState(); + + // Returns whether the linear filter estimate is usable. + bool UsableLinearEstimate() const { return usable_linear_estimate_; } + + // Returns whether there has been echo leakage detected. + bool EchoLeakageDetected() const { return echo_leakage_detected_; } + + // Returns whether it is possible at all to use the model based echo removal + // functionalities. + bool ModelBasedAecFeasible() const { return model_based_aec_feasible_; } + + // Returns whether the render signal is currently active. + bool ActiveRender() const { return active_render_counter_ > 0; } + + // Returns whether the number of active render blocks since an echo path + // change. + size_t ActiveRenderBlocks() const { return active_render_blocks_; } + + // Returns the ERLE. + const std::array& Erle() const { + return erle_estimator_.Erle(); + } + + // Returns the ERL. + const std::array& Erl() const { + return erl_estimator_.Erl(); + } + + // Returns the delay estimate based on the linear filter. + rtc::Optional FilterDelay() const { return filter_delay_; } + + // Returns the externally provided delay. + rtc::Optional ExternalDelay() const { return external_delay_; } + + // Returns the bands where the linear filter is reliable. + const std::array& BandsWithReliableFilter() const { + return bands_with_reliable_filter_; + } + + // Reports whether the filter is poorly aligned. + bool PoorlyAlignedFilter() const { + return FilterDelay() ? *FilterDelay() > 0.75f * filter_length_ : false; + } + + // Returns the strength of the filter. + const std::array& FilterEstimateStrength() const { + return filter_estimate_strength_; + } + + // Returns whether the capture signal is saturated. + bool SaturatedCapture() const { return capture_signal_saturation_; } + + // Updates the capture signal saturation. + void UpdateCaptureSaturation(bool capture_signal_saturation) { + capture_signal_saturation_ = capture_signal_saturation; + } + + // Returns whether a probable headset setup has been detected. + bool HeadsetDetected() const { return headset_detected_; } + + // Updates the aec state. + void Update(const std::vector>& + filter_frequency_response, + const rtc::Optional& external_delay_samples, + const FftBuffer& X_buffer, + const std::array& E2_main, + const std::array& E2_shadow, + const std::array& Y2, + rtc::ArrayView x, + const EchoPathVariability& echo_path_variability, + bool echo_leakage_detected); + + private: + static int instance_count_; + std::unique_ptr data_dumper_; + ErlEstimator erl_estimator_; + ErleEstimator erle_estimator_; + int echo_path_change_counter_; + int active_render_counter_; + size_t active_render_blocks_ = 0; + bool usable_linear_estimate_ = false; + bool echo_leakage_detected_ = false; + bool model_based_aec_feasible_ = false; + bool capture_signal_saturation_ = false; + bool headset_detected_ = false; + rtc::Optional filter_delay_; + rtc::Optional external_delay_; + std::array bands_with_reliable_filter_; + std::array filter_estimate_strength_; + size_t filter_length_; + + RTC_DISALLOW_COPY_AND_ASSIGN(AecState); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_AEC_STATE_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/block_framer.h b/include/webrtc/modules/audio_processing/aec3/block_framer.h new file mode 100644 index 0000000..c8bca8e --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/block_framer.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { + +// Class for producing frames consisting of 1 or 2 subframes of 80 samples each +// from 64 sample blocks. The class is designed to work together with the +// FrameBlocker class which performs the reverse conversion. Used together with +// that, this class produces output frames are the same rate as frames are +// received by the FrameBlocker class. Note that the internal buffers will +// overrun if any other rate of packets insertion is used. +class BlockFramer { + public: + explicit BlockFramer(size_t num_bands); + ~BlockFramer(); + // Adds a 64 sample block into the data that will form the next output frame. + void InsertBlock(const std::vector>& block); + // Adds a 64 sample block and extracts an 80 sample subframe. + void InsertBlockAndExtractSubFrame( + const std::vector>& block, + std::vector>* sub_frame); + + private: + const size_t num_bands_; + std::vector> buffer_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BlockFramer); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_FRAMER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/block_processor.h b/include/webrtc/modules/audio_processing/aec3/block_processor.h new file mode 100644 index 0000000..12a994e --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/block_processor.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ + +#include +#include + +#include "webrtc/modules/audio_processing/aec3/echo_remover.h" +#include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" +#include "webrtc/modules/audio_processing/aec3/render_delay_controller.h" + +namespace webrtc { + +// Class for performing echo cancellation on 64 sample blocks of audio data. +class BlockProcessor { + public: + static BlockProcessor* Create(int sample_rate_hz); + // Only used for testing purposes. + static BlockProcessor* Create( + int sample_rate_hz, + std::unique_ptr render_buffer); + static BlockProcessor* Create( + int sample_rate_hz, + std::unique_ptr render_buffer, + std::unique_ptr delay_controller, + std::unique_ptr echo_remover); + + virtual ~BlockProcessor() = default; + + // Processes a block of capture data. + virtual void ProcessCapture( + bool echo_path_gain_change, + bool capture_signal_saturation, + std::vector>* capture_block) = 0; + + // Buffers a block of render data supplied by a FrameBlocker object. Returns a + // bool indicating the success of the buffering. + virtual bool BufferRender(std::vector>* render_block) = 0; + + // Reports whether echo leakage has been detected in the echo canceller + // output. + virtual void UpdateEchoLeakageStatus(bool leakage_detected) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/block_processor_metrics.h b/include/webrtc/modules/audio_processing/aec3/block_processor_metrics.h new file mode 100644 index 0000000..6c278cd --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/block_processor_metrics.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_ + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +// Handles the reporting of metrics for the block_processor. +class BlockProcessorMetrics { + public: + BlockProcessorMetrics() = default; + + // Updates the metric with new capture data. + void UpdateCapture(bool underrun); + + // Updates the metric with new render data. + void UpdateRender(bool overrun); + + // Returns true if the metrics have just been reported, otherwise false. + bool MetricsReported() { return metrics_reported_; } + + private: + // Resets the metrics. + void ResetMetrics(); + + int capture_block_counter_ = 0; + bool metrics_reported_ = false; + int render_buffer_underruns_ = 0; + int render_buffer_overruns_ = 0; + int buffer_render_calls_ = 0; + + RTC_DISALLOW_COPY_AND_ASSIGN(BlockProcessorMetrics); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_BLOCK_PROCESSOR_METRICS_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h b/include/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h new file mode 100644 index 0000000..438a166 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +// Applies a number of identical biquads in a cascaded manner. The filter +// implementation is direct form 1. +class CascadedBiQuadFilter { + public: + struct BiQuadState { + BiQuadState() : x(), y() {} + float x[2]; + float y[2]; + }; + + struct BiQuadCoefficients { + float b[3]; + float a[2]; + }; + + CascadedBiQuadFilter( + const CascadedBiQuadFilter::BiQuadCoefficients& coefficients, + size_t num_biquads); + ~CascadedBiQuadFilter(); + // Applies the biquads on the values in x in order to form the output in y. + void Process(rtc::ArrayView x, rtc::ArrayView y); + // Applies the biquads on the values in y in an in-place manner. + void Process(rtc::ArrayView y); + + private: + void ApplyBiQuad(rtc::ArrayView x, + rtc::ArrayView y, + CascadedBiQuadFilter::BiQuadState* biquad_state); + + std::vector biquad_states_; + const BiQuadCoefficients coefficients_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CascadedBiQuadFilter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_CASCADED_BIQUAD_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/comfort_noise_generator.h b/include/webrtc/modules/audio_processing/aec3/comfort_noise_generator.h new file mode 100644 index 0000000..14332f7 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/comfort_noise_generator.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_COMFORT_NOISE_GENERATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_COMFORT_NOISE_GENERATOR_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec_state.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_data.h" + +namespace webrtc { +namespace aec3 { +#if defined(WEBRTC_ARCH_X86_FAMILY) + +void EstimateComfortNoise_SSE2(const std::array& N2, + uint32_t* seed, + FftData* lower_band_noise, + FftData* upper_band_noise); +#endif +void EstimateComfortNoise(const std::array& N2, + uint32_t* seed, + FftData* lower_band_noise, + FftData* upper_band_noise); + +} // namespace aec3 + +// Generates the comfort noise. +class ComfortNoiseGenerator { + public: + explicit ComfortNoiseGenerator(Aec3Optimization optimization); + ~ComfortNoiseGenerator(); + + // Computes the comfort noise. + void Compute(const AecState& aec_state, + const std::array& capture_spectrum, + FftData* lower_band_noise, + FftData* upper_band_noise); + + // Returns the estimate of the background noise spectrum. + const std::array& NoiseSpectrum() const { + return N2_; + } + + private: + const Aec3Optimization optimization_; + uint32_t seed_; + std::unique_ptr> N2_initial_; + std::array Y2_smoothed_; + std::array N2_; + int N2_counter_ = 0; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ComfortNoiseGenerator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_COMFORT_NOISE_GENERATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/decimator_by_4.h b/include/webrtc/modules/audio_processing/aec3/decimator_by_4.h new file mode 100644 index 0000000..9a22dfc --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/decimator_by_4.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_DECIMATOR_BY_4_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_DECIMATOR_BY_4_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" + +namespace webrtc { + +// Provides functionality for decimating a signal by 4. +class DecimatorBy4 { + public: + DecimatorBy4(); + + // Downsamples the signal. + void Decimate(rtc::ArrayView in, + std::array* out); + + private: + CascadedBiQuadFilter low_pass_filter_; + + RTC_DISALLOW_COPY_AND_ASSIGN(DecimatorBy4); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_DECIMATOR_BY_4_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/echo_canceller3.h b/include/webrtc/modules/audio_processing/aec3/echo_canceller3.h new file mode 100644 index 0000000..f1a7f38 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/echo_canceller3.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/race_checker.h" +#include "webrtc/base/swap_queue.h" +#include "webrtc/modules/audio_processing/aec3/block_framer.h" +#include "webrtc/modules/audio_processing/aec3/block_processor.h" +#include "webrtc/modules/audio_processing/aec3/cascaded_biquad_filter.h" +#include "webrtc/modules/audio_processing/aec3/frame_blocker.h" +#include "webrtc/modules/audio_processing/audio_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" + +namespace webrtc { + +// Functor for verifying the invariance of the frames being put into the render +// queue. +class Aec3RenderQueueItemVerifier { + public: + explicit Aec3RenderQueueItemVerifier(size_t num_bands, size_t frame_length) + : num_bands_(num_bands), frame_length_(frame_length) {} + + bool operator()(const std::vector>& v) const { + if (v.size() != num_bands_) { + return false; + } + for (const auto& v_k : v) { + if (v_k.size() != frame_length_) { + return false; + } + } + return true; + } + + private: + const size_t num_bands_; + const size_t frame_length_; +}; + +// Main class for the echo canceller3. +// It does 4 things: +// -Receives 10 ms frames of band-split audio. +// -Optionally applies an anti-hum (high-pass) filter on the +// received signals. +// -Provides the lower level echo canceller functionality with +// blocks of 64 samples of audio data. +// -Partially handles the jitter in the render and capture API +// call sequence. +// +// The class is supposed to be used in a non-concurrent manner apart from the +// AnalyzeRender call which can be called concurrently with the other methods. +class EchoCanceller3 { + public: + // Normal c-tor to use. + EchoCanceller3(int sample_rate_hz, bool use_highpass_filter); + // Testing c-tor that is used only for testing purposes. + EchoCanceller3(int sample_rate_hz, + bool use_highpass_filter, + std::unique_ptr block_processor); + ~EchoCanceller3(); + // Analyzes and stores an internal copy of the split-band domain render + // signal. + bool AnalyzeRender(AudioBuffer* farend); + // Analyzes the full-band domain capture signal to detect signal saturation. + void AnalyzeCapture(AudioBuffer* capture); + // Processes the split-band domain capture signal in order to remove any echo + // present in the signal. + void ProcessCapture(AudioBuffer* capture, bool level_change); + + // Signals whether an external detector has detected echo leakage from the + // echo canceller. + // Note that in the case echo leakage has been flagged, it should be unflagged + // once it is no longer occurring. + void UpdateEchoLeakageStatus(bool leakage_detected) { + RTC_DCHECK_RUNS_SERIALIZED(&capture_race_checker_); + block_processor_->UpdateEchoLeakageStatus(leakage_detected); + } + + // Validates a config. + static bool Validate(const AudioProcessing::Config::EchoCanceller3& config); + // Dumps a config to a string. + static std::string ToString( + const AudioProcessing::Config::EchoCanceller3& config); + + private: + class RenderWriter; + + // Empties the render SwapQueue. A bool is returned that indicates the success + // of the operation. + bool EmptyRenderQueue(); + + rtc::RaceChecker capture_race_checker_; + rtc::RaceChecker render_race_checker_; + + // State that is accessed by the AnalyzeRender call. + std::unique_ptr render_writer_ GUARDED_BY(render_race_checker_); + + // State that may be accessed by the capture thread. + static int instance_count_; + std::unique_ptr data_dumper_; + const int sample_rate_hz_; + const int num_bands_; + const size_t frame_length_; + BlockFramer output_framer_ GUARDED_BY(capture_race_checker_); + FrameBlocker capture_blocker_ GUARDED_BY(capture_race_checker_); + FrameBlocker render_blocker_ GUARDED_BY(capture_race_checker_); + SwapQueue>, Aec3RenderQueueItemVerifier> + render_transfer_queue_; + std::unique_ptr block_processor_ + GUARDED_BY(capture_race_checker_); + std::vector> render_queue_output_frame_ + GUARDED_BY(capture_race_checker_); + std::unique_ptr capture_highpass_filter_ + GUARDED_BY(capture_race_checker_); + bool saturated_microphone_signal_ GUARDED_BY(capture_race_checker_) = false; + std::vector> block_ GUARDED_BY(capture_race_checker_); + std::vector> sub_frame_view_ + GUARDED_BY(capture_race_checker_); + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h b/include/webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h new file mode 100644 index 0000000..bbe9a7c --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/echo_path_delay_estimator.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_DELAY_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_DELAY_ESTIMATOR_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/matched_filter.h" +#include "webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator.h" +#include "webrtc/modules/audio_processing/aec3/decimator_by_4.h" + +namespace webrtc { + +class ApmDataDumper; + +// Estimates the delay of the echo path. +class EchoPathDelayEstimator { + public: + explicit EchoPathDelayEstimator(ApmDataDumper* data_dumper); + ~EchoPathDelayEstimator(); + + // Produce a delay estimate if such is avaliable. + rtc::Optional EstimateDelay(rtc::ArrayView render, + rtc::ArrayView capture); + + private: + ApmDataDumper* const data_dumper_; + DecimatorBy4 render_decimator_; + DecimatorBy4 capture_decimator_; + MatchedFilter matched_filter_; + MatchedFilterLagAggregator matched_filter_lag_aggregator_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoPathDelayEstimator); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_DELAY_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/echo_path_variability.h b/include/webrtc/modules/audio_processing/aec3/echo_path_variability.h new file mode 100644 index 0000000..7755362 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/echo_path_variability.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_VARIABILITY_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_VARIABILITY_H_ + +namespace webrtc { + +struct EchoPathVariability { + EchoPathVariability(bool gain_change, bool delay_change); + + bool AudioPathChanged() const { return gain_change || delay_change; } + bool gain_change; + bool delay_change; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_PATH_VARIABILITY_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/echo_remover.h b/include/webrtc/modules/audio_processing/aec3/echo_remover.h new file mode 100644 index 0000000..f7ac50c --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/echo_remover.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_ + +#include + +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" + +namespace webrtc { + +// Class for removing the echo from the capture signal. +class EchoRemover { + public: + static EchoRemover* Create(int sample_rate_hz); + virtual ~EchoRemover() = default; + + // Removes the echo from a block of samples from the capture signal. The + // supplied render signal is assumed to be pre-aligned with the capture + // signal. + virtual void ProcessBlock( + const rtc::Optional& echo_path_delay_samples, + const EchoPathVariability& echo_path_variability, + bool capture_signal_saturation, + const std::vector>& render, + std::vector>* capture) = 0; + + // Updates the status on whether echo leakage is detected in the output of the + // echo remover. + virtual void UpdateEchoLeakageStatus(bool leakage_detected) = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/echo_remover_metrics.h b/include/webrtc/modules/audio_processing/aec3/echo_remover_metrics.h new file mode 100644 index 0000000..aaca159 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/echo_remover_metrics.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec_state.h" + +namespace webrtc { + +// Handles the reporting of metrics for the echo remover. +class EchoRemoverMetrics { + public: + struct DbMetric { + DbMetric(); + DbMetric(float sum_value, float floor_value, float ceil_value); + void Update(float value); + float sum_value; + float floor_value; + float ceil_value; + }; + + EchoRemoverMetrics(); + + // Updates the metric with new data. + void Update( + const AecState& aec_state, + const std::array& comfort_noise_spectrum, + const std::array& suppressor_gain); + + // Returns true if the metrics have just been reported, otherwise false. + bool MetricsReported() { return metrics_reported_; } + + private: + // Resets the metrics. + void ResetMetrics(); + + int block_counter_ = 0; + std::array erl_; + std::array erle_; + std::array comfort_noise_; + std::array suppressor_gain_; + int active_render_count_ = 0; + bool saturated_capture_ = false; + bool metrics_reported_ = false; + + RTC_DISALLOW_COPY_AND_ASSIGN(EchoRemoverMetrics); +}; + +namespace aec3 { + +// Updates a banded metric of type DbMetric with the values in the supplied +// array. +void UpdateDbMetric(const std::array& value, + std::array* statistic); + +// Transforms a DbMetric from the linear domain into the logarithmic domain. +int TransformDbMetricForReporting(bool negate, + float min_value, + float max_value, + float offset, + float scaling, + float value); + +} // namespace aec3 + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ECHO_REMOVER_METRICS_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/erl_estimator.h b/include/webrtc/modules/audio_processing/aec3/erl_estimator.h new file mode 100644 index 0000000..33eba26 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/erl_estimator.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERL_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERL_ESTIMATOR_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { + +// Estimates the echo return loss based on the signal spectra. +class ErlEstimator { + public: + ErlEstimator(); + ~ErlEstimator(); + + // Updates the ERL estimate. + void Update(const std::array& render_spectrum, + const std::array& capture_spectrum); + + // Returns the most recent ERL estimate. + const std::array& Erl() const { return erl_; } + + private: + std::array erl_; + std::array hold_counters_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ErlEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERL_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/erle_estimator.h b/include/webrtc/modules/audio_processing/aec3/erle_estimator.h new file mode 100644 index 0000000..d504ef2 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/erle_estimator.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERLE_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERLE_ESTIMATOR_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { + +// Estimates the echo return loss enhancement based on the signal spectra. +class ErleEstimator { + public: + ErleEstimator(); + ~ErleEstimator(); + + // Updates the ERLE estimate. + void Update(const std::array& render_spectrum, + const std::array& capture_spectrum, + const std::array& subtractor_spectrum); + + // Returns the most recent ERLE estimate. + const std::array& Erle() const { return erle_; } + + private: + std::array erle_; + std::array hold_counters_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ErleEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_ERLE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/fft_buffer.h b/include/webrtc/modules/audio_processing/aec3/fft_buffer.h new file mode 100644 index 0000000..c99c957 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/fft_buffer.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_BUFFER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_BUFFER_H_ + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/fft_data.h" + +namespace webrtc { + +// Provides a circular buffer for 128 point real-valued FFT data. +class FftBuffer { + public: + // The constructor takes as parameters the size of the buffer, as well as a + // vector containing the number of FFTs that will be included in the spectral + // sums in the call to SpectralSum. + FftBuffer(Aec3Optimization optimization, + size_t size, + const std::vector num_ffts_for_spectral_sums); + ~FftBuffer(); + + // Insert an FFT into the buffer. + void Insert(const FftData& fft); + + // Get the spectrum from one of the FFTs in the buffer + const std::array& Spectrum( + size_t buffer_offset_ffts) const { + return spectrum_buffer_[(position_ + buffer_offset_ffts) % + fft_buffer_.size()]; + } + + // Returns the sum of the spectrums for a certain number of FFTs. + const std::array& SpectralSum( + size_t num_ffts) const { + RTC_DCHECK_EQ(spectral_sums_length_, num_ffts); + return spectral_sums_[0]; + } + + // Returns the circular buffer. + rtc::ArrayView Buffer() const { return fft_buffer_; } + + // Returns the current position in the circular buffer + size_t Position() const { return position_; } + + private: + const Aec3Optimization optimization_; + std::vector fft_buffer_; + std::vector> spectrum_buffer_; + size_t spectral_sums_length_; + std::vector> spectral_sums_; + size_t position_ = 0; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FftBuffer); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_BUFFER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/fft_data.h b/include/webrtc/modules/audio_processing/aec3/fft_data.h new file mode 100644 index 0000000..5a92d91 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/fft_data.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_ + +#include "webrtc/typedefs.h" +#if defined(WEBRTC_ARCH_X86_FAMILY) +#include +#endif +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { + +// Struct that holds imaginary data produced from 128 point real-valued FFTs. +struct FftData { + // Copies the data in src. + void Assign(const FftData& src) { + std::copy(src.re.begin(), src.re.end(), re.begin()); + std::copy(src.im.begin(), src.im.end(), im.begin()); + im[0] = im[kFftLengthBy2] = 0; + } + + // Clears all the imaginary. + void Clear() { + re.fill(0.f); + im.fill(0.f); + } + + // Computes the power spectrum of the data. + void Spectrum(Aec3Optimization optimization, + std::array* power_spectrum) const { + RTC_DCHECK(power_spectrum); + switch (optimization) { +#if defined(WEBRTC_ARCH_X86_FAMILY) + case Aec3Optimization::kSse2: { + constexpr int kNumFourBinBands = kFftLengthBy2 / 4; + constexpr int kLimit = kNumFourBinBands * 4; + for (size_t k = 0; k < kLimit; k += 4) { + const __m128 r = _mm_loadu_ps(&re[k]); + const __m128 i = _mm_loadu_ps(&im[k]); + const __m128 ii = _mm_mul_ps(i, i); + const __m128 rr = _mm_mul_ps(r, r); + const __m128 rrii = _mm_add_ps(rr, ii); + _mm_storeu_ps(&(*power_spectrum)[k], rrii); + } + (*power_spectrum)[kFftLengthBy2] = + re[kFftLengthBy2] * re[kFftLengthBy2] + + im[kFftLengthBy2] * im[kFftLengthBy2]; + } break; +#endif + default: + std::transform(re.begin(), re.end(), im.begin(), + power_spectrum->begin(), + [](float a, float b) { return a * a + b * b; }); + } + } + + // Copy the data from an interleaved array. + void CopyFromPackedArray(const std::array& v) { + re[0] = v[0]; + re[kFftLengthBy2] = v[1]; + im[0] = im[kFftLengthBy2] = 0; + for (size_t k = 1, j = 2; k < kFftLengthBy2; ++k) { + re[k] = v[j++]; + im[k] = v[j++]; + } + } + + // Copies the data into an interleaved array. + void CopyToPackedArray(std::array* v) const { + RTC_DCHECK(v); + (*v)[0] = re[0]; + (*v)[1] = re[kFftLengthBy2]; + for (size_t k = 1, j = 2; k < kFftLengthBy2; ++k) { + (*v)[j++] = re[k]; + (*v)[j++] = im[k]; + } + } + + std::array re; + std::array im; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/frame_blocker.h b/include/webrtc/modules/audio_processing/aec3/frame_blocker.h new file mode 100644 index 0000000..c421720 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/frame_blocker.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { + +// Class for producing 64 sample multiband blocks from frames consisting of 1 or +// 2 subframes of 80 samples. +class FrameBlocker { + public: + explicit FrameBlocker(size_t num_bands); + ~FrameBlocker(); + // Inserts one 80 sample multiband subframe from the multiband frame and + // extracts one 64 sample multiband block. + void InsertSubFrameAndExtractBlock( + const std::vector>& sub_frame, + std::vector>* block); + // Reports whether a multiband block of 64 samples is available for + // extraction. + bool IsBlockAvailable() const; + // Extracts a multiband block of 64 samples. + void ExtractBlock(std::vector>* block); + + private: + const size_t num_bands_; + std::vector> buffer_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameBlocker); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_FRAME_BLOCKER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/main_filter_update_gain.h b/include/webrtc/modules/audio_processing/aec3/main_filter_update_gain.h new file mode 100644 index 0000000..9a3d8ee --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/main_filter_update_gain.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MAIN_FILTER_UPDATE_GAIN_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MAIN_FILTER_UPDATE_GAIN_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/render_signal_analyzer.h" +#include "webrtc/modules/audio_processing/aec3/subtractor_output.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { + +class ApmDataDumper; + +// Provides functionality for computing the adaptive gain for the main filter. +class MainFilterUpdateGain { + public: + MainFilterUpdateGain(); + ~MainFilterUpdateGain(); + + // Takes action in the case of a known echo path change. + void HandleEchoPathChange(); + + // Computes the gain. + void Compute(const FftBuffer& render_buffer, + const RenderSignalAnalyzer& render_signal_analyzer, + const SubtractorOutput& subtractor_output, + const AdaptiveFirFilter& filter, + bool saturated_capture_signal, + FftData* gain_fft); + + private: + static int instance_count_; + std::unique_ptr data_dumper_; + std::array H_error_; + size_t poor_excitation_counter_; + size_t call_counter_ = 0; + RTC_DISALLOW_COPY_AND_ASSIGN(MainFilterUpdateGain); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MAIN_FILTER_UPDATE_GAIN_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/matched_filter.h b/include/webrtc/modules/audio_processing/aec3/matched_filter.h new file mode 100644 index 0000000..4be4cc2 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/matched_filter.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_H_ + +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" + +namespace webrtc { +namespace aec3 { + +#if defined(WEBRTC_ARCH_X86_FAMILY) + +// Filter core for the matched filter that is optimized for SSE2. +void MatchedFilterCore_SSE2(size_t x_start_index, + float x2_sum_threshold, + rtc::ArrayView x, + rtc::ArrayView y, + rtc::ArrayView h, + bool* filters_updated, + float* error_sum); + +#endif + +// Filter core for the matched filter. +void MatchedFilterCore(size_t x_start_index, + float x2_sum_threshold, + rtc::ArrayView x, + rtc::ArrayView y, + rtc::ArrayView h, + bool* filters_updated, + float* error_sum); + +} // namespace aec3 + +class ApmDataDumper; + +// Produces recursively updated cross-correlation estimates for several signal +// shifts where the intra-shift spacing is uniform. +class MatchedFilter { + public: + // Stores properties for the lag estimate corresponding to a particular signal + // shift. + struct LagEstimate { + LagEstimate() = default; + LagEstimate(float accuracy, bool reliable, size_t lag, bool updated) + : accuracy(accuracy), reliable(reliable), lag(lag), updated(updated) {} + + float accuracy = 0.f; + bool reliable = false; + size_t lag = 0; + bool updated = false; + }; + + MatchedFilter(ApmDataDumper* data_dumper, + Aec3Optimization optimization, + size_t window_size_sub_blocks, + int num_matched_filters, + size_t alignment_shift_sub_blocks); + + ~MatchedFilter(); + + // Updates the correlation with the values in render and capture. + void Update(const std::array& render, + const std::array& capture); + + // Returns the current lag estimates. + rtc::ArrayView GetLagEstimates() const { + return lag_estimates_; + } + + // Returns the number of lag estimates produced using the shifted signals. + size_t NumLagEstimates() const { return filters_.size(); } + + private: + // Provides buffer with a related index. + struct IndexedBuffer { + explicit IndexedBuffer(size_t size); + ~IndexedBuffer(); + + std::vector data; + int index = 0; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(IndexedBuffer); + }; + + ApmDataDumper* const data_dumper_; + const Aec3Optimization optimization_; + const size_t filter_intra_lag_shift_; + std::vector> filters_; + std::vector lag_estimates_; + IndexedBuffer x_buffer_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MatchedFilter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator.h b/include/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator.h new file mode 100644 index 0000000..ce8a3d6 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/matched_filter_lag_aggregator.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_LAG_AGGREGATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_LAG_AGGREGATOR_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/matched_filter.h" + +namespace webrtc { + +class ApmDataDumper; + +// Aggregates lag estimates produced by the MatchedFilter class into a single +// reliable combined lag estimate. +class MatchedFilterLagAggregator { + public: + MatchedFilterLagAggregator(ApmDataDumper* data_dumper, + size_t num_lag_estimates); + ~MatchedFilterLagAggregator(); + + // Aggregates the provided lag estimates. + rtc::Optional Aggregate( + rtc::ArrayView lag_estimates); + + private: + ApmDataDumper* const data_dumper_; + std::vector lag_updates_in_a_row_; + size_t candidate_ = 0; + size_t candidate_counter_ = 0; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(MatchedFilterLagAggregator); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MATCHED_FILTER_LAG_AGGREGATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h b/include/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h new file mode 100644 index 0000000..60dab63 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_ + +#include + +#include "webrtc/modules/audio_processing/aec3/block_processor.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockBlockProcessor : public BlockProcessor { + public: + virtual ~MockBlockProcessor() {} + + MOCK_METHOD3(ProcessCapture, + void(bool level_change, + bool saturated_microphone_signal, + std::vector>* capture_block)); + MOCK_METHOD1(BufferRender, bool(std::vector>* block)); + MOCK_METHOD1(UpdateEchoLeakageStatus, void(bool leakage_detected)); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_BLOCK_PROCESSOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/mock/mock_echo_remover.h b/include/webrtc/modules/audio_processing/aec3/mock/mock_echo_remover.h new file mode 100644 index 0000000..6cde439 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/mock/mock_echo_remover.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_ECHO_REMOVER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_ECHO_REMOVER_H_ + +#include + +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" +#include "webrtc/modules/audio_processing/aec3/echo_remover.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockEchoRemover : public EchoRemover { + public: + virtual ~MockEchoRemover() = default; + + MOCK_METHOD5(ProcessBlock, + void(const rtc::Optional& echo_path_delay_samples, + const EchoPathVariability& echo_path_variability, + bool capture_signal_saturation, + const std::vector>& render, + std::vector>* capture)); + + MOCK_METHOD1(UpdateEchoLeakageStatus, void(bool leakage_detected)); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_ECHO_REMOVER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_buffer.h b/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_buffer.h new file mode 100644 index 0000000..93c8e0d --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_buffer.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_BUFFER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_BUFFER_H_ + +#include + +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockRenderDelayBuffer : public RenderDelayBuffer { + public: + explicit MockRenderDelayBuffer(int sample_rate_hz) + : block_(std::vector>( + NumBandsForRate(sample_rate_hz), + std::vector(kBlockSize, 0.f))) { + ON_CALL(*this, GetNext()) + .WillByDefault( + testing::Invoke(this, &MockRenderDelayBuffer::FakeGetNext)); + } + virtual ~MockRenderDelayBuffer() = default; + + MOCK_METHOD1(Insert, bool(std::vector>* block)); + MOCK_METHOD0(GetNext, const std::vector>&()); + MOCK_METHOD1(SetDelay, void(size_t delay)); + MOCK_CONST_METHOD0(Delay, size_t()); + MOCK_CONST_METHOD0(MaxDelay, size_t()); + MOCK_CONST_METHOD0(IsBlockAvailable, bool()); + MOCK_CONST_METHOD0(MaxApiJitter, size_t()); + + private: + const std::vector>& FakeGetNext() const { return block_; } + std::vector> block_; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_BUFFER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_controller.h b/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_controller.h new file mode 100644 index 0000000..5af2e84 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/mock/mock_render_delay_controller.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_CONTROLLER_H_ + +#include "webrtc/base/array_view.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/render_delay_controller.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { +namespace test { + +class MockRenderDelayController : public RenderDelayController { + public: + virtual ~MockRenderDelayController() = default; + + MOCK_METHOD1(GetDelay, size_t(rtc::ArrayView capture)); + MOCK_METHOD1(AnalyzeRender, bool(rtc::ArrayView capture)); + MOCK_CONST_METHOD0(AlignmentHeadroomSamples, rtc::Optional()); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_MOCK_MOCK_RENDER_DELAY_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/output_selector.h b/include/webrtc/modules/audio_processing/aec3/output_selector.h new file mode 100644 index 0000000..943e547 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/output_selector.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_OUTPUT_SELECTOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_OUTPUT_SELECTOR_H_ + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +// Performs the selection between which of the linear aec output and the +// microphone signal should be used as the echo suppressor output. +class OutputSelector { + public: + OutputSelector(); + ~OutputSelector(); + + // Forms the most appropriate output signal. + void FormLinearOutput(rtc::ArrayView subtractor_output, + rtc::ArrayView capture); + + // Returns true if the linear aec output is the one used. + bool UseSubtractorOutput() const { return use_subtractor_output_; } + + private: + bool use_subtractor_output_ = false; + int output_change_counter_ = 0; + RTC_DISALLOW_COPY_AND_ASSIGN(OutputSelector); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_OUTPUT_SELECTOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/power_echo_model.h b/include/webrtc/modules/audio_processing/aec3/power_echo_model.h new file mode 100644 index 0000000..8df82f0 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/power_echo_model.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_POWER_ECHO_MODEL_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_POWER_ECHO_MODEL_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec_state.h" +#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { + +// Provides an echo model based on power spectral estimates that estimates the +// echo spectrum. +class PowerEchoModel { + public: + PowerEchoModel(); + ~PowerEchoModel(); + + // Ajusts the model according to echo path changes. + void HandleEchoPathChange(const EchoPathVariability& variability); + + // Updates the echo model and estimates the echo spectrum. + void EstimateEcho( + const FftBuffer& render_buffer, + const std::array& capture_spectrum, + const AecState& aec_state, + std::array* echo_spectrum); + + // Returns the minimum required farend buffer length. + size_t MinFarendBufferLength() const { return kRenderBufferSize; } + + private: + // Provides a float value that is coupled with a counter. + struct CountedFloat { + CountedFloat() : value(0.f), counter(0) {} + CountedFloat(float value, int counter) : value(value), counter(counter) {} + float value; + int counter; + }; + + const size_t kRenderBufferSize = 100; + std::array H2_; + + RTC_DISALLOW_COPY_AND_ASSIGN(PowerEchoModel); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_POWER_ECHO_MODEL_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/render_delay_buffer.h b/include/webrtc/modules/audio_processing/aec3/render_delay_buffer.h new file mode 100644 index 0000000..0fe2c9e --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/render_delay_buffer.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_BUFFER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_BUFFER_H_ + +#include +#include + +namespace webrtc { + +// Class for buffering the incoming render blocks such that these may be +// extracted with a specified delay. +class RenderDelayBuffer { + public: + static RenderDelayBuffer* Create(size_t size_blocks, + size_t num_bands, + size_t max_api_jitter_blocks); + virtual ~RenderDelayBuffer() = default; + + // Swaps a block into the buffer (the content of block is destroyed) and + // returns true if the insert is successful. + virtual bool Insert(std::vector>* block) = 0; + + // Gets a reference to the next block (having the specified buffer delay) to + // read in the buffer. This method can only be called if a block is + // available which means that that must be checked prior to the call using + // the method IsBlockAvailable(). + virtual const std::vector>& GetNext() = 0; + + // Sets the buffer delay. The delay set must be lower than the delay reported + // by MaxDelay(). + virtual void SetDelay(size_t delay) = 0; + + // Gets the buffer delay. + virtual size_t Delay() const = 0; + + // Returns the maximum allowed buffer delay increase. + virtual size_t MaxDelay() const = 0; + + // Returns whether a block is available for reading. + virtual bool IsBlockAvailable() const = 0; + + // Returns the maximum allowed api call jitter in blocks. + virtual size_t MaxApiJitter() const = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_BUFFER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/render_delay_controller.h b/include/webrtc/modules/audio_processing/aec3/render_delay_controller.h new file mode 100644 index 0000000..b22a5fd --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/render_delay_controller.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_H_ + +#include "webrtc/base/array_view.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" +#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" + +namespace webrtc { + +// Class for aligning the render and capture signal using a RenderDelayBuffer. +class RenderDelayController { + public: + static RenderDelayController* Create( + int sample_rate_hz, + const RenderDelayBuffer& render_delay_buffer); + virtual ~RenderDelayController() = default; + + // Aligns the render buffer content with the capture signal. + virtual size_t GetDelay(rtc::ArrayView capture) = 0; + + // Analyzes the render signal and returns false if there is a buffer overrun. + virtual bool AnalyzeRender(rtc::ArrayView render) = 0; + + // Returns an approximate value for the headroom in the buffer alignment. + virtual rtc::Optional AlignmentHeadroomSamples() const = 0; +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h b/include/webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h new file mode 100644 index 0000000..9b9ea86 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/render_delay_controller_metrics.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" + +namespace webrtc { + +// Handles the reporting of metrics for the render delay controller. +class RenderDelayControllerMetrics { + public: + RenderDelayControllerMetrics() = default; + + // Updates the metric with new data. + void Update(rtc::Optional delay_samples, size_t buffer_delay_blocks); + + // Returns true if the metrics have just been reported, otherwise false. + bool MetricsReported() { return metrics_reported_; } + + private: + // Resets the metrics. + void ResetMetrics(); + + size_t delay_blocks_ = 0; + int reliable_delay_estimate_counter_ = 0; + int delay_change_counter_ = 0; + int call_counter_ = 0; + int initial_call_counter_ = 0; + bool metrics_reported_ = false; + bool initial_update = true; + + RTC_DISALLOW_COPY_AND_ASSIGN(RenderDelayControllerMetrics); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_DELAY_CONTROLLER_METRICS_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/render_signal_analyzer.h b/include/webrtc/modules/audio_processing/aec3/render_signal_analyzer.h new file mode 100644 index 0000000..1218fe6 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/render_signal_analyzer.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_SIGNAL_ANALYZER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_SIGNAL_ANALYZER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { + +// Provides functionality for analyzing the properties of the render signal. +class RenderSignalAnalyzer { + public: + RenderSignalAnalyzer(); + ~RenderSignalAnalyzer(); + + // Updates the render signal analysis with the most recent render signal. + void Update(const FftBuffer& X_buffer, + const rtc::Optional& delay_partitions); + + // Returns true if the render signal is poorly exciting. + bool PoorSignalExcitation() const { + RTC_DCHECK_LT(2, narrow_band_counters_.size()); + return std::any_of(narrow_band_counters_.begin(), + narrow_band_counters_.end(), + [](size_t a) { return a > 10; }); + } + + // Zeros the array around regions with narrow bands signal characteristics. + void MaskRegionsAroundNarrowBands( + std::array* v) const; + + private: + std::array narrow_band_counters_; + + RTC_DISALLOW_COPY_AND_ASSIGN(RenderSignalAnalyzer); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RENDER_SIGNAL_ANALYZER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h b/include/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h new file mode 100644 index 0000000..a4f85c4 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/residual_echo_estimator.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RESIDUAL_ECHO_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RESIDUAL_ECHO_ESTIMATOR_H_ + +#include +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec_state.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { + +class ResidualEchoEstimator { + public: + ResidualEchoEstimator(); + ~ResidualEchoEstimator(); + + void Estimate(bool using_subtractor_output, + const AecState& aec_state, + const FftBuffer& X_buffer, + const std::vector>& H2, + const std::array& E2_main, + const std::array& E2_shadow, + const std::array& S2_linear, + const std::array& S2_fallback, + const std::array& Y2, + std::array* R2); + + void HandleEchoPathChange(const EchoPathVariability& echo_path_variability); + + private: + std::array echo_path_gain_; + size_t blocks_since_last_saturation_ = 1000; + + RTC_DISALLOW_COPY_AND_ASSIGN(ResidualEchoEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_RESIDUAL_ECHO_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain.h b/include/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain.h new file mode 100644 index 0000000..0f414ff --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/shadow_filter_update_gain.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SHADOW_FILTER_UPDATE_GAIN_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SHADOW_FILTER_UPDATE_GAIN_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" +#include "webrtc/modules/audio_processing/aec3/render_signal_analyzer.h" + +namespace webrtc { + +// Provides functionality for computing the fixed gain for the shadow filter. +class ShadowFilterUpdateGain { + public: + // Computes the gain. + void Compute(const FftBuffer& X_buffer, + const RenderSignalAnalyzer& render_signal_analyzer, + const FftData& E_shadow, + size_t size_partitions, + bool saturated_capture_signal, + FftData* G); + + private: + size_t poor_signal_excitation_counter_ = 0; + size_t call_counter_ = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SHADOW_FILTER_UPDATE_GAIN_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/subtractor.h b/include/webrtc/modules/audio_processing/aec3/subtractor.h new file mode 100644 index 0000000..742e57c --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/subtractor.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_H_ + +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/adaptive_fir_filter.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec3_fft.h" +#include "webrtc/modules/audio_processing/aec3/echo_path_variability.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" +#include "webrtc/modules/audio_processing/aec3/main_filter_update_gain.h" +#include "webrtc/modules/audio_processing/aec3/shadow_filter_update_gain.h" +#include "webrtc/modules/audio_processing/aec3/subtractor_output.h" +#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" + +namespace webrtc { + +// Proves linear echo cancellation functionality +class Subtractor { + public: + Subtractor(ApmDataDumper* data_dumper, Aec3Optimization optimization); + ~Subtractor(); + + // Performs the echo subtraction. + void Process(const FftBuffer& render_buffer, + const rtc::ArrayView capture, + const RenderSignalAnalyzer& render_signal_analyzer, + bool saturation, + SubtractorOutput* output); + + // Returns a vector with the number of blocks included in the render buffer + // sums. + std::vector NumBlocksInRenderSums() const; + + // Returns the minimum required farend buffer length. + size_t MinFarendBufferLength() const { + return std::max(kMainFilterSizePartitions, kShadowFilterSizePartitions); + } + + void HandleEchoPathChange(const EchoPathVariability& echo_path_variability); + + // Returns the block-wise frequency response of the main adaptive filter. + const std::vector>& + FilterFrequencyResponse() const { + return main_filter_.FilterFrequencyResponse(); + } + + private: + const size_t kMainFilterSizePartitions = 12; + const size_t kShadowFilterSizePartitions = 12; + + const Aec3Fft fft_; + ApmDataDumper* data_dumper_; + const Aec3Optimization optimization_; + AdaptiveFirFilter main_filter_; + AdaptiveFirFilter shadow_filter_; + MainFilterUpdateGain G_main_; + ShadowFilterUpdateGain G_shadow_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Subtractor); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/subtractor_output.h b/include/webrtc/modules/audio_processing/aec3/subtractor_output.h new file mode 100644 index 0000000..90b9065 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/subtractor_output.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_OUTPUT_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_OUTPUT_H_ + +#include + +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_data.h" + +namespace webrtc { + +// Stores the values being returned from the echo subtractor. +struct SubtractorOutput { + std::array e_main; + std::array e_shadow; + FftData E_main; + FftData E_shadow; + std::array E2_main; + std::array E2_shadow; + + void Reset() { + e_main.fill(0.f); + e_shadow.fill(0.f); + E_main.re.fill(0.f); + E_main.im.fill(0.f); + E_shadow.re.fill(0.f); + E_shadow.im.fill(0.f); + E2_main.fill(0.f); + E2_shadow.fill(0.f); + } +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUBTRACTOR_OUTPUT_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/suppression_filter.h b/include/webrtc/modules/audio_processing/aec3/suppression_filter.h new file mode 100644 index 0000000..3171047 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/suppression_filter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_FILTER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/aec3_fft.h" + +namespace webrtc { + +class SuppressionFilter { + public: + explicit SuppressionFilter(int sample_rate_hz); + ~SuppressionFilter(); + void ApplyGain(const FftData& comfort_noise, + const FftData& comfort_noise_high_bands, + const std::array& suppression_gain, + std::vector>* e); + + private: + const int sample_rate_hz_; + const OouraFft ooura_fft_; + const Aec3Fft fft_; + std::array e_input_old_; + std::vector> e_output_old_; + RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionFilter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/aec3/suppression_gain.h b/include/webrtc/modules/audio_processing/aec3/suppression_gain.h new file mode 100644 index 0000000..bccbed8 --- /dev/null +++ b/include/webrtc/modules/audio_processing/aec3/suppression_gain.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_H_ + +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/aec3/aec3_common.h" +#include "webrtc/modules/audio_processing/aec3/fft_buffer.h" + +namespace webrtc { +namespace aec3 { +#if defined(WEBRTC_ARCH_X86_FAMILY) + +void ComputeGains_SSE2( + const std::array& nearend_power, + const std::array& residual_echo_power, + const std::array& comfort_noise_power, + float strong_nearend_margin, + std::array* previous_gain_squared, + std::array* previous_masker, + std::array* gain); + +#endif + +void ComputeGains( + const std::array& nearend_power, + const std::array& residual_echo_power, + const std::array& comfort_noise_power, + float strong_nearend_margin, + std::array* previous_gain_squared, + std::array* previous_masker, + std::array* gain); + +} // namespace aec3 + +class SuppressionGain { + public: + explicit SuppressionGain(Aec3Optimization optimization); + void GetGain(const std::array& nearend_power, + const std::array& residual_echo_power, + const std::array& comfort_noise_power, + float strong_nearend_margin, + std::array* gain); + + private: + const Aec3Optimization optimization_; + std::array previous_gain_squared_; + std::array previous_masker_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SuppressionGain); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC3_SUPPRESSION_GAIN_H_ diff --git a/include/webrtc/modules/audio_processing/agc/agc.h b/include/webrtc/modules/audio_processing/agc/agc.h index 9b6b855..e681e37 100644 --- a/include/webrtc/modules/audio_processing/agc/agc.h +++ b/include/webrtc/modules/audio_processing/agc/agc.h @@ -19,7 +19,7 @@ namespace webrtc { class AudioFrame; -class Histogram; +class LoudnessHistogram; class Agc { public: @@ -40,17 +40,14 @@ class Agc { virtual void Reset(); virtual int set_target_level_dbfs(int level); - virtual int target_level_dbfs() const { return target_level_dbfs_; } - - virtual float voice_probability() const { - return vad_.last_voice_probability(); - } + virtual int target_level_dbfs() const; + virtual float voice_probability() const; private: double target_level_loudness_; int target_level_dbfs_; - std::unique_ptr histogram_; - std::unique_ptr inactive_histogram_; + std::unique_ptr histogram_; + std::unique_ptr inactive_histogram_; VoiceActivityDetector vad_; }; diff --git a/include/webrtc/modules/audio_processing/agc/agc_manager_direct.h b/include/webrtc/modules/audio_processing/agc/agc_manager_direct.h index 6b16e8b..578a0f3 100644 --- a/include/webrtc/modules/audio_processing/agc/agc_manager_direct.h +++ b/include/webrtc/modules/audio_processing/agc/agc_manager_direct.h @@ -46,13 +46,15 @@ class AgcManagerDirect final { // outside that range will be clamped. AgcManagerDirect(GainControl* gctrl, VolumeCallbacks* volume_callbacks, - int startup_min_level); + int startup_min_level, + int clipped_level_min); // Dependency injection for testing. Don't delete |agc| as the memory is owned // by the manager. AgcManagerDirect(Agc* agc, GainControl* gctrl, VolumeCallbacks* volume_callbacks, - int startup_min_level); + int startup_min_level, + int clipped_level_min); ~AgcManagerDirect(); int Initialize(); @@ -98,6 +100,7 @@ class AgcManagerDirect final { bool check_volume_on_next_process_; bool startup_; int startup_min_level_; + const int clipped_level_min_; std::unique_ptr file_preproc_; std::unique_ptr file_postproc_; diff --git a/include/webrtc/modules/audio_processing/agc/legacy/analog_agc.h b/include/webrtc/modules/audio_processing/agc/legacy/analog_agc.h index 820221a..235fd14 100644 --- a/include/webrtc/modules/audio_processing/agc/legacy/analog_agc.h +++ b/include/webrtc/modules/audio_processing/agc/legacy/analog_agc.h @@ -32,102 +32,101 @@ * of our measure Rxx160_LP. Remember that the levels are in blocks of 16 in * Q(-7). (Example matlab code: round(db2pow(-21.2)*16/2^7) ) */ -#define RXX_BUFFER_LEN 10 +#define RXX_BUFFER_LEN 10 static const int16_t kMsecSpeechInner = 520; static const int16_t kMsecSpeechOuter = 340; static const int16_t kNormalVadThreshold = 400; -static const int16_t kAlphaShortTerm = 6; // 1 >> 6 = 0.0156 -static const int16_t kAlphaLongTerm = 10; // 1 >> 10 = 0.000977 - -typedef struct -{ - // Configurable parameters/variables - uint32_t fs; // Sampling frequency - int16_t compressionGaindB; // Fixed gain level in dB - int16_t targetLevelDbfs; // Target level in -dBfs of envelope (default -3) - int16_t agcMode; // Hard coded mode (adaptAna/adaptDig/fixedDig) - uint8_t limiterEnable; // Enabling limiter (on/off (default off)) - WebRtcAgcConfig defaultConfig; - WebRtcAgcConfig usedConfig; - - // General variables - int16_t initFlag; - int16_t lastError; - - // Target level parameters - // Based on the above: analogTargetLevel = round((32767*10^(-22/20))^2*16/2^7) - int32_t analogTargetLevel; // = RXX_BUFFER_LEN * 846805; -22 dBfs - int32_t startUpperLimit; // = RXX_BUFFER_LEN * 1066064; -21 dBfs - int32_t startLowerLimit; // = RXX_BUFFER_LEN * 672641; -23 dBfs - int32_t upperPrimaryLimit; // = RXX_BUFFER_LEN * 1342095; -20 dBfs - int32_t lowerPrimaryLimit; // = RXX_BUFFER_LEN * 534298; -24 dBfs - int32_t upperSecondaryLimit;// = RXX_BUFFER_LEN * 2677832; -17 dBfs - int32_t lowerSecondaryLimit;// = RXX_BUFFER_LEN * 267783; -27 dBfs - uint16_t targetIdx; // Table index for corresponding target level +static const int16_t kAlphaShortTerm = 6; // 1 >> 6 = 0.0156 +static const int16_t kAlphaLongTerm = 10; // 1 >> 10 = 0.000977 + +typedef struct { + // Configurable parameters/variables + uint32_t fs; // Sampling frequency + int16_t compressionGaindB; // Fixed gain level in dB + int16_t targetLevelDbfs; // Target level in -dBfs of envelope (default -3) + int16_t agcMode; // Hard coded mode (adaptAna/adaptDig/fixedDig) + uint8_t limiterEnable; // Enabling limiter (on/off (default off)) + WebRtcAgcConfig defaultConfig; + WebRtcAgcConfig usedConfig; + + // General variables + int16_t initFlag; + int16_t lastError; + + // Target level parameters + // Based on the above: analogTargetLevel = round((32767*10^(-22/20))^2*16/2^7) + int32_t analogTargetLevel; // = RXX_BUFFER_LEN * 846805; -22 dBfs + int32_t startUpperLimit; // = RXX_BUFFER_LEN * 1066064; -21 dBfs + int32_t startLowerLimit; // = RXX_BUFFER_LEN * 672641; -23 dBfs + int32_t upperPrimaryLimit; // = RXX_BUFFER_LEN * 1342095; -20 dBfs + int32_t lowerPrimaryLimit; // = RXX_BUFFER_LEN * 534298; -24 dBfs + int32_t upperSecondaryLimit; // = RXX_BUFFER_LEN * 2677832; -17 dBfs + int32_t lowerSecondaryLimit; // = RXX_BUFFER_LEN * 267783; -27 dBfs + uint16_t targetIdx; // Table index for corresponding target level #ifdef MIC_LEVEL_FEEDBACK - uint16_t targetIdxOffset; // Table index offset for level compensation + uint16_t targetIdxOffset; // Table index offset for level compensation #endif - int16_t analogTarget; // Digital reference level in ENV scale - - // Analog AGC specific variables - int32_t filterState[8]; // For downsampling wb to nb - int32_t upperLimit; // Upper limit for mic energy - int32_t lowerLimit; // Lower limit for mic energy - int32_t Rxx160w32; // Average energy for one frame - int32_t Rxx16_LPw32; // Low pass filtered subframe energies - int32_t Rxx160_LPw32; // Low pass filtered frame energies - int32_t Rxx16_LPw32Max; // Keeps track of largest energy subframe - int32_t Rxx16_vectorw32[RXX_BUFFER_LEN];// Array with subframe energies - int32_t Rxx16w32_array[2][5];// Energy values of microphone signal - int32_t env[2][10]; // Envelope values of subframes - - int16_t Rxx16pos; // Current position in the Rxx16_vectorw32 - int16_t envSum; // Filtered scaled envelope in subframes - int16_t vadThreshold; // Threshold for VAD decision - int16_t inActive; // Inactive time in milliseconds - int16_t msTooLow; // Milliseconds of speech at a too low level - int16_t msTooHigh; // Milliseconds of speech at a too high level - int16_t changeToSlowMode; // Change to slow mode after some time at target - int16_t firstCall; // First call to the process-function - int16_t msZero; // Milliseconds of zero input - int16_t msecSpeechOuterChange;// Min ms of speech between volume changes - int16_t msecSpeechInnerChange;// Min ms of speech between volume changes - int16_t activeSpeech; // Milliseconds of active speech - int16_t muteGuardMs; // Counter to prevent mute action - int16_t inQueue; // 10 ms batch indicator - - // Microphone level variables - int32_t micRef; // Remember ref. mic level for virtual mic - uint16_t gainTableIdx; // Current position in virtual gain table - int32_t micGainIdx; // Gain index of mic level to increase slowly - int32_t micVol; // Remember volume between frames - int32_t maxLevel; // Max possible vol level, incl dig gain - int32_t maxAnalog; // Maximum possible analog volume level - int32_t maxInit; // Initial value of "max" - int32_t minLevel; // Minimum possible volume level - int32_t minOutput; // Minimum output volume level - int32_t zeroCtrlMax; // Remember max gain => don't amp low input - int32_t lastInMicLevel; - - int16_t scale; // Scale factor for internal volume levels + int16_t analogTarget; // Digital reference level in ENV scale + + // Analog AGC specific variables + int32_t filterState[8]; // For downsampling wb to nb + int32_t upperLimit; // Upper limit for mic energy + int32_t lowerLimit; // Lower limit for mic energy + int32_t Rxx160w32; // Average energy for one frame + int32_t Rxx16_LPw32; // Low pass filtered subframe energies + int32_t Rxx160_LPw32; // Low pass filtered frame energies + int32_t Rxx16_LPw32Max; // Keeps track of largest energy subframe + int32_t Rxx16_vectorw32[RXX_BUFFER_LEN]; // Array with subframe energies + int32_t Rxx16w32_array[2][5]; // Energy values of microphone signal + int32_t env[2][10]; // Envelope values of subframes + + int16_t Rxx16pos; // Current position in the Rxx16_vectorw32 + int16_t envSum; // Filtered scaled envelope in subframes + int16_t vadThreshold; // Threshold for VAD decision + int16_t inActive; // Inactive time in milliseconds + int16_t msTooLow; // Milliseconds of speech at a too low level + int16_t msTooHigh; // Milliseconds of speech at a too high level + int16_t changeToSlowMode; // Change to slow mode after some time at target + int16_t firstCall; // First call to the process-function + int16_t msZero; // Milliseconds of zero input + int16_t msecSpeechOuterChange; // Min ms of speech between volume changes + int16_t msecSpeechInnerChange; // Min ms of speech between volume changes + int16_t activeSpeech; // Milliseconds of active speech + int16_t muteGuardMs; // Counter to prevent mute action + int16_t inQueue; // 10 ms batch indicator + + // Microphone level variables + int32_t micRef; // Remember ref. mic level for virtual mic + uint16_t gainTableIdx; // Current position in virtual gain table + int32_t micGainIdx; // Gain index of mic level to increase slowly + int32_t micVol; // Remember volume between frames + int32_t maxLevel; // Max possible vol level, incl dig gain + int32_t maxAnalog; // Maximum possible analog volume level + int32_t maxInit; // Initial value of "max" + int32_t minLevel; // Minimum possible volume level + int32_t minOutput; // Minimum output volume level + int32_t zeroCtrlMax; // Remember max gain => don't amp low input + int32_t lastInMicLevel; + + int16_t scale; // Scale factor for internal volume levels #ifdef MIC_LEVEL_FEEDBACK - int16_t numBlocksMicLvlSat; - uint8_t micLvlSat; + int16_t numBlocksMicLvlSat; + uint8_t micLvlSat; #endif - // Structs for VAD and digital_agc - AgcVad vadMic; - DigitalAgc digitalAgc; + // Structs for VAD and digital_agc + AgcVad vadMic; + DigitalAgc digitalAgc; #ifdef WEBRTC_AGC_DEBUG_DUMP - FILE* fpt; - FILE* agcLog; - int32_t fcount; + FILE* fpt; + FILE* agcLog; + int32_t fcount; #endif - int16_t lowLevelSignal; + int16_t lowLevelSignal; } LegacyAgc; -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LEGACY_ANALOG_AGC_H_ +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LEGACY_ANALOG_AGC_H_ diff --git a/include/webrtc/modules/audio_processing/agc/legacy/digital_agc.h b/include/webrtc/modules/audio_processing/agc/legacy/digital_agc.h index 819844d..4664b59 100644 --- a/include/webrtc/modules/audio_processing/agc/legacy/digital_agc.h +++ b/include/webrtc/modules/audio_processing/agc/legacy/digital_agc.h @@ -18,37 +18,36 @@ #include "webrtc/typedefs.h" // the 32 most significant bits of A(19) * B(26) >> 13 -#define AGC_MUL32(A, B) (((B)>>13)*(A) + ( ((0x00001FFF & (B))*(A)) >> 13 )) +#define AGC_MUL32(A, B) (((B) >> 13) * (A) + (((0x00001FFF & (B)) * (A)) >> 13)) // C + the 32 most significant bits of A * B -#define AGC_SCALEDIFF32(A, B, C) ((C) + ((B)>>16)*(A) + ( ((0x0000FFFF & (B))*(A)) >> 16 )) +#define AGC_SCALEDIFF32(A, B, C) \ + ((C) + ((B) >> 16) * (A) + (((0x0000FFFF & (B)) * (A)) >> 16)) -typedef struct -{ - int32_t downState[8]; - int16_t HPstate; - int16_t counter; - int16_t logRatio; // log( P(active) / P(inactive) ) (Q10) - int16_t meanLongTerm; // Q10 - int32_t varianceLongTerm; // Q8 - int16_t stdLongTerm; // Q10 - int16_t meanShortTerm; // Q10 - int32_t varianceShortTerm; // Q8 - int16_t stdShortTerm; // Q10 -} AgcVad; // total = 54 bytes +typedef struct { + int32_t downState[8]; + int16_t HPstate; + int16_t counter; + int16_t logRatio; // log( P(active) / P(inactive) ) (Q10) + int16_t meanLongTerm; // Q10 + int32_t varianceLongTerm; // Q8 + int16_t stdLongTerm; // Q10 + int16_t meanShortTerm; // Q10 + int32_t varianceShortTerm; // Q8 + int16_t stdShortTerm; // Q10 +} AgcVad; // total = 54 bytes -typedef struct -{ - int32_t capacitorSlow; - int32_t capacitorFast; - int32_t gain; - int32_t gainTable[32]; - int16_t gatePrevious; - int16_t agcMode; - AgcVad vadNearend; - AgcVad vadFarend; +typedef struct { + int32_t capacitorSlow; + int32_t capacitorFast; + int32_t gain; + int32_t gainTable[32]; + int16_t gatePrevious; + int16_t agcMode; + AgcVad vadNearend; + AgcVad vadFarend; #ifdef WEBRTC_AGC_DEBUG_DUMP - FILE* logFile; - int frameCounter; + FILE* logFile; + int frameCounter; #endif } DigitalAgc; @@ -67,14 +66,14 @@ int32_t WebRtcAgc_AddFarendToDigital(DigitalAgc* digitalAgcInst, void WebRtcAgc_InitVad(AgcVad* vadInst); -int16_t WebRtcAgc_ProcessVad(AgcVad* vadInst, // (i) VAD state - const int16_t* in, // (i) Speech signal +int16_t WebRtcAgc_ProcessVad(AgcVad* vadInst, // (i) VAD state + const int16_t* in, // (i) Speech signal size_t nrSamples); // (i) number of samples -int32_t WebRtcAgc_CalculateGainTable(int32_t *gainTable, // Q16 - int16_t compressionGaindB, // Q0 (in dB) - int16_t targetLevelDbfs,// Q0 (in dB) +int32_t WebRtcAgc_CalculateGainTable(int32_t* gainTable, // Q16 + int16_t compressionGaindB, // Q0 (in dB) + int16_t targetLevelDbfs, // Q0 (in dB) uint8_t limiterEnable, int16_t analogTarget); -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LEGACY_DIGITAL_AGC_H_ +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LEGACY_DIGITAL_AGC_H_ diff --git a/include/webrtc/modules/audio_processing/agc/legacy/gain_control.h b/include/webrtc/modules/audio_processing/agc/legacy/gain_control.h index db942fe..c315750 100644 --- a/include/webrtc/modules/audio_processing/agc/legacy/gain_control.h +++ b/include/webrtc/modules/audio_processing/agc/legacy/gain_control.h @@ -14,39 +14,32 @@ #include "webrtc/typedefs.h" // Errors -#define AGC_UNSPECIFIED_ERROR 18000 -#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001 -#define AGC_UNINITIALIZED_ERROR 18002 -#define AGC_NULL_POINTER_ERROR 18003 -#define AGC_BAD_PARAMETER_ERROR 18004 +#define AGC_UNSPECIFIED_ERROR 18000 +#define AGC_UNSUPPORTED_FUNCTION_ERROR 18001 +#define AGC_UNINITIALIZED_ERROR 18002 +#define AGC_NULL_POINTER_ERROR 18003 +#define AGC_BAD_PARAMETER_ERROR 18004 // Warnings -#define AGC_BAD_PARAMETER_WARNING 18050 +#define AGC_BAD_PARAMETER_WARNING 18050 -enum -{ - kAgcModeUnchanged, - kAgcModeAdaptiveAnalog, - kAgcModeAdaptiveDigital, - kAgcModeFixedDigital +enum { + kAgcModeUnchanged, + kAgcModeAdaptiveAnalog, + kAgcModeAdaptiveDigital, + kAgcModeFixedDigital }; -enum -{ - kAgcFalse = 0, - kAgcTrue -}; +enum { kAgcFalse = 0, kAgcTrue }; -typedef struct -{ - int16_t targetLevelDbfs; // default 3 (-3 dBOv) - int16_t compressionGaindB; // default 9 dB - uint8_t limiterEnable; // default kAgcTrue (on) +typedef struct { + int16_t targetLevelDbfs; // default 3 (-3 dBOv) + int16_t compressionGaindB; // default 9 dB + uint8_t limiterEnable; // default kAgcTrue (on) } WebRtcAgcConfig; #if defined(__cplusplus) -extern "C" -{ +extern "C" { #endif /* @@ -78,9 +71,7 @@ int WebRtcAgc_GetAddFarendError(void* state, size_t samples); * : 0 - Normal operation. * : -1 - Error */ -int WebRtcAgc_AddFarend(void* agcInst, - const int16_t* inFar, - size_t samples); +int WebRtcAgc_AddFarend(void* agcInst, const int16_t* inFar, size_t samples); /* * This function processes a 10 ms frame of microphone speech to determine @@ -243,7 +234,7 @@ void WebRtcAgc_Free(void* agcInst); * Return value : 0 - Ok * -1 - Error */ -int WebRtcAgc_Init(void *agcInst, +int WebRtcAgc_Init(void* agcInst, int32_t minLevel, int32_t maxLevel, int16_t agcMode, diff --git a/include/webrtc/modules/audio_processing/agc/histogram.h b/include/webrtc/modules/audio_processing/agc/loudness_histogram.h similarity index 75% rename from include/webrtc/modules/audio_processing/agc/histogram.h rename to include/webrtc/modules/audio_processing/agc/loudness_histogram.h index fd369a2..b079299 100644 --- a/include/webrtc/modules/audio_processing/agc/histogram.h +++ b/include/webrtc/modules/audio_processing/agc/loudness_histogram.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AGC_HISTOGRAM_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_HISTOGRAM_H_ +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LOUDNESS_HISTOGRAM_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LOUDNESS_HISTOGRAM_H_ #include @@ -21,15 +21,15 @@ namespace webrtc { // This class implements the histogram of loudness with circular buffers so that // the histogram tracks the last T seconds of the loudness. -class Histogram { +class LoudnessHistogram { public: - // Create a non-sliding Histogram. - static Histogram* Create(); + // Create a non-sliding LoudnessHistogram. + static LoudnessHistogram* Create(); - // Create a sliding Histogram, i.e. the histogram represents the last + // Create a sliding LoudnessHistogram, i.e. the histogram represents the last // |window_size| samples. - static Histogram* Create(int window_size); - ~Histogram(); + static LoudnessHistogram* Create(int window_size); + ~LoudnessHistogram(); // Insert RMS and the corresponding activity probability. void Update(double rms, double activity_probability); @@ -48,8 +48,8 @@ class Histogram { int num_updates() const { return num_updates_; } private: - Histogram(); - explicit Histogram(int window); + LoudnessHistogram(); + explicit LoudnessHistogram(int window); // Find the histogram bin associated with the given |rms|. int GetBinIndex(double rms); @@ -68,9 +68,9 @@ class Histogram { // |bin_count_q10_|. int64_t audio_content_q10_; - // Histogram of input RMS in Q10 with |kHistSize_| bins. In each 'Update(),' - // we increment the associated histogram-bin with the given probability. The - // increment is implemented in Q10 to avoid rounding errors. + // LoudnessHistogram of input RMS in Q10 with |kHistSize_| bins. In each + // 'Update(),' we increment the associated histogram-bin with the given + // probability. The increment is implemented in Q10 to avoid rounding errors. int64_t bin_count_q10_[kHistSize]; // Circular buffer for probabilities @@ -89,4 +89,4 @@ class Histogram { } // namespace webrtc -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_HISTOGRAM_H_ +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AGC_LOUDNESS_HISTOGRAM_H_ diff --git a/include/webrtc/modules/audio_processing/agc/mock_agc.h b/include/webrtc/modules/audio_processing/agc/mock_agc.h index 9e8f64e..3b9c22f 100644 --- a/include/webrtc/modules/audio_processing/agc/mock_agc.h +++ b/include/webrtc/modules/audio_processing/agc/mock_agc.h @@ -13,8 +13,8 @@ #include "webrtc/modules/audio_processing/agc/agc.h" -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/include/module_common_types.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/audio_processing/audio_buffer.h b/include/webrtc/modules/audio_processing/audio_buffer.h index d90219e..d0e79db 100644 --- a/include/webrtc/modules/audio_processing/audio_buffer.h +++ b/include/webrtc/modules/audio_processing/audio_buffer.h @@ -123,6 +123,8 @@ class AudioBuffer { void MergeFrequencyBands(); private: + FRIEND_TEST_ALL_PREFIXES(AudioBufferTest, + SetNumChannelsSetsChannelBuffersNumChannels); // Called from DeinterleaveFrom() and CopyFrom(). void InitForNewData(); diff --git a/include/webrtc/modules/audio_processing/audio_processing_impl.h b/include/webrtc/modules/audio_processing/audio_processing_impl.h index 04ddabd..01b640f 100644 --- a/include/webrtc/modules/audio_processing/audio_processing_impl.h +++ b/include/webrtc/modules/audio_processing/audio_processing_impl.h @@ -17,18 +17,26 @@ #include #include "webrtc/base/criticalsection.h" +#include "webrtc/base/function_view.h" +#include "webrtc/base/gtest_prod_util.h" +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/swap_queue.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/audio_processing/audio_buffer.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/audio_processing/render_queue_item_verifier.h" +#include "webrtc/modules/audio_processing/rms_level.h" #include "webrtc/system_wrappers/include/file_wrapper.h" #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP // Files generated at build-time by the protobuf compiler. +RTC_PUSH_IGNORING_WUNDEF() #ifdef WEBRTC_ANDROID_PLATFORM_BUILD #include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" #else #include "webrtc/modules/audio_processing/debug.pb.h" #endif +RTC_POP_IGNORING_WUNDEF() #endif // WEBRTC_AUDIOPROC_DEBUG_DUMP namespace webrtc { @@ -36,31 +44,32 @@ namespace webrtc { class AgcManagerDirect; class AudioConverter; -template -class Beamformer; +class NonlinearBeamformer; class AudioProcessingImpl : public AudioProcessing { public: // Methods forcing APM to run in a single-threaded manner. // Acquires both the render and capture locks. - explicit AudioProcessingImpl(const Config& config); + explicit AudioProcessingImpl(const webrtc::Config& config); // AudioProcessingImpl takes ownership of beamformer. - AudioProcessingImpl(const Config& config, Beamformer* beamformer); - virtual ~AudioProcessingImpl(); + AudioProcessingImpl(const webrtc::Config& config, + NonlinearBeamformer* beamformer); + ~AudioProcessingImpl() override; int Initialize() override; - int Initialize(int input_sample_rate_hz, - int output_sample_rate_hz, - int reverse_sample_rate_hz, - ChannelLayout input_layout, - ChannelLayout output_layout, - ChannelLayout reverse_layout) override; + int Initialize(int capture_input_sample_rate_hz, + int capture_output_sample_rate_hz, + int render_sample_rate_hz, + ChannelLayout capture_input_layout, + ChannelLayout capture_output_layout, + ChannelLayout render_input_layout) override; int Initialize(const ProcessingConfig& processing_config) override; - void SetExtraOptions(const Config& config) override; + void ApplyConfig(const AudioProcessing::Config& config) override; + void SetExtraOptions(const webrtc::Config& config) override; void UpdateHistogramsOnCallEnd() override; int StartDebugRecording(const char filename[kMaxFilenameSize], int64_t max_log_size_bytes) override; int StartDebugRecording(FILE* handle, int64_t max_log_size_bytes) override; - + int StartDebugRecording(FILE* handle) override; int StartDebugRecordingForPlatformFile(rtc::PlatformFile handle) override; int StopDebugRecording() override; @@ -92,8 +101,8 @@ class AudioProcessingImpl : public AudioProcessing { int sample_rate_hz, ChannelLayout layout) override; int ProcessReverseStream(const float* const* src, - const StreamConfig& reverse_input_config, - const StreamConfig& reverse_output_config, + const StreamConfig& input_config, + const StreamConfig& output_config, float* const* dest) override; // Methods only accessed from APM submodules or @@ -109,6 +118,8 @@ class AudioProcessingImpl : public AudioProcessing { bool was_stream_delay_set() const override EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); + AudioProcessingStatistics GetStatistics() const override; + // Methods returning pointers to APM submodules. // No locks are aquired in those, as those locks // would offer no protection (the submodules are @@ -117,24 +128,77 @@ class AudioProcessingImpl : public AudioProcessing { EchoCancellation* echo_cancellation() const override; EchoControlMobile* echo_control_mobile() const override; GainControl* gain_control() const override; + // TODO(peah): Deprecate this API call. HighPassFilter* high_pass_filter() const override; LevelEstimator* level_estimator() const override; NoiseSuppression* noise_suppression() const override; VoiceDetection* voice_detection() const override; + // TODO(peah): Remove these two methods once the new API allows that. + void MutateConfig(rtc::FunctionView mutator); + AudioProcessing::Config GetConfig() const; + protected: // Overridden in a mock. virtual int InitializeLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); private: + // TODO(peah): These friend classes should be removed as soon as the new + // parameter setting scheme allows. + FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, DefaultBehavior); + FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, ValidConfigBehavior); + FRIEND_TEST_ALL_PREFIXES(ApmConfiguration, InValidConfigBehavior); struct ApmPublicSubmodules; struct ApmPrivateSubmodules; + // Submodule interface implementations. + std::unique_ptr high_pass_filter_impl_; + + class ApmSubmoduleStates { + public: + ApmSubmoduleStates(); + // Updates the submodule state and returns true if it has changed. + bool Update(bool low_cut_filter_enabled, + bool echo_canceller_enabled, + bool mobile_echo_controller_enabled, + bool residual_echo_detector_enabled, + bool noise_suppressor_enabled, + bool intelligibility_enhancer_enabled, + bool beamformer_enabled, + bool adaptive_gain_controller_enabled, + bool level_controller_enabled, + bool echo_canceller3_enabled, + bool voice_activity_detector_enabled, + bool level_estimator_enabled, + bool transient_suppressor_enabled); + bool CaptureMultiBandSubModulesActive() const; + bool CaptureMultiBandProcessingActive() const; + bool RenderMultiBandSubModulesActive() const; + bool RenderMultiBandProcessingActive() const; + + private: + bool low_cut_filter_enabled_ = false; + bool echo_canceller_enabled_ = false; + bool mobile_echo_controller_enabled_ = false; + bool residual_echo_detector_enabled_ = false; + bool noise_suppressor_enabled_ = false; + bool intelligibility_enhancer_enabled_ = false; + bool beamformer_enabled_ = false; + bool adaptive_gain_controller_enabled_ = false; + bool level_controller_enabled_ = false; + bool echo_canceller3_enabled_ = false; + bool level_estimator_enabled_ = false; + bool voice_activity_detector_enabled_ = false; + bool transient_suppressor_enabled_ = false; + bool first_update_ = true; + }; + #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP // State for the debug dump. struct ApmDebugDumpThreadState { - ApmDebugDumpThreadState() : event_msg(new audioproc::Event()) {} + ApmDebugDumpThreadState(); + ~ApmDebugDumpThreadState(); std::unique_ptr event_msg; // Protobuf message. std::string event_str; // Memory for protobuf serialization. @@ -143,7 +207,8 @@ class AudioProcessingImpl : public AudioProcessing { }; struct ApmDebugDumpState { - ApmDebugDumpState() : debug_file(FileWrapper::Create()) {} + ApmDebugDumpState(); + ~ApmDebugDumpState(); // Number of bytes that can still be written to the log before the maximum // size is reached. A value of <= 0 indicates that no limit is used. int64_t num_bytes_left_for_log_ = -1; @@ -159,57 +224,46 @@ class AudioProcessingImpl : public AudioProcessing { // that the capture thread blocks the render thread. // The struct is modified in a single-threaded manner by holding both the // render and capture locks. - int MaybeInitialize(const ProcessingConfig& config) + int MaybeInitialize(const ProcessingConfig& config, bool force_initialization) EXCLUSIVE_LOCKS_REQUIRED(crit_render_); int MaybeInitializeRender(const ProcessingConfig& processing_config) EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - int MaybeInitializeCapture(const ProcessingConfig& processing_config) + int MaybeInitializeCapture(const ProcessingConfig& processing_config, + bool force_initialization) EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - // Method for checking for the need of conversion. Accesses the formats - // structs in a read manner but the requirement for the render lock to be held - // was added as it currently anyway is always called in that manner. - bool rev_conversion_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - bool render_check_rev_conversion_needed() const - EXCLUSIVE_LOCKS_REQUIRED(crit_render_); + // Method for updating the state keeping track of the active submodules. + // Returns a bool indicating whether the state has changed. + bool UpdateActiveSubmoduleStates() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); // Methods requiring APM running in a single-threaded manner. // Are called with both the render and capture locks already // acquired. - void InitializeExperimentalAgc() - EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); void InitializeTransient() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); void InitializeBeamformer() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); void InitializeIntelligibility() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); - void InitializeHighPassFilter() - EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - void InitializeNoiseSuppression() - EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - void InitializeLevelEstimator() - EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - void InitializeVoiceDetection() - EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - void InitializeEchoCanceller() - EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); - void InitializeGainController() + int InitializeLocked(const ProcessingConfig& config) EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); - void InitializeEchoControlMobile() + void InitializeLevelController() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); + void InitializeResidualEchoDetector() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); - int InitializeLocked(const ProcessingConfig& config) + void InitializeLowCutFilter() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); + void InitializeEchoCanceller3() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); + + void EmptyQueuedRenderAudio(); + void AllocateRenderQueue() EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_); + void QueueRenderAudio(AudioBuffer* audio) + EXCLUSIVE_LOCKS_REQUIRED(crit_render_); // Capture-side exclusive methods possibly running APM in a multi-threaded // manner that are called with the render lock already acquired. - int ProcessStreamLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - bool output_copy_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - bool is_fwd_processed() const EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - bool fwd_synthesis_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); - bool fwd_analysis_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); + int ProcessCaptureStreamLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); void MaybeUpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_capture_); // Render-side exclusive methods possibly running APM in a multi-threaded @@ -219,10 +273,7 @@ class AudioProcessingImpl : public AudioProcessing { const StreamConfig& input_config, const StreamConfig& output_config) EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - bool is_rev_processed() const EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - bool rev_synthesis_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - bool rev_analysis_needed() const EXCLUSIVE_LOCKS_REQUIRED(crit_render_); - int ProcessReverseStreamLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_render_); + int ProcessRenderStreamLocked() EXCLUSIVE_LOCKS_REQUIRED(crit_render_); // Debug dump methods that are internal and called without locks. // TODO(peah): Make thread safe. @@ -252,10 +303,15 @@ class AudioProcessingImpl : public AudioProcessing { rtc::CriticalSection crit_render_ ACQUIRED_BEFORE(crit_capture_); rtc::CriticalSection crit_capture_; + // Struct containing the Config specifying the behavior of APM. + AudioProcessing::Config config_; + + // Class containing information about what submodules are active. + ApmSubmoduleStates submodule_states_; + // Structs containing the pointers to the submodules. std::unique_ptr public_submodules_; - std::unique_ptr private_submodules_ - GUARDED_BY(crit_capture_); + std::unique_ptr private_submodules_; // State that is written to while holding both the render and capture locks // but can be read without any lock being held. @@ -269,38 +325,30 @@ class AudioProcessingImpl : public AudioProcessing { {kSampleRate16kHz, 1, false}, {kSampleRate16kHz, 1, false}, {kSampleRate16kHz, 1, false}}}), - rev_proc_format(kSampleRate16kHz, 1) {} + render_processing_format(kSampleRate16kHz, 1) {} ProcessingConfig api_format; - StreamConfig rev_proc_format; + StreamConfig render_processing_format; } formats_; // APM constants. const struct ApmConstants { - ApmConstants(int agc_startup_min_volume, bool use_experimental_agc) + ApmConstants(int agc_startup_min_volume, + int agc_clipped_level_min, + bool use_experimental_agc) : // Format of processing streams at input/output call sites. agc_startup_min_volume(agc_startup_min_volume), + agc_clipped_level_min(agc_clipped_level_min), use_experimental_agc(use_experimental_agc) {} int agc_startup_min_volume; + int agc_clipped_level_min; bool use_experimental_agc; } constants_; struct ApmCaptureState { ApmCaptureState(bool transient_suppressor_enabled, const std::vector& array_geometry, - SphericalPointf target_direction) - : aec_system_delay_jumps(-1), - delay_offset_ms(0), - was_stream_delay_set(false), - last_stream_delay_ms(0), - last_aec_system_delay_ms(0), - stream_delay_jumps(-1), - output_will_be_muted(false), - key_pressed(false), - transient_suppressor_enabled(transient_suppressor_enabled), - array_geometry(array_geometry), - target_direction(target_direction), - fwd_proc_format(kSampleRate16kHz), - split_rate(kSampleRate16kHz) {} + SphericalPointf target_direction); + ~ApmCaptureState(); int aec_system_delay_jumps; int delay_offset_ms; bool was_stream_delay_set; @@ -313,35 +361,75 @@ class AudioProcessingImpl : public AudioProcessing { std::vector array_geometry; SphericalPointf target_direction; std::unique_ptr capture_audio; - // Only the rate and samples fields of fwd_proc_format_ are used because the - // forward processing number of channels is mutable and is tracked by the - // capture_audio_. - StreamConfig fwd_proc_format; + // Only the rate and samples fields of capture_processing_format_ are used + // because the capture processing number of channels is mutable and is + // tracked by the capture_audio_. + StreamConfig capture_processing_format; int split_rate; } capture_ GUARDED_BY(crit_capture_); struct ApmCaptureNonLockedState { ApmCaptureNonLockedState(bool beamformer_enabled, bool intelligibility_enabled) - : fwd_proc_format(kSampleRate16kHz), + : capture_processing_format(kSampleRate16kHz), split_rate(kSampleRate16kHz), stream_delay_ms(0), beamformer_enabled(beamformer_enabled), intelligibility_enabled(intelligibility_enabled) {} - // Only the rate and samples fields of fwd_proc_format_ are used because the - // forward processing number of channels is mutable and is tracked by the - // capture_audio_. - StreamConfig fwd_proc_format; + // Only the rate and samples fields of capture_processing_format_ are used + // because the forward processing number of channels is mutable and is + // tracked by the capture_audio_. + StreamConfig capture_processing_format; int split_rate; int stream_delay_ms; bool beamformer_enabled; bool intelligibility_enabled; + bool level_controller_enabled = false; + bool echo_canceller3_enabled = false; } capture_nonlocked_; struct ApmRenderState { + ApmRenderState(); + ~ApmRenderState(); std::unique_ptr render_converter; std::unique_ptr render_audio; } render_ GUARDED_BY(crit_render_); + + size_t aec_render_queue_element_max_size_ GUARDED_BY(crit_render_) + GUARDED_BY(crit_capture_) = 0; + std::vector aec_render_queue_buffer_ GUARDED_BY(crit_render_); + std::vector aec_capture_queue_buffer_ GUARDED_BY(crit_capture_); + + size_t aecm_render_queue_element_max_size_ GUARDED_BY(crit_render_) + GUARDED_BY(crit_capture_) = 0; + std::vector aecm_render_queue_buffer_ GUARDED_BY(crit_render_); + std::vector aecm_capture_queue_buffer_ GUARDED_BY(crit_capture_); + + size_t agc_render_queue_element_max_size_ GUARDED_BY(crit_render_) + GUARDED_BY(crit_capture_) = 0; + std::vector agc_render_queue_buffer_ GUARDED_BY(crit_render_); + std::vector agc_capture_queue_buffer_ GUARDED_BY(crit_capture_); + + size_t red_render_queue_element_max_size_ GUARDED_BY(crit_render_) + GUARDED_BY(crit_capture_) = 0; + std::vector red_render_queue_buffer_ GUARDED_BY(crit_render_); + std::vector red_capture_queue_buffer_ GUARDED_BY(crit_capture_); + + RmsLevel capture_input_rms_ GUARDED_BY(crit_capture_); + RmsLevel capture_output_rms_ GUARDED_BY(crit_capture_); + int capture_rms_interval_counter_ GUARDED_BY(crit_capture_) = 0; + + // Lock protection not needed. + std::unique_ptr, RenderQueueItemVerifier>> + aec_render_signal_queue_; + std::unique_ptr< + SwapQueue, RenderQueueItemVerifier>> + aecm_render_signal_queue_; + std::unique_ptr< + SwapQueue, RenderQueueItemVerifier>> + agc_render_signal_queue_; + std::unique_ptr, RenderQueueItemVerifier>> + red_render_signal_queue_; }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/beamformer/beamformer.h b/include/webrtc/modules/audio_processing/beamformer/beamformer.h deleted file mode 100644 index 6a9ff45..0000000 --- a/include/webrtc/modules/audio_processing/beamformer/beamformer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_BEAMFORMER_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_BEAMFORMER_H_ - -#include "webrtc/common_audio/channel_buffer.h" -#include "webrtc/modules/audio_processing/beamformer/array_util.h" - -namespace webrtc { - -template -class Beamformer { - public: - virtual ~Beamformer() {} - - // Process one time-domain chunk of audio. The audio is expected to be split - // into frequency bands inside the ChannelBuffer. The number of frames and - // channels must correspond to the constructor parameters. The same - // ChannelBuffer can be passed in as |input| and |output|. - virtual void ProcessChunk(const ChannelBuffer& input, - ChannelBuffer* output) = 0; - - // Sample rate corresponds to the lower band. - // Needs to be called before the the Beamformer can be used. - virtual void Initialize(int chunk_size_ms, int sample_rate_hz) = 0; - - // Aim the beamformer at a point in space. - virtual void AimAt(const SphericalPointf& spherical_point) = 0; - - // Indicates whether a given point is inside of the beam. - virtual bool IsInBeam(const SphericalPointf& spherical_point) { return true; } - - // Returns true if the current data contains the target signal. - // Which signals are considered "targets" is implementation dependent. - virtual bool is_target_present() = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_BEAMFORMER_H_ diff --git a/include/webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h b/include/webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h index 9891a82..57bd82e 100644 --- a/include/webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h +++ b/include/webrtc/modules/audio_processing/beamformer/matrix_test_helpers.h @@ -11,9 +11,9 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_MATRIX_TEST_HELPERS_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_MATRIX_TEST_HELPERS_H_ -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_processing/beamformer/complex_matrix.h" #include "webrtc/modules/audio_processing/beamformer/matrix.h" +#include "webrtc/test/gtest.h" namespace { const float kTolerance = 0.001f; diff --git a/include/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h b/include/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h index e2b4417..7493dcb 100644 --- a/include/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h +++ b/include/webrtc/modules/audio_processing/beamformer/mock_nonlinear_beamformer.h @@ -13,19 +13,23 @@ #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h" +#include "webrtc/test/gmock.h" namespace webrtc { class MockNonlinearBeamformer : public NonlinearBeamformer { public: - explicit MockNonlinearBeamformer(const std::vector& array_geometry) - : NonlinearBeamformer(array_geometry) {} + MockNonlinearBeamformer(const std::vector& array_geometry, + size_t num_postfilter_channels) + : NonlinearBeamformer(array_geometry, num_postfilter_channels) {} + + MockNonlinearBeamformer(const std::vector& array_geometry) + : NonlinearBeamformer(array_geometry, 1u) {} MOCK_METHOD2(Initialize, void(int chunk_size_ms, int sample_rate_hz)); - MOCK_METHOD2(ProcessChunk, void(const ChannelBuffer& input, - ChannelBuffer* output)); + MOCK_METHOD1(AnalyzeChunk, void(const ChannelBuffer& data)); + MOCK_METHOD1(PostFilter, void(ChannelBuffer* data)); MOCK_METHOD1(IsInBeam, bool(const SphericalPointf& spherical_point)); MOCK_METHOD0(is_target_present, bool()); }; diff --git a/include/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h b/include/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h index b8953b0..9b45c8b 100644 --- a/include/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h +++ b/include/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h @@ -21,48 +21,73 @@ #include "webrtc/common_audio/lapped_transform.h" #include "webrtc/common_audio/channel_buffer.h" -#include "webrtc/modules/audio_processing/beamformer/beamformer.h" +#include "webrtc/modules/audio_processing/beamformer/array_util.h" #include "webrtc/modules/audio_processing/beamformer/complex_matrix.h" namespace webrtc { +class PostFilterTransform : public LappedTransform::Callback { + public: + PostFilterTransform(size_t num_channels, + size_t chunk_length, + float* window, + size_t fft_size); + + void ProcessChunk(float* const* data, float* final_mask); + + protected: + void ProcessAudioBlock(const complex* const* input, + size_t num_input_channels, + size_t num_freq_bins, + size_t num_output_channels, + complex* const* output) override; + + private: + LappedTransform transform_; + const size_t num_freq_bins_; + float* final_mask_; +}; + // Enhances sound sources coming directly in front of a uniform linear array // and suppresses sound sources coming from all other directions. Operates on // multichannel signals and produces single-channel output. // // The implemented nonlinear postfilter algorithm taken from "A Robust Nonlinear // Beamforming Postprocessor" by Bastiaan Kleijn. -class NonlinearBeamformer - : public Beamformer, - public LappedTransform::Callback { +class NonlinearBeamformer : public LappedTransform::Callback { public: static const float kHalfBeamWidthRadians; explicit NonlinearBeamformer( const std::vector& array_geometry, + size_t num_postfilter_channels = 1u, SphericalPointf target_direction = SphericalPointf(static_cast(M_PI) / 2.f, 0.f, 1.f)); + ~NonlinearBeamformer() override; // Sample rate corresponds to the lower band. // Needs to be called before the NonlinearBeamformer can be used. - void Initialize(int chunk_size_ms, int sample_rate_hz) override; + virtual void Initialize(int chunk_size_ms, int sample_rate_hz); - // Process one time-domain chunk of audio. The audio is expected to be split + // Analyzes one time-domain chunk of audio. The audio is expected to be split // into frequency bands inside the ChannelBuffer. The number of frames and - // channels must correspond to the constructor parameters. The same - // ChannelBuffer can be passed in as |input| and |output|. - void ProcessChunk(const ChannelBuffer& input, - ChannelBuffer* output) override; + // channels must correspond to the constructor parameters. + virtual void AnalyzeChunk(const ChannelBuffer& data); + + // Applies the postfilter mask to one chunk of audio. The audio is expected to + // be split into frequency bands inside the ChannelBuffer. The number of + // frames and channels must correspond to the constructor parameters. + virtual void PostFilter(ChannelBuffer* data); - void AimAt(const SphericalPointf& target_direction) override; + virtual void AimAt(const SphericalPointf& target_direction); - bool IsInBeam(const SphericalPointf& spherical_point) override; + virtual bool IsInBeam(const SphericalPointf& spherical_point); // After processing each block |is_target_present_| is set to true if the // target signal es present and to false otherwise. This methods can be called // to know if the data is target signal or interference and process it // accordingly. - bool is_target_present() override { return is_target_present_; } + virtual bool is_target_present(); protected: // Process one frequency-domain block of audio. This is where the fun @@ -116,8 +141,8 @@ class NonlinearBeamformer // Compute the means needed for the above frequency correction. float MaskRangeMean(size_t start_bin, size_t end_bin); - // Applies both sets of masks to |input| and store in |output|. - void ApplyMasks(const complex_f* const* input, complex_f* const* output); + // Applies post-filter mask to |input| and store in |output|. + void ApplyPostFilter(const complex_f* input, complex_f* output); void EstimateTargetPresence(); @@ -126,11 +151,13 @@ class NonlinearBeamformer // Deals with the fft transform and blocking. size_t chunk_length_; - std::unique_ptr lapped_transform_; + std::unique_ptr process_transform_; + std::unique_ptr postfilter_transform_; float window_[kFftSize]; // Parameters exposed to the user. const size_t num_input_channels_; + const size_t num_postfilter_channels_; int sample_rate_hz_; const std::vector array_geometry_; @@ -161,7 +188,6 @@ class NonlinearBeamformer // Array of length |kNumFreqBins|, Matrix of size |1| x |num_channels_|. ComplexMatrixF delay_sum_masks_[kNumFreqBins]; - ComplexMatrixF normalized_delay_sum_masks_[kNumFreqBins]; // Arrays of length |kNumFreqBins|, Matrix of size |num_input_channels_| x // |num_input_channels_|. @@ -186,6 +212,7 @@ class NonlinearBeamformer // For processing the high-frequency input signal. float high_pass_postfilter_mask_; + float old_high_pass_mask_; // True when the target signal is present. bool is_target_present_; diff --git a/include/webrtc/modules/audio_processing/common.h b/include/webrtc/modules/audio_processing/common.h index d4ddb92..184e2a5 100644 --- a/include/webrtc/modules/audio_processing/common.h +++ b/include/webrtc/modules/audio_processing/common.h @@ -11,8 +11,7 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_COMMON_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_COMMON_H_ -#include - +#include "webrtc/base/checks.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" namespace webrtc { @@ -26,7 +25,7 @@ static inline size_t ChannelsFromLayout(AudioProcessing::ChannelLayout layout) { case AudioProcessing::kStereoAndKeyboard: return 2; } - assert(false); + RTC_NOTREACHED(); return 0; } diff --git a/include/webrtc/modules/audio_processing/echo_cancellation_impl.h b/include/webrtc/modules/audio_processing/echo_cancellation_impl.h index f67ef7b..19da981 100644 --- a/include/webrtc/modules/audio_processing/echo_cancellation_impl.h +++ b/include/webrtc/modules/audio_processing/echo_cancellation_impl.h @@ -16,9 +16,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" -#include "webrtc/base/swap_queue.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" -#include "webrtc/modules/audio_processing/render_queue_item_verifier.h" namespace webrtc { @@ -28,9 +26,9 @@ class EchoCancellationImpl : public EchoCancellation { public: EchoCancellationImpl(rtc::CriticalSection* crit_render, rtc::CriticalSection* crit_capture); - virtual ~EchoCancellationImpl(); + ~EchoCancellationImpl() override; - int ProcessRenderAudio(const AudioBuffer* audio); + void ProcessRenderAudio(rtc::ArrayView packed_render_audio); int ProcessCaptureAudio(AudioBuffer* audio, int stream_delay_ms); // EchoCancellation implementation. @@ -43,25 +41,36 @@ class EchoCancellationImpl : public EchoCancellation { size_t num_reverse_channels_, size_t num_output_channels_, size_t num_proc_channels_); - void SetExtraOptions(const Config& config); + void SetExtraOptions(const webrtc::Config& config); bool is_delay_agnostic_enabled() const; bool is_extended_filter_enabled() const; - bool is_aec3_enabled() const; std::string GetExperimentsDescription(); bool is_refined_adaptive_filter_enabled() const; - // Checks whether the module is enabled. Must only be - // called from the render side of APM as otherwise - // deadlocks may occur. - bool is_enabled_render_side_query() const; - - // Reads render side data that has been queued on the render call. - // Called holding the capture lock. - void ReadQueuedRenderData(); - // Returns the system delay of the first AEC component. int GetSystemDelayInSamples() const; + static void PackRenderAudioBuffer(const AudioBuffer* audio, + size_t num_output_channels, + size_t num_channels, + std::vector* packed_buffer); + static size_t NumCancellersRequired(size_t num_output_channels, + size_t num_reverse_channels); + + // Enable logging of various AEC statistics. + int enable_metrics(bool enable) override; + + // Provides various statistics about the AEC. + int GetMetrics(Metrics* metrics) override; + + // Enable logging of delay metrics. + int enable_delay_logging(bool enable) override; + + // Provides delay metrics. + int GetDelayMetrics(int* median, + int* std, + float* fraction_poor_delays) override; + private: class Canceller; struct StreamProperties; @@ -71,21 +80,13 @@ class EchoCancellationImpl : public EchoCancellation { int enable_drift_compensation(bool enable) override; void set_stream_drift_samples(int drift) override; int set_suppression_level(SuppressionLevel level) override; - int enable_metrics(bool enable) override; bool are_metrics_enabled() const override; bool stream_has_echo() const override; - int GetMetrics(Metrics* metrics) override; - int enable_delay_logging(bool enable) override; bool is_delay_logging_enabled() const override; int GetDelayMetrics(int* median, int* std) override; - int GetDelayMetrics(int* median, - int* std, - float* fraction_poor_delays) override; struct AecCore* aec_core() const override; - size_t NumCancellersRequired() const; - void AllocateRenderQueue(); int Configure(); @@ -102,18 +103,8 @@ class EchoCancellationImpl : public EchoCancellation { bool delay_logging_enabled_ GUARDED_BY(crit_capture_); bool extended_filter_enabled_ GUARDED_BY(crit_capture_); bool delay_agnostic_enabled_ GUARDED_BY(crit_capture_); - bool aec3_enabled_ GUARDED_BY(crit_capture_); bool refined_adaptive_filter_enabled_ GUARDED_BY(crit_capture_) = false; - size_t render_queue_element_max_size_ GUARDED_BY(crit_render_) - GUARDED_BY(crit_capture_); - std::vector render_queue_buffer_ GUARDED_BY(crit_render_); - std::vector capture_queue_buffer_ GUARDED_BY(crit_capture_); - - // Lock protection not needed. - std::unique_ptr, RenderQueueItemVerifier>> - render_signal_queue_; - std::vector> cancellers_; std::unique_ptr stream_properties_; diff --git a/include/webrtc/modules/audio_processing/echo_control_mobile_impl.h b/include/webrtc/modules/audio_processing/echo_control_mobile_impl.h index 97e2407..571de36 100644 --- a/include/webrtc/modules/audio_processing/echo_control_mobile_impl.h +++ b/include/webrtc/modules/audio_processing/echo_control_mobile_impl.h @@ -29,9 +29,9 @@ class EchoControlMobileImpl : public EchoControlMobile { EchoControlMobileImpl(rtc::CriticalSection* crit_render, rtc::CriticalSection* crit_capture); - virtual ~EchoControlMobileImpl(); + ~EchoControlMobileImpl() override; - int ProcessRenderAudio(const AudioBuffer* audio); + void ProcessRenderAudio(rtc::ArrayView packed_render_audio); int ProcessCaptureAudio(AudioBuffer* audio, int stream_delay_ms); // EchoControlMobile implementation. @@ -43,13 +43,13 @@ class EchoControlMobileImpl : public EchoControlMobile { size_t num_reverse_channels, size_t num_output_channels); - // Checks whether the module is enabled. Must only be - // called from the render side of APM as otherwise - // deadlocks may occur. - bool is_enabled_render_side_query() const; + static void PackRenderAudioBuffer(const AudioBuffer* audio, + size_t num_output_channels, + size_t num_channels, + std::vector* packed_buffer); - // Reads render side data that has been queued on the render call. - void ReadQueuedRenderData(); + static size_t NumCancellersRequired(size_t num_output_channels, + size_t num_reverse_channels); private: class Canceller; @@ -62,9 +62,6 @@ class EchoControlMobileImpl : public EchoControlMobile { int SetEchoPath(const void* echo_path, size_t size_bytes) override; int GetEchoPath(void* echo_path, size_t size_bytes) const override; - size_t num_handles_required() const; - - void AllocateRenderQueue(); int Configure(); rtc::CriticalSection* const crit_render_ ACQUIRED_BEFORE(crit_capture_); @@ -77,17 +74,6 @@ class EchoControlMobileImpl : public EchoControlMobile { unsigned char* external_echo_path_ GUARDED_BY(crit_render_) GUARDED_BY(crit_capture_); - size_t render_queue_element_max_size_ GUARDED_BY(crit_render_) - GUARDED_BY(crit_capture_); - - std::vector render_queue_buffer_ GUARDED_BY(crit_render_); - std::vector capture_queue_buffer_ GUARDED_BY(crit_capture_); - - // Lock protection not needed. - std::unique_ptr< - SwapQueue, RenderQueueItemVerifier>> - render_signal_queue_; - std::vector> cancellers_; std::unique_ptr stream_properties_; diff --git a/include/webrtc/modules/audio_processing/echo_detector/circular_buffer.h b/include/webrtc/modules/audio_processing/echo_detector/circular_buffer.h new file mode 100644 index 0000000..667b1f8 --- /dev/null +++ b/include/webrtc/modules/audio_processing/echo_detector/circular_buffer.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_CIRCULAR_BUFFER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_CIRCULAR_BUFFER_H_ + +#include + +#include "webrtc/base/optional.h" + +namespace webrtc { + +// Ring buffer containing floating point values. +struct CircularBuffer { + public: + explicit CircularBuffer(size_t size); + ~CircularBuffer(); + + void Push(float value); + rtc::Optional Pop(); + size_t Size() const { return nr_elements_in_buffer_; } + // This function fills the buffer with zeros, but does not change its size. + void Clear(); + + private: + std::vector buffer_; + size_t next_insertion_index_ = 0; + // This is the number of elements that have been pushed into the circular + // buffer, not the allocated buffer size. + size_t nr_elements_in_buffer_ = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_CIRCULAR_BUFFER_H_ diff --git a/include/webrtc/modules/audio_processing/echo_detector/mean_variance_estimator.h b/include/webrtc/modules/audio_processing/echo_detector/mean_variance_estimator.h new file mode 100644 index 0000000..3c0700f --- /dev/null +++ b/include/webrtc/modules/audio_processing/echo_detector/mean_variance_estimator.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MEAN_VARIANCE_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MEAN_VARIANCE_ESTIMATOR_H_ + +namespace webrtc { + +// This class iteratively estimates the mean and variance of a signal. +class MeanVarianceEstimator { + public: + void Update(float value); + float std_deviation() const; + float mean() const; + void Clear(); + + private: + // Estimate of the expected value of the input values. + float mean_ = 0.f; + // Estimate of the variance of the input values. + float variance_ = 0.f; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MEAN_VARIANCE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/echo_detector/moving_max.h b/include/webrtc/modules/audio_processing/echo_detector/moving_max.h new file mode 100644 index 0000000..556facf --- /dev/null +++ b/include/webrtc/modules/audio_processing/echo_detector/moving_max.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MOVING_MAX_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MOVING_MAX_H_ + +#include + +namespace webrtc { + +class MovingMax { + public: + explicit MovingMax(size_t window_size); + ~MovingMax(); + + void Update(float value); + float max() const; + // Reset all of the state in this class. + void Clear(); + + private: + float max_value_ = 0.f; + size_t counter_ = 0; + size_t window_size_ = 1; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_MOVING_MAX_H_ diff --git a/include/webrtc/modules/audio_processing/echo_detector/normalized_covariance_estimator.h b/include/webrtc/modules/audio_processing/echo_detector/normalized_covariance_estimator.h new file mode 100644 index 0000000..f77a30e --- /dev/null +++ b/include/webrtc/modules/audio_processing/echo_detector/normalized_covariance_estimator.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_NORMALIZED_COVARIANCE_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_NORMALIZED_COVARIANCE_ESTIMATOR_H_ + +namespace webrtc { + +// This class iteratively estimates the normalized covariance between two +// signals. +class NormalizedCovarianceEstimator { + public: + void Update(float x, + float x_mean, + float x_var, + float y, + float y_mean, + float y_var); + // This function returns an estimate of the Pearson product-moment correlation + // coefficient of the two signals. + float normalized_cross_correlation() const { + return normalized_cross_correlation_; + } + // This function resets the estimated values to zero. + void Clear(); + + private: + float normalized_cross_correlation_ = 0.f; + // Estimate of the covariance value. + float covariance_ = 0.f; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_ECHO_DETECTOR_NORMALIZED_COVARIANCE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/gain_control_for_experimental_agc.h b/include/webrtc/modules/audio_processing/gain_control_for_experimental_agc.h index 4fbd05c..75d87d1 100644 --- a/include/webrtc/modules/audio_processing/gain_control_for_experimental_agc.h +++ b/include/webrtc/modules/audio_processing/gain_control_for_experimental_agc.h @@ -19,6 +19,8 @@ namespace webrtc { +class ApmDataDumper; + // This class has two main purposes: // // 1) It is returned instead of the real GainControl after the new AGC has been @@ -33,8 +35,9 @@ namespace webrtc { class GainControlForExperimentalAgc : public GainControl, public VolumeCallbacks { public: - explicit GainControlForExperimentalAgc(GainControl* gain_control, - rtc::CriticalSection* crit_capture); + GainControlForExperimentalAgc(GainControl* gain_control, + rtc::CriticalSection* crit_capture); + ~GainControlForExperimentalAgc() override; // GainControl implementation. int Enable(bool enable) override; @@ -58,11 +61,15 @@ class GainControlForExperimentalAgc : public GainControl, void SetMicVolume(int volume) override; int GetMicVolume() override; + void Initialize(); + private: + std::unique_ptr data_dumper_; GainControl* real_gain_control_; int volume_; rtc::CriticalSection* crit_capture_; - RTC_DISALLOW_COPY_AND_ASSIGN(GainControlForExperimentalAgc); + static int instance_counter_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GainControlForExperimentalAgc); }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/gain_control_impl.h b/include/webrtc/modules/audio_processing/gain_control_impl.h index 2459ce3..bd56ed4 100644 --- a/include/webrtc/modules/audio_processing/gain_control_impl.h +++ b/include/webrtc/modules/audio_processing/gain_control_impl.h @@ -23,6 +23,7 @@ namespace webrtc { +class ApmDataDumper; class AudioBuffer; class GainControlImpl : public GainControl { @@ -31,26 +32,21 @@ class GainControlImpl : public GainControl { rtc::CriticalSection* crit_capture); ~GainControlImpl() override; - int ProcessRenderAudio(AudioBuffer* audio); + void ProcessRenderAudio(rtc::ArrayView packed_render_audio); int AnalyzeCaptureAudio(AudioBuffer* audio); int ProcessCaptureAudio(AudioBuffer* audio, bool stream_has_echo); void Initialize(size_t num_proc_channels, int sample_rate_hz); + static void PackRenderAudioBuffer(AudioBuffer* audio, + std::vector* packed_buffer); + // GainControl implementation. bool is_enabled() const override; int stream_analog_level() override; bool is_limiter_enabled() const override; Mode mode() const override; - // Checks whether the module is enabled. Must only be - // called from the render side of APM as otherwise - // deadlocks may occur. - bool is_enabled_render_side_query() const; - - // Reads render side data that has been queued on the render call. - void ReadQueuedRenderData(); - int compression_gain_db() const override; private: @@ -69,12 +65,13 @@ class GainControlImpl : public GainControl { int analog_level_maximum() const override; bool stream_is_saturated() const override; - void AllocateRenderQueue(); int Configure(); rtc::CriticalSection* const crit_render_ ACQUIRED_BEFORE(crit_capture_); rtc::CriticalSection* const crit_capture_; + std::unique_ptr data_dumper_; + bool enabled_ = false; Mode mode_ GUARDED_BY(crit_capture_); @@ -87,21 +84,12 @@ class GainControlImpl : public GainControl { bool was_analog_level_set_ GUARDED_BY(crit_capture_); bool stream_is_saturated_ GUARDED_BY(crit_capture_); - size_t render_queue_element_max_size_ GUARDED_BY(crit_render_) - GUARDED_BY(crit_capture_); - std::vector render_queue_buffer_ GUARDED_BY(crit_render_); - std::vector capture_queue_buffer_ GUARDED_BY(crit_capture_); - - // Lock protection not needed. - std::unique_ptr< - SwapQueue, RenderQueueItemVerifier>> - render_signal_queue_; - std::vector> gain_controllers_; rtc::Optional num_proc_channels_ GUARDED_BY(crit_capture_); rtc::Optional sample_rate_hz_ GUARDED_BY(crit_capture_); + static int instance_counter_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GainControlImpl); }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/high_pass_filter_impl.h b/include/webrtc/modules/audio_processing/high_pass_filter_impl.h deleted file mode 100644 index 5cb18f1..0000000 --- a/include/webrtc/modules/audio_processing/high_pass_filter_impl.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_HIGH_PASS_FILTER_IMPL_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_HIGH_PASS_FILTER_IMPL_H_ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/base/criticalsection.h" -#include "webrtc/modules/audio_processing/include/audio_processing.h" - -namespace webrtc { - -class AudioBuffer; - -class HighPassFilterImpl : public HighPassFilter { - public: - explicit HighPassFilterImpl(rtc::CriticalSection* crit); - ~HighPassFilterImpl() override; - - // TODO(peah): Fold into ctor, once public API is removed. - void Initialize(size_t channels, int sample_rate_hz); - void ProcessCaptureAudio(AudioBuffer* audio); - - // HighPassFilter implementation. - int Enable(bool enable) override; - bool is_enabled() const override; - - private: - class BiquadFilter; - rtc::CriticalSection* const crit_ = nullptr; - bool enabled_ GUARDED_BY(crit_) = false; - std::vector> filters_ GUARDED_BY(crit_); - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(HighPassFilterImpl); -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_HIGH_PASS_FILTER_IMPL_H_ diff --git a/include/webrtc/modules/audio_processing/include/audio_processing.h b/include/webrtc/modules/audio_processing/include/audio_processing.h index 2f8e48f..ab924b7 100644 --- a/include/webrtc/modules/audio_processing/include/audio_processing.h +++ b/include/webrtc/modules/audio_processing/include/audio_processing.h @@ -21,8 +21,8 @@ #include "webrtc/base/arraysize.h" #include "webrtc/base/platform_file.h" -#include "webrtc/common.h" #include "webrtc/modules/audio_processing/beamformer/array_util.h" +#include "webrtc/modules/audio_processing/include/config.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -31,8 +31,7 @@ struct AecCore; class AudioFrame; -template -class Beamformer; +class NonlinearBeamformer; class StreamConfig; class ProcessingConfig; @@ -69,17 +68,6 @@ struct ExtendedFilter { bool enabled; }; -// Enables the next generation AEC functionality. This feature replaces the -// standard methods for echo removal in the AEC. This configuration only applies -// to EchoCancellation and not EchoControlMobile. It can be set in the -// constructor or using AudioProcessing::SetExtraOptions(). -struct EchoCanceller3 { - EchoCanceller3() : enabled(false) {} - explicit EchoCanceller3(bool enabled) : enabled(enabled) {} - static const ConfigOptionID identifier = ConfigOptionID::kEchoCanceller3; - bool enabled; -}; - // Enables the refined linear filter adaptation in the echo canceller. // This configuration only applies to EchoCancellation and not // EchoControlMobile. It can be set in the constructor @@ -115,15 +103,21 @@ static const int kAgcStartupMinVolume = 85; #else static const int kAgcStartupMinVolume = 0; #endif // defined(WEBRTC_CHROMIUM_BUILD) +static constexpr int kClippedLevelMin = 170; struct ExperimentalAgc { - ExperimentalAgc() : enabled(true), startup_min_volume(kAgcStartupMinVolume) {} - explicit ExperimentalAgc(bool enabled) - : enabled(enabled), startup_min_volume(kAgcStartupMinVolume) {} + ExperimentalAgc() = default; + explicit ExperimentalAgc(bool enabled) : enabled(enabled) {} ExperimentalAgc(bool enabled, int startup_min_volume) : enabled(enabled), startup_min_volume(startup_min_volume) {} + ExperimentalAgc(bool enabled, int startup_min_volume, int clipped_level_min) + : enabled(enabled), + startup_min_volume(startup_min_volume), + clipped_level_min(clipped_level_min) {} static const ConfigOptionID identifier = ConfigOptionID::kExperimentalAgc; - bool enabled; - int startup_min_volume; + bool enabled = true; + int startup_min_volume = kAgcStartupMinVolume; + // Lowest microphone level that will be applied in response to clipping. + int clipped_level_min = kClippedLevelMin; }; // Use to enable experimental noise suppression. It can be set in the @@ -138,22 +132,13 @@ struct ExperimentalNs { // Use to enable beamforming. Must be provided through the constructor. It will // have no impact if used with AudioProcessing::SetExtraOptions(). struct Beamforming { - Beamforming() - : enabled(false), - array_geometry(), - target_direction( - SphericalPointf(static_cast(M_PI) / 2.f, 0.f, 1.f)) {} - Beamforming(bool enabled, const std::vector& array_geometry) - : Beamforming(enabled, - array_geometry, - SphericalPointf(static_cast(M_PI) / 2.f, 0.f, 1.f)) { - } + Beamforming(); + Beamforming(bool enabled, const std::vector& array_geometry); Beamforming(bool enabled, const std::vector& array_geometry, - SphericalPointf target_direction) - : enabled(enabled), - array_geometry(array_geometry), - target_direction(target_direction) {} + SphericalPointf target_direction); + ~Beamforming(); + static const ConfigOptionID identifier = ConfigOptionID::kBeamforming; const bool enabled; const std::vector array_geometry; @@ -207,7 +192,10 @@ struct Intelligibility { // Usage example, omitting error checking: // AudioProcessing* apm = AudioProcessing::Create(0); // -// apm->high_pass_filter()->Enable(true); +// AudioProcessing::Config config; +// config.level_controller.enabled = true; +// config.high_pass_filter.enabled = true; +// apm->ApplyConfig(config) // // apm->echo_cancellation()->enable_drift_compensation(false); // apm->echo_cancellation()->Enable(true); @@ -246,14 +234,49 @@ struct Intelligibility { // class AudioProcessing { public: + // The struct below constitutes the new parameter scheme for the audio + // processing. It is being introduced gradually and until it is fully + // introduced, it is prone to change. + // TODO(peah): Remove this comment once the new config scheme is fully rolled + // out. + // + // The parameters and behavior of the audio processing module are controlled + // by changing the default values in the AudioProcessing::Config struct. + // The config is applied by passing the struct to the ApplyConfig method. + struct Config { + struct LevelController { + bool enabled = false; + + // Sets the initial peak level to use inside the level controller in order + // to compute the signal gain. The unit for the peak level is dBFS and + // the allowed range is [-100, 0]. + float initial_peak_level_dbfs = -6.0206f; + } level_controller; + struct ResidualEchoDetector { + bool enabled = true; + } residual_echo_detector; + + struct HighPassFilter { + bool enabled = false; + } high_pass_filter; + + // Enables the next generation AEC functionality. This feature replaces the + // standard methods for echo removal in the AEC. + // The functionality is not yet activated in the code and turning this on + // does not yet have the desired behavior. + struct EchoCanceller3 { + bool enabled = false; + } echo_canceller3; + }; + // TODO(mgraczyk): Remove once all methods that use ChannelLayout are gone. enum ChannelLayout { kMono, // Left, right. kStereo, - // Mono, keyboard mic. + // Mono, keyboard, and mic. kMonoAndKeyboard, - // Left, right, keyboard mic. + // Left, right, keyboard, and mic. kStereoAndKeyboard }; @@ -264,10 +287,10 @@ class AudioProcessing { // be one instance for every incoming stream. static AudioProcessing* Create(); // Allows passing in an optional configuration at create-time. - static AudioProcessing* Create(const Config& config); + static AudioProcessing* Create(const webrtc::Config& config); // Only for testing. - static AudioProcessing* Create(const Config& config, - Beamformer* beamformer); + static AudioProcessing* Create(const webrtc::Config& config, + NonlinearBeamformer* beamformer); virtual ~AudioProcessing() {} // Initializes internal states, while retaining all user settings. This @@ -295,16 +318,20 @@ class AudioProcessing { // Initialize with unpacked parameters. See Initialize() above for details. // // TODO(mgraczyk): Remove once clients are updated to use the new interface. - virtual int Initialize(int input_sample_rate_hz, - int output_sample_rate_hz, - int reverse_sample_rate_hz, - ChannelLayout input_layout, - ChannelLayout output_layout, - ChannelLayout reverse_layout) = 0; + virtual int Initialize(int capture_input_sample_rate_hz, + int capture_output_sample_rate_hz, + int render_sample_rate_hz, + ChannelLayout capture_input_layout, + ChannelLayout capture_output_layout, + ChannelLayout render_input_layout) = 0; + + // TODO(peah): This method is a temporary solution used to take control + // over the parameters in the audio processing module and is likely to change. + virtual void ApplyConfig(const Config& config) = 0; // Pass down additional options which don't have explicit setters. This // ensures the options are applied immediately. - virtual void SetExtraOptions(const Config& config) = 0; + virtual void SetExtraOptions(const webrtc::Config& config) = 0; // TODO(ajm): Only intended for internal use. Make private and friend the // necessary classes? @@ -381,14 +408,14 @@ class AudioProcessing { // TODO(mgraczyk): Remove once clients are updated to use the new interface. virtual int AnalyzeReverseStream(const float* const* data, size_t samples_per_channel, - int rev_sample_rate_hz, + int sample_rate_hz, ChannelLayout layout) = 0; // Accepts deinterleaved float audio with the range [-1, 1]. Each element of // |data| points to a channel buffer, arranged according to |reverse_config|. virtual int ProcessReverseStream(const float* const* src, - const StreamConfig& reverse_input_config, - const StreamConfig& reverse_output_config, + const StreamConfig& input_config, + const StreamConfig& output_config, float* const* dest) = 0; // This must be called if and only if echo processing is enabled. @@ -436,16 +463,12 @@ class AudioProcessing { virtual int StartDebugRecording(FILE* handle, int64_t max_log_size_bytes) = 0; // TODO(ivoc): Remove this function after Chrome stops using it. - int StartDebugRecording(FILE* handle) { - return StartDebugRecording(handle, -1); - } + virtual int StartDebugRecording(FILE* handle) = 0; // Same as above but uses an existing PlatformFile handle. Takes ownership // of |handle| and closes it at StopDebugRecording(). // TODO(xians): Make this interface pure virtual. - virtual int StartDebugRecordingForPlatformFile(rtc::PlatformFile handle) { - return -1; - } + virtual int StartDebugRecordingForPlatformFile(rtc::PlatformFile handle) = 0; // Stops recording debugging information, and closes the file. Recording // cannot be resumed in the same file (without overwriting it). @@ -455,24 +478,87 @@ class AudioProcessing { // specific member variables are reset. virtual void UpdateHistogramsOnCallEnd() = 0; + // TODO(ivoc): Remove when the calling code no longer uses the old Statistics + // API. + struct Statistic { + int instant = 0; // Instantaneous value. + int average = 0; // Long-term average. + int maximum = 0; // Long-term maximum. + int minimum = 0; // Long-term minimum. + }; + + struct Stat { + void Set(const Statistic& other) { + Set(other.instant, other.average, other.maximum, other.minimum); + } + void Set(float instant, float average, float maximum, float minimum) { + instant_ = instant; + average_ = average; + maximum_ = maximum; + minimum_ = minimum; + } + float instant() const { return instant_; } + float average() const { return average_; } + float maximum() const { return maximum_; } + float minimum() const { return minimum_; } + + private: + float instant_ = 0.0f; // Instantaneous value. + float average_ = 0.0f; // Long-term average. + float maximum_ = 0.0f; // Long-term maximum. + float minimum_ = 0.0f; // Long-term minimum. + }; + + struct AudioProcessingStatistics { + AudioProcessingStatistics(); + AudioProcessingStatistics(const AudioProcessingStatistics& other); + ~AudioProcessingStatistics(); + + // AEC Statistics. + // RERL = ERL + ERLE + Stat residual_echo_return_loss; + // ERL = 10log_10(P_far / P_echo) + Stat echo_return_loss; + // ERLE = 10log_10(P_echo / P_out) + Stat echo_return_loss_enhancement; + // (Pre non-linear processing suppression) A_NLP = 10log_10(P_echo / P_a) + Stat a_nlp; + // Fraction of time that the AEC linear filter is divergent, in a 1-second + // non-overlapped aggregation window. + float divergent_filter_fraction = -1.0f; + + // The delay metrics consists of the delay median and standard deviation. It + // also consists of the fraction of delay estimates that can make the echo + // cancellation perform poorly. The values are aggregated until the first + // call to |GetStatistics()| and afterwards aggregated and updated every + // second. Note that if there are several clients pulling metrics from + // |GetStatistics()| during a session the first call from any of them will + // change to one second aggregation window for all. + int delay_median = -1; + int delay_standard_deviation = -1; + float fraction_poor_delays = -1.0f; + + // Residual echo detector likelihood. + float residual_echo_likelihood = -1.0f; + // Maximum residual echo likelihood from the last time period. + float residual_echo_likelihood_recent_max = -1.0f; + }; + + // TODO(ivoc): Make this pure virtual when all subclasses have been updated. + virtual AudioProcessingStatistics GetStatistics() const; + // These provide access to the component interfaces and should never return // NULL. The pointers will be valid for the lifetime of the APM instance. // The memory for these objects is entirely managed internally. virtual EchoCancellation* echo_cancellation() const = 0; virtual EchoControlMobile* echo_control_mobile() const = 0; virtual GainControl* gain_control() const = 0; + // TODO(peah): Deprecate this API call. virtual HighPassFilter* high_pass_filter() const = 0; virtual LevelEstimator* level_estimator() const = 0; virtual NoiseSuppression* noise_suppression() const = 0; virtual VoiceDetection* voice_detection() const = 0; - struct Statistic { - int instant; // Instantaneous value. - int average; // Long-term average. - int maximum; // Long-term maximum. - int minimum; // Long-term minimum. - }; - enum Error { // Fatal errors. kNoError = 0, @@ -502,9 +588,15 @@ class AudioProcessing { kSampleRate48kHz = 48000 }; - static const int kNativeSampleRatesHz[]; - static const size_t kNumNativeSampleRates; - static const int kMaxNativeSampleRateHz; + // TODO(kwiberg): We currently need to support a compiler (Visual C++) that + // complains if we don't explicitly state the size of the array here. Remove + // the size when that's no longer the case. + static constexpr int kNativeSampleRatesHz[4] = { + kSampleRate8kHz, kSampleRate16kHz, kSampleRate32kHz, kSampleRate48kHz}; + static constexpr size_t kNumNativeSampleRates = + arraysize(kNativeSampleRatesHz); + static constexpr int kMaxNativeSampleRateHz = + kNativeSampleRatesHz[kNumNativeSampleRates - 1]; static const int kChunkSizeMs = 10; }; @@ -688,6 +780,7 @@ class EchoCancellation { float divergent_filter_fraction; }; + // Deprecated. Use GetStatistics on the AudioProcessing interface instead. // TODO(ajm): discuss the metrics update period. virtual int GetMetrics(Metrics* metrics) = 0; @@ -704,8 +797,9 @@ class EchoCancellation { // Note that if there are several clients pulling metrics from // |GetDelayMetrics()| during a session the first call from any of them will // change to one second aggregation window for all. - // TODO(bjornv): Deprecated, remove. + // Deprecated. Use GetStatistics on the AudioProcessing interface instead. virtual int GetDelayMetrics(int* median, int* std) = 0; + // Deprecated. Use GetStatistics on the AudioProcessing interface instead. virtual int GetDelayMetrics(int* median, int* std, float* fraction_poor_delays) = 0; @@ -866,7 +960,7 @@ class GainControl { protected: virtual ~GainControl() {} }; - +// TODO(peah): Remove this interface. // A filtering component which removes DC offset and low-frequency noise. // Recommended to be enabled on the client-side. class HighPassFilter { @@ -874,7 +968,6 @@ class HighPassFilter { virtual int Enable(bool enable) = 0; virtual bool is_enabled() const = 0; - protected: virtual ~HighPassFilter() {} }; diff --git a/include/webrtc/common.h b/include/webrtc/modules/audio_processing/include/config.h similarity index 87% rename from include/webrtc/common.h rename to include/webrtc/modules/audio_processing/include/config.h index 3aeea81..0473d2d 100644 --- a/include/webrtc/common.h +++ b/include/webrtc/modules/audio_processing/include/config.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_COMMON_H_ -#define WEBRTC_COMMON_H_ +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_ #include @@ -23,18 +23,19 @@ namespace webrtc { enum class ConfigOptionID { kMyExperimentForTest, kAlgo1CostFunctionForTest, - kTemporalLayersFactory, - kNetEqCapacityConfig, - kNetEqFastAccelerate, - kVoicePacing, + kTemporalLayersFactory, // Deprecated + kNetEqCapacityConfig, // Deprecated + kNetEqFastAccelerate, // Deprecated + kVoicePacing, // Deprecated kExtendedFilter, kDelayAgnostic, kExperimentalAgc, kExperimentalNs, kBeamforming, kIntelligibility, - kEchoCanceller3, - kAecRefinedAdaptiveFilter + kEchoCanceller3, // Deprecated + kAecRefinedAdaptiveFilter, + kLevelControl }; // Class Config is designed to ease passing a set of options across webrtc code. @@ -70,15 +71,8 @@ class Config { // This instance gets ownership of the newly set value. template void Set(T* value); - Config() {} - ~Config() { - // Note: this method is inline so webrtc public API depends only - // on the headers. - for (OptionMap::iterator it = options_.begin(); - it != options_.end(); ++it) { - delete it->second; - } - } + Config(); + ~Config(); private: struct BaseOption { @@ -134,7 +128,6 @@ void Config::Set(T* value) { delete it; it = new Option(value); } - } // namespace webrtc -#endif // WEBRTC_COMMON_H_ +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_INCLUDE_CONFIG_H_ diff --git a/include/webrtc/modules/audio_processing/include/mock_audio_processing.h b/include/webrtc/modules/audio_processing/include/mock_audio_processing.h index b5ea587..b5a1fa4 100644 --- a/include/webrtc/modules/audio_processing/include/mock_audio_processing.h +++ b/include/webrtc/modules/audio_processing/include/mock_audio_processing.h @@ -14,252 +14,176 @@ #include #include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/test/gmock.h" namespace webrtc { +namespace test { + class MockEchoCancellation : public EchoCancellation { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_METHOD1(enable_drift_compensation, - int(bool enable)); - MOCK_CONST_METHOD0(is_drift_compensation_enabled, - bool()); - MOCK_METHOD1(set_stream_drift_samples, - void(int drift)); - MOCK_CONST_METHOD0(stream_drift_samples, - int()); - MOCK_METHOD1(set_suppression_level, - int(SuppressionLevel level)); - MOCK_CONST_METHOD0(suppression_level, - SuppressionLevel()); - MOCK_CONST_METHOD0(stream_has_echo, - bool()); - MOCK_METHOD1(enable_metrics, - int(bool enable)); - MOCK_CONST_METHOD0(are_metrics_enabled, - bool()); - MOCK_METHOD1(GetMetrics, - int(Metrics* metrics)); - MOCK_METHOD1(enable_delay_logging, - int(bool enable)); - MOCK_CONST_METHOD0(is_delay_logging_enabled, - bool()); - MOCK_METHOD2(GetDelayMetrics, - int(int* median, int* std)); - MOCK_METHOD3(GetDelayMetrics, - int(int* median, int* std, float* fraction_poor_delays)); - MOCK_CONST_METHOD0(aec_core, - struct AecCore*()); + virtual ~MockEchoCancellation() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_METHOD1(enable_drift_compensation, int(bool enable)); + MOCK_CONST_METHOD0(is_drift_compensation_enabled, bool()); + MOCK_METHOD1(set_stream_drift_samples, void(int drift)); + MOCK_CONST_METHOD0(stream_drift_samples, int()); + MOCK_METHOD1(set_suppression_level, int(SuppressionLevel level)); + MOCK_CONST_METHOD0(suppression_level, SuppressionLevel()); + MOCK_CONST_METHOD0(stream_has_echo, bool()); + MOCK_METHOD1(enable_metrics, int(bool enable)); + MOCK_CONST_METHOD0(are_metrics_enabled, bool()); + MOCK_METHOD1(GetMetrics, int(Metrics* metrics)); + MOCK_METHOD1(enable_delay_logging, int(bool enable)); + MOCK_CONST_METHOD0(is_delay_logging_enabled, bool()); + MOCK_METHOD2(GetDelayMetrics, int(int* median, int* std)); + MOCK_METHOD3(GetDelayMetrics, int(int* median, int* std, + float* fraction_poor_delays)); + MOCK_CONST_METHOD0(aec_core, struct AecCore*()); }; class MockEchoControlMobile : public EchoControlMobile { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_METHOD1(set_routing_mode, - int(RoutingMode mode)); - MOCK_CONST_METHOD0(routing_mode, - RoutingMode()); - MOCK_METHOD1(enable_comfort_noise, - int(bool enable)); - MOCK_CONST_METHOD0(is_comfort_noise_enabled, - bool()); - MOCK_METHOD2(SetEchoPath, - int(const void* echo_path, size_t size_bytes)); - MOCK_CONST_METHOD2(GetEchoPath, - int(void* echo_path, size_t size_bytes)); + virtual ~MockEchoControlMobile() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_METHOD1(set_routing_mode, int(RoutingMode mode)); + MOCK_CONST_METHOD0(routing_mode, RoutingMode()); + MOCK_METHOD1(enable_comfort_noise, int(bool enable)); + MOCK_CONST_METHOD0(is_comfort_noise_enabled, bool()); + MOCK_METHOD2(SetEchoPath, int(const void* echo_path, size_t size_bytes)); + MOCK_CONST_METHOD2(GetEchoPath, int(void* echo_path, size_t size_bytes)); }; class MockGainControl : public GainControl { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_METHOD1(set_stream_analog_level, - int(int level)); - MOCK_METHOD0(stream_analog_level, - int()); - MOCK_METHOD1(set_mode, - int(Mode mode)); - MOCK_CONST_METHOD0(mode, - Mode()); - MOCK_METHOD1(set_target_level_dbfs, - int(int level)); - MOCK_CONST_METHOD0(target_level_dbfs, - int()); - MOCK_METHOD1(set_compression_gain_db, - int(int gain)); - MOCK_CONST_METHOD0(compression_gain_db, - int()); - MOCK_METHOD1(enable_limiter, - int(bool enable)); - MOCK_CONST_METHOD0(is_limiter_enabled, - bool()); - MOCK_METHOD2(set_analog_level_limits, - int(int minimum, int maximum)); - MOCK_CONST_METHOD0(analog_level_minimum, - int()); - MOCK_CONST_METHOD0(analog_level_maximum, - int()); - MOCK_CONST_METHOD0(stream_is_saturated, - bool()); + virtual ~MockGainControl() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_METHOD1(set_stream_analog_level, int(int level)); + MOCK_METHOD0(stream_analog_level, int()); + MOCK_METHOD1(set_mode, int(Mode mode)); + MOCK_CONST_METHOD0(mode, Mode()); + MOCK_METHOD1(set_target_level_dbfs, int(int level)); + MOCK_CONST_METHOD0(target_level_dbfs, int()); + MOCK_METHOD1(set_compression_gain_db, int(int gain)); + MOCK_CONST_METHOD0(compression_gain_db, int()); + MOCK_METHOD1(enable_limiter, int(bool enable)); + MOCK_CONST_METHOD0(is_limiter_enabled, bool()); + MOCK_METHOD2(set_analog_level_limits, int(int minimum, int maximum)); + MOCK_CONST_METHOD0(analog_level_minimum, int()); + MOCK_CONST_METHOD0(analog_level_maximum, int()); + MOCK_CONST_METHOD0(stream_is_saturated, bool()); }; class MockHighPassFilter : public HighPassFilter { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); + virtual ~MockHighPassFilter() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); }; class MockLevelEstimator : public LevelEstimator { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_METHOD0(RMS, - int()); + virtual ~MockLevelEstimator() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_METHOD0(RMS, int()); }; class MockNoiseSuppression : public NoiseSuppression { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_METHOD1(set_level, - int(Level level)); - MOCK_CONST_METHOD0(level, - Level()); - MOCK_CONST_METHOD0(speech_probability, - float()); + virtual ~MockNoiseSuppression() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_METHOD1(set_level, int(Level level)); + MOCK_CONST_METHOD0(level, Level()); + MOCK_CONST_METHOD0(speech_probability, float()); MOCK_METHOD0(NoiseEstimate, std::vector()); }; class MockVoiceDetection : public VoiceDetection { public: - MOCK_METHOD1(Enable, - int(bool enable)); - MOCK_CONST_METHOD0(is_enabled, - bool()); - MOCK_CONST_METHOD0(stream_has_voice, - bool()); - MOCK_METHOD1(set_stream_has_voice, - int(bool has_voice)); - MOCK_METHOD1(set_likelihood, - int(Likelihood likelihood)); - MOCK_CONST_METHOD0(likelihood, - Likelihood()); - MOCK_METHOD1(set_frame_size_ms, - int(int size)); - MOCK_CONST_METHOD0(frame_size_ms, - int()); + virtual ~MockVoiceDetection() {} + MOCK_METHOD1(Enable, int(bool enable)); + MOCK_CONST_METHOD0(is_enabled, bool()); + MOCK_CONST_METHOD0(stream_has_voice, bool()); + MOCK_METHOD1(set_stream_has_voice, int(bool has_voice)); + MOCK_METHOD1(set_likelihood, int(Likelihood likelihood)); + MOCK_CONST_METHOD0(likelihood, Likelihood()); + MOCK_METHOD1(set_frame_size_ms, int(int size)); + MOCK_CONST_METHOD0(frame_size_ms, int()); }; class MockAudioProcessing : public AudioProcessing { public: MockAudioProcessing() - : echo_cancellation_(new MockEchoCancellation), - echo_control_mobile_(new MockEchoControlMobile), - gain_control_(new MockGainControl), - high_pass_filter_(new MockHighPassFilter), - level_estimator_(new MockLevelEstimator), - noise_suppression_(new MockNoiseSuppression), - voice_detection_(new MockVoiceDetection) { - } - - virtual ~MockAudioProcessing() { + : echo_cancellation_(new testing::NiceMock()), + echo_control_mobile_(new testing::NiceMock()), + gain_control_(new testing::NiceMock()), + high_pass_filter_(new testing::NiceMock()), + level_estimator_(new testing::NiceMock()), + noise_suppression_(new testing::NiceMock()), + voice_detection_(new testing::NiceMock()) { } - MOCK_METHOD0(Initialize, - int()); - MOCK_METHOD6(Initialize, - int(int sample_rate_hz, - int output_sample_rate_hz, - int reverse_sample_rate_hz, - ChannelLayout input_layout, - ChannelLayout output_layout, - ChannelLayout reverse_layout)); - MOCK_METHOD1(Initialize, - int(const ProcessingConfig& processing_config)); - MOCK_METHOD1(SetExtraOptions, - void(const Config& config)); - MOCK_METHOD1(set_sample_rate_hz, - int(int rate)); - MOCK_CONST_METHOD0(input_sample_rate_hz, - int()); - MOCK_CONST_METHOD0(sample_rate_hz, - int()); - MOCK_CONST_METHOD0(proc_sample_rate_hz, - int()); - MOCK_CONST_METHOD0(proc_split_sample_rate_hz, - int()); - MOCK_CONST_METHOD0(num_input_channels, - size_t()); - MOCK_CONST_METHOD0(num_output_channels, - size_t()); - MOCK_CONST_METHOD0(num_reverse_channels, - size_t()); - MOCK_METHOD1(set_output_will_be_muted, - void(bool muted)); - MOCK_CONST_METHOD0(output_will_be_muted, - bool()); - MOCK_METHOD1(ProcessStream, - int(AudioFrame* frame)); - MOCK_METHOD7(ProcessStream, - int(const float* const* src, - size_t samples_per_channel, - int input_sample_rate_hz, - ChannelLayout input_layout, - int output_sample_rate_hz, - ChannelLayout output_layout, - float* const* dest)); - MOCK_METHOD4(ProcessStream, - int(const float* const* src, - const StreamConfig& input_config, - const StreamConfig& output_config, - float* const* dest)); - MOCK_METHOD1(AnalyzeReverseStream, - int(AudioFrame* frame)); + virtual ~MockAudioProcessing() {} + + MOCK_METHOD0(Initialize, int()); + MOCK_METHOD6(Initialize, int(int capture_input_sample_rate_hz, + int capture_output_sample_rate_hz, + int render_sample_rate_hz, + ChannelLayout capture_input_layout, + ChannelLayout capture_output_layout, + ChannelLayout render_input_layout)); + MOCK_METHOD1(Initialize, int(const ProcessingConfig& processing_config)); + MOCK_METHOD1(ApplyConfig, void(const Config& config)); + MOCK_METHOD1(SetExtraOptions, void(const webrtc::Config& config)); + MOCK_CONST_METHOD0(proc_sample_rate_hz, int()); + MOCK_CONST_METHOD0(proc_split_sample_rate_hz, int()); + MOCK_CONST_METHOD0(num_input_channels, size_t()); + MOCK_CONST_METHOD0(num_proc_channels, size_t()); + MOCK_CONST_METHOD0(num_output_channels, size_t()); + MOCK_CONST_METHOD0(num_reverse_channels, size_t()); + MOCK_METHOD1(set_output_will_be_muted, void(bool muted)); + MOCK_METHOD1(ProcessStream, int(AudioFrame* frame)); + MOCK_METHOD7(ProcessStream, int(const float* const* src, + size_t samples_per_channel, + int input_sample_rate_hz, + ChannelLayout input_layout, + int output_sample_rate_hz, + ChannelLayout output_layout, + float* const* dest)); + MOCK_METHOD4(ProcessStream, int(const float* const* src, + const StreamConfig& input_config, + const StreamConfig& output_config, + float* const* dest)); MOCK_METHOD1(ProcessReverseStream, int(AudioFrame* frame)); - MOCK_METHOD4(AnalyzeReverseStream, - int(const float* const* data, size_t frames, int sample_rate_hz, - ChannelLayout input_layout)); - MOCK_METHOD4(ProcessReverseStream, - int(const float* const* src, - const StreamConfig& input_config, - const StreamConfig& output_config, - float* const* dest)); - MOCK_METHOD1(set_stream_delay_ms, - int(int delay)); - MOCK_CONST_METHOD0(stream_delay_ms, - int()); - MOCK_CONST_METHOD0(was_stream_delay_set, - bool()); - MOCK_METHOD1(set_stream_key_pressed, - void(bool key_pressed)); - MOCK_CONST_METHOD0(stream_key_pressed, - bool()); - MOCK_METHOD1(set_delay_offset_ms, - void(int offset)); - MOCK_CONST_METHOD0(delay_offset_ms, - int()); - MOCK_METHOD2(StartDebugRecording, - int(const char filename[kMaxFilenameSize], - int64_t max_log_size_bytes)); - MOCK_METHOD2(StartDebugRecording, - int(FILE* handle, int64_t max_log_size_bytes)); - MOCK_METHOD0(StopDebugRecording, - int()); + MOCK_METHOD4(AnalyzeReverseStream, int(const float* const* data, + size_t samples_per_channel, + int sample_rate_hz, + ChannelLayout layout)); + MOCK_METHOD4(ProcessReverseStream, int(const float* const* src, + const StreamConfig& input_config, + const StreamConfig& output_config, + float* const* dest)); + MOCK_METHOD1(set_stream_delay_ms, int(int delay)); + MOCK_CONST_METHOD0(stream_delay_ms, int()); + MOCK_CONST_METHOD0(was_stream_delay_set, bool()); + MOCK_METHOD1(set_stream_key_pressed, void(bool key_pressed)); + MOCK_METHOD1(set_delay_offset_ms, void(int offset)); + MOCK_CONST_METHOD0(delay_offset_ms, int()); + MOCK_METHOD2(StartDebugRecording, int(const char filename[kMaxFilenameSize], + int64_t max_log_size_bytes)); + MOCK_METHOD2(StartDebugRecording, int(FILE* handle, + int64_t max_log_size_bytes)); + MOCK_METHOD1(StartDebugRecording, int (FILE* handle)); + MOCK_METHOD1(StartDebugRecordingForPlatformFile, + int(rtc::PlatformFile handle)); + MOCK_METHOD0(StopDebugRecording, int()); MOCK_METHOD0(UpdateHistogramsOnCallEnd, void()); + MOCK_CONST_METHOD0(GetStatistics, AudioProcessingStatistics()); virtual MockEchoCancellation* echo_cancellation() const { return echo_cancellation_.get(); } @@ -292,6 +216,7 @@ class MockAudioProcessing : public AudioProcessing { std::unique_ptr voice_detection_; }; +} // namespace test } // namespace webrtc #endif // WEBRTC_MODULES_AUDIO_PROCESSING_INCLUDE_MOCK_AUDIO_PROCESSING_H_ diff --git a/include/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.h b/include/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.h index 63ae80e..f7306cb 100644 --- a/include/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.h +++ b/include/webrtc/modules/audio_processing/intelligibility/intelligibility_enhancer.h @@ -16,8 +16,9 @@ #include #include "webrtc/base/swap_queue.h" -#include "webrtc/common_audio/lapped_transform.h" #include "webrtc/common_audio/channel_buffer.h" +#include "webrtc/common_audio/lapped_transform.h" +#include "webrtc/modules/audio_processing/audio_buffer.h" #include "webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h" #include "webrtc/modules/audio_processing/render_queue_item_verifier.h" #include "webrtc/modules/audio_processing/vad/voice_activity_detector.h" @@ -33,15 +34,16 @@ class IntelligibilityEnhancer : public LappedTransform::Callback { public: IntelligibilityEnhancer(int sample_rate_hz, size_t num_render_channels, + size_t num_bands, size_t num_noise_bins); + ~IntelligibilityEnhancer() override; + // Sets the capture noise magnitude spectrum estimate. - void SetCaptureNoiseEstimate(std::vector noise, int gain_db); + void SetCaptureNoiseEstimate(std::vector noise, float gain); // Reads chunk of speech in time domain and updates with modified signal. - void ProcessRenderAudio(float* const* audio, - int sample_rate_hz, - size_t num_channels); + void ProcessRenderAudio(AudioBuffer* audio); bool active() const; protected: @@ -54,10 +56,13 @@ class IntelligibilityEnhancer : public LappedTransform::Callback { std::complex* const* out_block) override; private: + FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestRenderUpdate); FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestErbCreation); FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestSolveForGains); FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestNoiseGainHasExpectedResult); + FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, + TestAllBandsHaveSameDelay); // Updates the SNR estimation and enables or disables this component using a // hysteresis. @@ -82,6 +87,10 @@ class IntelligibilityEnhancer : public LappedTransform::Callback { // Returns true if the audio is speech. bool IsSpeech(const float* audio); + // Delays the high bands to compensate for the processing delay in the low + // band. + void DelayHighBands(AudioBuffer* audio); + static const size_t kMaxNumNoiseEstimatesToBuffer = 5; const size_t freqs_; // Num frequencies in frequency domain. @@ -112,9 +121,15 @@ class IntelligibilityEnhancer : public LappedTransform::Callback { float snr_; bool is_active_; + unsigned long int num_chunks_; + unsigned long int num_active_chunks_; + std::vector noise_estimation_buffer_; SwapQueue, RenderQueueItemVerifier> noise_estimation_queue_; + + std::vector> + high_bands_buffers_; }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h b/include/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h index 11b9e49..2566616 100644 --- a/include/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h +++ b/include/webrtc/modules/audio_processing/intelligibility/intelligibility_utils.h @@ -48,6 +48,8 @@ class GainApplier { public: GainApplier(size_t freqs, float relative_change_limit); + ~GainApplier(); + // Copy |in_block| to |out_block|, multiplied by the current set of gains, // and step the current set of gains towards the target set. void Apply(const std::complex* in_block, @@ -63,6 +65,20 @@ class GainApplier { std::vector current_; }; +// Helper class to delay a signal by an integer number of samples. +class DelayBuffer { + public: + DelayBuffer(size_t delay, size_t num_channels); + + ~DelayBuffer(); + + void Delay(float* const* data, size_t length); + + private: + std::vector> buffer_; + size_t read_index_; +}; + } // namespace intelligibility } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/level_controller/biquad_filter.h b/include/webrtc/modules/audio_processing/level_controller/biquad_filter.h new file mode 100644 index 0000000..7e073b6 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/biquad_filter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_BIQUAD_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_BIQUAD_FILTER_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/arraysize.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class BiQuadFilter { + public: + struct BiQuadCoefficients { + float b[3]; + float a[2]; + }; + + BiQuadFilter() = default; + + void Initialize(const BiQuadCoefficients& coefficients) { + coefficients_ = coefficients; + } + + // Produces a filtered output y of the input x. Both x and y need to + // have the same length. + void Process(rtc::ArrayView x, rtc::ArrayView y); + + private: + struct BiQuadState { + BiQuadState() { + std::fill(b, b + arraysize(b), 0.f); + std::fill(a, a + arraysize(a), 0.f); + } + + float b[2]; + float a[2]; + }; + + BiQuadState biquad_state_; + BiQuadCoefficients coefficients_; + + RTC_DISALLOW_COPY_AND_ASSIGN(BiQuadFilter); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_BIQUAD_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/down_sampler.h b/include/webrtc/modules/audio_processing/level_controller/down_sampler.h new file mode 100644 index 0000000..5c8aaf3 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/down_sampler.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_DOWN_SAMPLER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_DOWN_SAMPLER_H_ + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/level_controller/biquad_filter.h" + +namespace webrtc { + +class ApmDataDumper; + +class DownSampler { + public: + explicit DownSampler(ApmDataDumper* data_dumper); + void Initialize(int sample_rate_hz); + + void DownSample(rtc::ArrayView in, rtc::ArrayView out); + + private: + ApmDataDumper* data_dumper_; + int sample_rate_hz_; + int down_sampling_factor_; + BiQuadFilter low_pass_filter_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DownSampler); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_DOWN_SAMPLER_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/gain_applier.h b/include/webrtc/modules/audio_processing/level_controller/gain_applier.h new file mode 100644 index 0000000..2fc3543 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/gain_applier.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_APPLIER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_APPLIER_H_ + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class ApmDataDumper; +class AudioBuffer; + +class GainApplier { + public: + explicit GainApplier(ApmDataDumper* data_dumper); + void Initialize(int sample_rate_hz); + + // Applies the specified gain to the audio frame and returns the resulting + // number of saturated sample values. + int Process(float new_gain, AudioBuffer* audio); + + private: + ApmDataDumper* const data_dumper_; + float old_gain_ = 1.f; + float gain_increase_step_size_ = 0.f; + float gain_normal_decrease_step_size_ = 0.f; + float gain_saturated_decrease_step_size_ = 0.f; + bool last_frame_was_saturated_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GainApplier); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_APPLIER_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/gain_selector.h b/include/webrtc/modules/audio_processing/level_controller/gain_selector.h new file mode 100644 index 0000000..78b9101 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/gain_selector.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_SELECTOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_SELECTOR_H_ + +#include "webrtc/base/constructormagic.h" + +#include "webrtc/modules/audio_processing/level_controller/signal_classifier.h" + +namespace webrtc { + +class GainSelector { + public: + GainSelector(); + void Initialize(int sample_rate_hz); + float GetNewGain(float peak_level, + float noise_energy, + float saturating_gain, + bool gain_jumpstart, + SignalClassifier::SignalType signal_type); + + private: + float gain_; + size_t frame_length_; + int highly_nonstationary_signal_hold_counter_; + + RTC_DISALLOW_COPY_AND_ASSIGN(GainSelector); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_GAIN_SELECTOR_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/level_controller.h b/include/webrtc/modules/audio_processing/level_controller/level_controller.h new file mode 100644 index 0000000..1030f79 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/level_controller.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/audio_processing/level_controller/gain_applier.h" +#include "webrtc/modules/audio_processing/level_controller/gain_selector.h" +#include "webrtc/modules/audio_processing/level_controller/noise_level_estimator.h" +#include "webrtc/modules/audio_processing/level_controller/peak_level_estimator.h" +#include "webrtc/modules/audio_processing/level_controller/saturating_gain_estimator.h" +#include "webrtc/modules/audio_processing/level_controller/signal_classifier.h" + +namespace webrtc { + +class ApmDataDumper; +class AudioBuffer; + +class LevelController { + public: + LevelController(); + ~LevelController(); + + void Initialize(int sample_rate_hz); + void Process(AudioBuffer* audio); + float GetLastGain() { return last_gain_; } + + // TODO(peah): This method is a temporary solution as the the aim is to + // instead apply the config inside the constructor. Therefore this is likely + // to change. + void ApplyConfig(const AudioProcessing::Config::LevelController& config); + // Validates a config. + static bool Validate(const AudioProcessing::Config::LevelController& config); + // Dumps a config to a string. + static std::string ToString( + const AudioProcessing::Config::LevelController& config); + + private: + class Metrics { + public: + Metrics() { Initialize(AudioProcessing::kSampleRate48kHz); } + void Initialize(int sample_rate_hz); + void Update(float long_term_peak_level, + float noise_level, + float gain, + float frame_peak_level); + + private: + void Reset(); + + size_t metrics_frame_counter_; + float gain_sum_; + float peak_level_sum_; + float noise_energy_sum_; + float max_gain_; + float max_peak_level_; + float max_noise_energy_; + float frame_length_; + }; + + std::unique_ptr data_dumper_; + GainSelector gain_selector_; + GainApplier gain_applier_; + SignalClassifier signal_classifier_; + NoiseLevelEstimator noise_level_estimator_; + PeakLevelEstimator peak_level_estimator_; + SaturatingGainEstimator saturating_gain_estimator_; + Metrics metrics_; + rtc::Optional sample_rate_hz_; + static int instance_count_; + float dc_level_[2]; + float dc_forgetting_factor_; + float last_gain_; + bool gain_jumpstart_ = false; + AudioProcessing::Config::LevelController config_; + + RTC_DISALLOW_COPY_AND_ASSIGN(LevelController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/level_controller_constants.h b/include/webrtc/modules/audio_processing/level_controller/level_controller_constants.h new file mode 100644 index 0000000..7b962d3 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/level_controller_constants.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_ + +namespace webrtc { + +const float kMaxLcGain = 10; +const float kMaxLcNoisePower = 100.f * 100.f; +const float kTargetLcPeakLevel = 16384.f; +const float kTargetLcPeakLeveldBFS = -6.0206f; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_LEVEL_CONTROLLER_CONSTANTS_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/noise_level_estimator.h b/include/webrtc/modules/audio_processing/level_controller/noise_level_estimator.h new file mode 100644 index 0000000..235b139 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/noise_level_estimator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_LEVEL_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_LEVEL_ESTIMATOR_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/level_controller/signal_classifier.h" + +namespace webrtc { + +class NoiseLevelEstimator { + public: + NoiseLevelEstimator(); + ~NoiseLevelEstimator(); + void Initialize(int sample_rate_hz); + float Analyze(SignalClassifier::SignalType signal_type, float frame_energy); + + private: + float min_noise_energy_ = 0.f; + bool first_update_; + float noise_energy_; + int noise_energy_hold_counter_; + + RTC_DISALLOW_COPY_AND_ASSIGN(NoiseLevelEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_LEVEL_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/noise_spectrum_estimator.h b/include/webrtc/modules/audio_processing/level_controller/noise_spectrum_estimator.h new file mode 100644 index 0000000..4bf81e3 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/noise_spectrum_estimator.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_SPECTRUM_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_SPECTRUM_ESTIMATOR_H_ + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class ApmDataDumper; + +class NoiseSpectrumEstimator { + public: + explicit NoiseSpectrumEstimator(ApmDataDumper* data_dumper); + void Initialize(); + void Update(rtc::ArrayView spectrum, bool first_update); + + rtc::ArrayView GetNoiseSpectrum() const { + return rtc::ArrayView(noise_spectrum_); + } + + private: + ApmDataDumper* data_dumper_; + float noise_spectrum_[65]; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(NoiseSpectrumEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_NOISE_SPECTRUM_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/peak_level_estimator.h b/include/webrtc/modules/audio_processing/level_controller/peak_level_estimator.h new file mode 100644 index 0000000..f908717 --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/peak_level_estimator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_PEAK_LEVEL_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_PEAK_LEVEL_ESTIMATOR_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/level_controller/level_controller_constants.h" +#include "webrtc/modules/audio_processing/level_controller/signal_classifier.h" + +namespace webrtc { + +class PeakLevelEstimator { + public: + explicit PeakLevelEstimator(float initial_peak_level_dbfs); + ~PeakLevelEstimator(); + void Initialize(float initial_peak_level_dbfs); + float Analyze(SignalClassifier::SignalType signal_type, + float frame_peak_level); + private: + float peak_level_; + int hold_counter_; + bool initialization_phase_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PeakLevelEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_PEAK_LEVEL_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/saturating_gain_estimator.h b/include/webrtc/modules/audio_processing/level_controller/saturating_gain_estimator.h new file mode 100644 index 0000000..1ec723d --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/saturating_gain_estimator.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SATURATING_GAIN_ESTIMATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SATURATING_GAIN_ESTIMATOR_H_ + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class ApmDataDumper; + +class SaturatingGainEstimator { + public: + SaturatingGainEstimator(); + ~SaturatingGainEstimator(); + void Initialize(); + void Update(float gain, int num_saturations); + float GetGain() const { return saturating_gain_; } + + private: + float saturating_gain_; + int saturating_gain_hold_counter_; + + RTC_DISALLOW_COPY_AND_ASSIGN(SaturatingGainEstimator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SATURATING_GAIN_ESTIMATOR_H_ diff --git a/include/webrtc/modules/audio_processing/level_controller/signal_classifier.h b/include/webrtc/modules/audio_processing/level_controller/signal_classifier.h new file mode 100644 index 0000000..8c791fe --- /dev/null +++ b/include/webrtc/modules/audio_processing/level_controller/signal_classifier.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SIGNAL_CLASSIFIER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SIGNAL_CLASSIFIER_H_ + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/audio_processing/level_controller/down_sampler.h" +#include "webrtc/modules/audio_processing/level_controller/noise_spectrum_estimator.h" +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" + +namespace webrtc { + +class ApmDataDumper; +class AudioBuffer; + +class SignalClassifier { + public: + enum class SignalType { kHighlyNonStationary, kNonStationary, kStationary }; + + explicit SignalClassifier(ApmDataDumper* data_dumper); + ~SignalClassifier(); + + void Initialize(int sample_rate_hz); + void Analyze(const AudioBuffer& audio, SignalType* signal_type); + + private: + class FrameExtender { + public: + FrameExtender(size_t frame_size, size_t extended_frame_size); + ~FrameExtender(); + + void ExtendFrame(rtc::ArrayView x, + rtc::ArrayView x_extended); + + private: + std::vector x_old_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameExtender); + }; + + ApmDataDumper* const data_dumper_; + DownSampler down_sampler_; + std::unique_ptr frame_extender_; + NoiseSpectrumEstimator noise_spectrum_estimator_; + int sample_rate_hz_; + int initialization_frames_left_; + int consistent_classification_counter_; + SignalType last_signal_type_; + const OouraFft ooura_fft_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SignalClassifier); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LEVEL_CONTROLLER_SIGNAL_CLASSIFIER_H_ diff --git a/include/webrtc/modules/audio_processing/level_estimator_impl.h b/include/webrtc/modules/audio_processing/level_estimator_impl.h index df43c9b..11dbdbe 100644 --- a/include/webrtc/modules/audio_processing/level_estimator_impl.h +++ b/include/webrtc/modules/audio_processing/level_estimator_impl.h @@ -20,7 +20,7 @@ namespace webrtc { class AudioBuffer; -class RMSLevel; +class RmsLevel; class LevelEstimatorImpl : public LevelEstimator { public: @@ -39,7 +39,7 @@ class LevelEstimatorImpl : public LevelEstimator { private: rtc::CriticalSection* const crit_ = nullptr; bool enabled_ GUARDED_BY(crit_) = false; - std::unique_ptr rms_ GUARDED_BY(crit_); + std::unique_ptr rms_ GUARDED_BY(crit_); RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(LevelEstimatorImpl); }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/logging/apm_data_dumper.h b/include/webrtc/modules/audio_processing/logging/apm_data_dumper.h index 93232b7..e342fab 100644 --- a/include/webrtc/modules/audio_processing/logging/apm_data_dumper.h +++ b/include/webrtc/modules/audio_processing/logging/apm_data_dumper.h @@ -22,14 +22,14 @@ #include "webrtc/common_audio/wav_file.h" // Check to verify that the define is properly set. -#if !defined(WEBRTC_AEC_DEBUG_DUMP) || \ - (WEBRTC_AEC_DEBUG_DUMP != 0 && WEBRTC_AEC_DEBUG_DUMP != 1) -#error "Set WEBRTC_AEC_DEBUG_DUMP to either 0 or 1" +#if !defined(WEBRTC_APM_DEBUG_DUMP) || \ + (WEBRTC_APM_DEBUG_DUMP != 0 && WEBRTC_APM_DEBUG_DUMP != 1) +#error "Set WEBRTC_APM_DEBUG_DUMP to either 0 or 1" #endif namespace webrtc { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 // Functor used to use as a custom deleter in the map of file pointers to raw // files. struct RawFileCloseFunctor { @@ -40,78 +40,161 @@ struct RawFileCloseFunctor { // Class that handles dumping of variables into files. class ApmDataDumper { public: -// Constructor that takes an instance index that may -// be used to distinguish data dumped from different -// instances of the code. -#if WEBRTC_AEC_DEBUG_DUMP == 1 - explicit ApmDataDumper(int instance_index) - : instance_index_(instance_index) {} -#else - explicit ApmDataDumper(int instance_index) {} -#endif + // Constructor that takes an instance index that may + // be used to distinguish data dumped from different + // instances of the code. + explicit ApmDataDumper(int instance_index); + + ~ApmDataDumper(); // Reinitializes the data dumping such that new versions // of all files being dumped to are created. void InitiateNewSetOfRecordings() { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 ++recording_set_index_; #endif } // Methods for performing dumping of data of various types into // various formats. - void DumpRaw(const char* name, int v_length, const float* v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 + void DumpRaw(const char* name, double v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(&v, sizeof(v), 1, file); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const double* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(v, sizeof(v[0]), v_length, file); +#endif + } + + void DumpRaw(const char* name, rtc::ArrayView v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + DumpRaw(name, v.size(), v.data()); +#endif + } + + void DumpRaw(const char* name, float v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(&v, sizeof(v), 1, file); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const float* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 FILE* file = GetRawFile(name); fwrite(v, sizeof(v[0]), v_length, file); #endif } void DumpRaw(const char* name, rtc::ArrayView v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 DumpRaw(name, v.size(), v.data()); #endif } - void DumpRaw(const char* name, int v_length, const int16_t* v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 + void DumpRaw(const char* name, bool v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + DumpRaw(name, static_cast(v)); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const bool* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + for (size_t k = 0; k < v_length; ++k) { + int16_t value = static_cast(v[k]); + fwrite(&value, sizeof(value), 1, file); + } +#endif + } + + void DumpRaw(const char* name, rtc::ArrayView v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + DumpRaw(name, v.size(), v.data()); +#endif + } + + void DumpRaw(const char* name, int16_t v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(&v, sizeof(v), 1, file); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const int16_t* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 FILE* file = GetRawFile(name); fwrite(v, sizeof(v[0]), v_length, file); #endif } void DumpRaw(const char* name, rtc::ArrayView v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 DumpRaw(name, v.size(), v.data()); #endif } - void DumpRaw(const char* name, int v_length, const int32_t* v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 + void DumpRaw(const char* name, int32_t v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(&v, sizeof(v), 1, file); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const int32_t* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(v, sizeof(v[0]), v_length, file); +#endif + } + + void DumpRaw(const char* name, size_t v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + FILE* file = GetRawFile(name); + fwrite(&v, sizeof(v), 1, file); +#endif + } + + void DumpRaw(const char* name, size_t v_length, const size_t* v) { +#if WEBRTC_APM_DEBUG_DUMP == 1 FILE* file = GetRawFile(name); fwrite(v, sizeof(v[0]), v_length, file); #endif } void DumpRaw(const char* name, rtc::ArrayView v) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 DumpRaw(name, v.size(), v.data()); #endif } void DumpWav(const char* name, - int v_length, + size_t v_length, const float* v, int sample_rate_hz, int num_channels) { -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels); file->WriteSamples(v, v_length); #endif } + void DumpWav(const char* name, + rtc::ArrayView v, + int sample_rate_hz, + int num_channels) { +#if WEBRTC_APM_DEBUG_DUMP == 1 + DumpWav(name, v.size(), v.data(), sample_rate_hz, num_channels); +#endif + } + private: -#if WEBRTC_AEC_DEBUG_DUMP == 1 +#if WEBRTC_APM_DEBUG_DUMP == 1 const int instance_index_; int recording_set_index_ = 0; std::unordered_map> diff --git a/include/webrtc/modules/audio_processing/low_cut_filter.h b/include/webrtc/modules/audio_processing/low_cut_filter.h new file mode 100644 index 0000000..3a4da71 --- /dev/null +++ b/include/webrtc/modules/audio_processing/low_cut_filter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_LOW_CUT_FILTER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_LOW_CUT_FILTER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class AudioBuffer; + +class LowCutFilter { + public: + LowCutFilter(size_t channels, int sample_rate_hz); + ~LowCutFilter(); + void Process(AudioBuffer* audio); + + private: + class BiquadFilter; + std::vector> filters_; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(LowCutFilter); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_LOW_CUT_FILTER_H_ diff --git a/include/webrtc/modules/audio_processing/residual_echo_detector.h b/include/webrtc/modules/audio_processing/residual_echo_detector.h new file mode 100644 index 0000000..ba0d0d3 --- /dev/null +++ b/include/webrtc/modules/audio_processing/residual_echo_detector.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_RESIDUAL_ECHO_DETECTOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_RESIDUAL_ECHO_DETECTOR_H_ + +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/modules/audio_processing/echo_detector/circular_buffer.h" +#include "webrtc/modules/audio_processing/echo_detector/mean_variance_estimator.h" +#include "webrtc/modules/audio_processing/echo_detector/moving_max.h" +#include "webrtc/modules/audio_processing/echo_detector/normalized_covariance_estimator.h" + +namespace webrtc { + +class AudioBuffer; +class EchoDetector; + +class ResidualEchoDetector { + public: + ResidualEchoDetector(); + ~ResidualEchoDetector(); + + // This function should be called while holding the render lock. + void AnalyzeRenderAudio(rtc::ArrayView render_audio); + + // This function should be called while holding the capture lock. + void AnalyzeCaptureAudio(rtc::ArrayView capture_audio); + + // This function should be called while holding the capture lock. + void Initialize(); + + // This function is for testing purposes only. + void SetReliabilityForTest(float value) { reliability_ = value; } + + static void PackRenderAudioBuffer(AudioBuffer* audio, + std::vector* packed_buffer); + + // This function should be called while holding the capture lock. + float echo_likelihood() const { return echo_likelihood_; } + + float echo_likelihood_recent_max() const { + return recent_likelihood_max_.max(); + } + + private: + // Keep track if the |Process| function has been previously called. + bool first_process_call_ = true; + // Buffer for storing the power of incoming farend buffers. This is needed for + // cases where calls to BufferFarend and Process are jittery. + CircularBuffer render_buffer_; + // Count how long ago it was that the size of |render_buffer_| was zero. This + // value is also reset to zero when clock drift is detected and a value from + // the renderbuffer is discarded, even though the buffer is not actually zero + // at that point. This is done to avoid repeatedly removing elements in this + // situation. + size_t frames_since_zero_buffer_size_ = 0; + + // Circular buffers containing delayed versions of the power, mean and + // standard deviation, for calculating the delayed covariance values. + std::vector render_power_; + std::vector render_power_mean_; + std::vector render_power_std_dev_; + // Covariance estimates for different delay values. + std::vector covariances_; + // Index where next element should be inserted in all of the above circular + // buffers. + size_t next_insertion_index_ = 0; + + MeanVarianceEstimator render_statistics_; + MeanVarianceEstimator capture_statistics_; + // Current echo likelihood. + float echo_likelihood_ = 0.f; + // Reliability of the current likelihood. + float reliability_ = 0.f; + MovingMax recent_likelihood_max_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_RESIDUAL_ECHO_DETECTOR_H_ diff --git a/include/webrtc/modules/audio_processing/rms_level.h b/include/webrtc/modules/audio_processing/rms_level.h index 12fa212..a186bcf 100644 --- a/include/webrtc/modules/audio_processing/rms_level.h +++ b/include/webrtc/modules/audio_processing/rms_level.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_RMS_LEVEL_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_RMS_LEVEL_H_ -#include - +#include "webrtc/base/array_view.h" +#include "webrtc/base/optional.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -23,34 +23,50 @@ namespace webrtc { // with the intent that it can provide the RTP audio level indication. // // The expected approach is to provide constant-sized chunks of audio to -// Process(). When enough chunks have been accumulated to form a packet, call -// RMS() to get the audio level indicator for the RTP header. -class RMSLevel { +// Analyze(). When enough chunks have been accumulated to form a packet, call +// Average() to get the audio level indicator for the RTP header. +class RmsLevel { public: - static const int kMinLevel = 127; + struct Levels { + int average; + int peak; + }; + + static constexpr int kMinLevelDb = 127; - RMSLevel(); - ~RMSLevel(); + RmsLevel(); + ~RmsLevel(); // Can be called to reset internal states, but is not required during normal // operation. void Reset(); - // Pass each chunk of audio to Process() to accumulate the level. - void Process(const int16_t* data, size_t length); + // Pass each chunk of audio to Analyze() to accumulate the level. + void Analyze(rtc::ArrayView data); // If all samples with the given |length| have a magnitude of zero, this is // a shortcut to avoid some computation. - void ProcessMuted(size_t length); + void AnalyzeMuted(size_t length); - // Computes the RMS level over all data passed to Process() since the last - // call to RMS(). The returned value is positive but should be interpreted as - // negative as per the RFC. It is constrained to [0, 127]. - int RMS(); + // Computes the RMS level over all data passed to Analyze() since the last + // call to Average(). The returned value is positive but should be interpreted + // as negative as per the RFC. It is constrained to [0, 127]. Resets the + // internal state to start a new measurement period. + int Average(); + + // Like Average() above, but also returns the RMS peak value. Resets the + // internal state to start a new measurement period. + Levels AverageAndPeak(); private: + // Compares |block_size| with |block_size_|. If they are different, calls + // Reset() and stores the new size. + void CheckBlockSize(size_t block_size); + float sum_square_; size_t sample_count_; + float max_sum_square_; + rtc::Optional block_size_; }; } // namespace webrtc diff --git a/include/webrtc/modules/audio_processing/splitting_filter.h b/include/webrtc/modules/audio_processing/splitting_filter.h index 2828df3..2d3750a 100644 --- a/include/webrtc/modules/audio_processing/splitting_filter.h +++ b/include/webrtc/modules/audio_processing/splitting_filter.h @@ -46,6 +46,7 @@ struct TwoBandsStates { class SplittingFilter { public: SplittingFilter(size_t num_channels, size_t num_bands, size_t num_frames); + ~SplittingFilter(); void Analysis(const IFChannelBuffer* data, IFChannelBuffer* bands); void Synthesis(const IFChannelBuffer* bands, IFChannelBuffer* data); diff --git a/include/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h b/include/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h new file mode 100644 index 0000000..5f7d138 --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/aec_dump_based_simulator.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AEC_DUMP_BASED_SIMULATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AEC_DUMP_BASED_SIMULATOR_H_ + +#include "webrtc/modules/audio_processing/test/audio_processing_simulator.h" + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/ignore_wundef.h" + +RTC_PUSH_IGNORING_WUNDEF() +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" +#else +#include "webrtc/modules/audio_processing/debug.pb.h" +#endif +RTC_POP_IGNORING_WUNDEF() + +namespace webrtc { +namespace test { + +// Used to perform an audio processing simulation from an aec dump. +class AecDumpBasedSimulator final : public AudioProcessingSimulator { + public: + explicit AecDumpBasedSimulator(const SimulationSettings& settings); + ~AecDumpBasedSimulator() override; + + // Processes the messages in the aecdump file. + void Process() override; + + private: + void HandleMessage(const webrtc::audioproc::Init& msg); + void HandleMessage(const webrtc::audioproc::Stream& msg); + void HandleMessage(const webrtc::audioproc::ReverseStream& msg); + void HandleMessage(const webrtc::audioproc::Config& msg); + void PrepareProcessStreamCall(const webrtc::audioproc::Stream& msg, + bool* set_stream_analog_level_called); + void PrepareReverseProcessStreamCall( + const webrtc::audioproc::ReverseStream& msg); + void VerifyProcessStreamBitExactness(const webrtc::audioproc::Stream& msg); + + enum InterfaceType { + kFixedInterface, + kFloatInterface, + kNotSpecified, + }; + + FILE* dump_input_file_; + std::unique_ptr> artificial_nearend_buf_; + std::unique_ptr artificial_nearend_buffer_reader_; + bool artificial_nearend_eof_reported_ = false; + InterfaceType interface_used_ = InterfaceType::kNotSpecified; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AecDumpBasedSimulator); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AEC_DUMP_BASED_SIMULATOR_H_ diff --git a/include/webrtc/modules/audio_processing/test/audio_file_processor.h b/include/webrtc/modules/audio_processing/test/audio_file_processor.h deleted file mode 100644 index 76d5e0e..0000000 --- a/include/webrtc/modules/audio_processing/test/audio_file_processor.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_FILE_PROCESSOR_H_ -#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_FILE_PROCESSOR_H_ - -#include -#include -#include -#include - -#include "webrtc/base/timeutils.h" -#include "webrtc/common_audio/channel_buffer.h" -#include "webrtc/common_audio/wav_file.h" -#include "webrtc/modules/audio_processing/include/audio_processing.h" -#include "webrtc/modules/audio_processing/test/test_utils.h" - -#ifdef WEBRTC_ANDROID_PLATFORM_BUILD -#include "external/webrtc/webrtc/modules/audio_processing/debug.pb.h" -#else -#include "webrtc/modules/audio_processing/debug.pb.h" -#endif - -namespace webrtc { - -// Holds a few statistics about a series of TickIntervals. -struct TickIntervalStats { - TickIntervalStats() : min(std::numeric_limits::max()) {} - int64_t sum; - int64_t max; - int64_t min; -}; - -// Interface for processing an input file with an AudioProcessing instance and -// dumping the results to an output file. -class AudioFileProcessor { - public: - static const int kChunksPerSecond = 1000 / AudioProcessing::kChunkSizeMs; - - virtual ~AudioFileProcessor() {} - - // Processes one AudioProcessing::kChunkSizeMs of data from the input file and - // writes to the output file. - virtual bool ProcessChunk() = 0; - - // Returns the execution time of all AudioProcessing calls. - const TickIntervalStats& proc_time() const { return proc_time_; } - - protected: - // RAII class for execution time measurement. Updates the provided - // TickIntervalStats based on the time between ScopedTimer creation and - // leaving the enclosing scope. - class ScopedTimer { - public: - explicit ScopedTimer(TickIntervalStats* proc_time) - : proc_time_(proc_time), start_time_(rtc::TimeNanos()) {} - - ~ScopedTimer() { - int64_t interval = rtc::TimeNanos() - start_time_; - proc_time_->sum += interval; - proc_time_->max = std::max(proc_time_->max, interval); - proc_time_->min = std::min(proc_time_->min, interval); - } - - private: - TickIntervalStats* const proc_time_; - int64_t start_time_; - }; - - TickIntervalStats* mutable_proc_time() { return &proc_time_; } - - private: - TickIntervalStats proc_time_; -}; - -// Used to read from and write to WavFile objects. -class WavFileProcessor final : public AudioFileProcessor { - public: - // Takes ownership of all parameters. - WavFileProcessor(std::unique_ptr ap, - std::unique_ptr in_file, - std::unique_ptr out_file, - std::unique_ptr reverse_in_file, - std::unique_ptr reverse_out_file); - virtual ~WavFileProcessor() {} - - // Processes one chunk from the WAV input and writes to the WAV output. - bool ProcessChunk() override; - - private: - std::unique_ptr ap_; - - ChannelBuffer in_buf_; - ChannelBuffer out_buf_; - const StreamConfig input_config_; - const StreamConfig output_config_; - ChannelBufferWavReader buffer_reader_; - ChannelBufferWavWriter buffer_writer_; - std::unique_ptr> reverse_in_buf_; - std::unique_ptr> reverse_out_buf_; - std::unique_ptr reverse_input_config_; - std::unique_ptr reverse_output_config_; - std::unique_ptr reverse_buffer_reader_; - std::unique_ptr reverse_buffer_writer_; -}; - -// Used to read from an aecdump file and write to a WavWriter. -class AecDumpFileProcessor final : public AudioFileProcessor { - public: - // Takes ownership of all parameters. - AecDumpFileProcessor(std::unique_ptr ap, - FILE* dump_file, - std::unique_ptr out_file); - - virtual ~AecDumpFileProcessor(); - - // Processes messages from the aecdump file until the first Stream message is - // completed. Passes other data from the aecdump messages as appropriate. - bool ProcessChunk() override; - - private: - void HandleMessage(const webrtc::audioproc::Init& msg); - void HandleMessage(const webrtc::audioproc::Stream& msg); - void HandleMessage(const webrtc::audioproc::ReverseStream& msg); - - std::unique_ptr ap_; - FILE* dump_file_; - - std::unique_ptr> in_buf_; - std::unique_ptr> reverse_buf_; - ChannelBuffer out_buf_; - StreamConfig input_config_; - StreamConfig reverse_config_; - const StreamConfig output_config_; - ChannelBufferWavWriter buffer_writer_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_FILE_PROCESSOR_H_ diff --git a/include/webrtc/modules/audio_processing/test/audio_processing_simulator.h b/include/webrtc/modules/audio_processing/test/audio_processing_simulator.h new file mode 100644 index 0000000..f597fa1 --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/audio_processing_simulator.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_ + +#include +#include +#include +#include +#include + +#include "webrtc/base/timeutils.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/common_audio/channel_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/modules/audio_processing/test/test_utils.h" + +namespace webrtc { +namespace test { + +// Holds all the parameters available for controlling the simulation. +struct SimulationSettings { + SimulationSettings(); + SimulationSettings(const SimulationSettings&); + ~SimulationSettings(); + rtc::Optional stream_delay; + rtc::Optional stream_drift_samples; + rtc::Optional output_sample_rate_hz; + rtc::Optional output_num_channels; + rtc::Optional reverse_output_sample_rate_hz; + rtc::Optional reverse_output_num_channels; + rtc::Optional microphone_positions; + int target_angle_degrees = 90; + rtc::Optional output_filename; + rtc::Optional reverse_output_filename; + rtc::Optional input_filename; + rtc::Optional reverse_input_filename; + rtc::Optional artificial_nearend_filename; + rtc::Optional use_aec; + rtc::Optional use_aecm; + rtc::Optional use_ed; // Residual Echo Detector. + rtc::Optional ed_graph_output_filename; + rtc::Optional use_agc; + rtc::Optional use_hpf; + rtc::Optional use_ns; + rtc::Optional use_ts; + rtc::Optional use_bf; + rtc::Optional use_ie; + rtc::Optional use_vad; + rtc::Optional use_le; + rtc::Optional use_all; + rtc::Optional aec_suppression_level; + rtc::Optional use_delay_agnostic; + rtc::Optional use_extended_filter; + rtc::Optional use_drift_compensation; + rtc::Optional use_aec3; + rtc::Optional use_lc; + rtc::Optional use_experimental_agc; + rtc::Optional aecm_routing_mode; + rtc::Optional use_aecm_comfort_noise; + rtc::Optional agc_mode; + rtc::Optional agc_target_level; + rtc::Optional use_agc_limiter; + rtc::Optional agc_compression_gain; + rtc::Optional vad_likelihood; + rtc::Optional ns_level; + rtc::Optional use_refined_adaptive_filter; + bool report_performance = false; + bool report_bitexactness = false; + bool use_verbose_logging = false; + bool discard_all_settings_in_aecdump = true; + rtc::Optional aec_dump_input_filename; + rtc::Optional aec_dump_output_filename; + bool fixed_interface = false; + bool store_intermediate_output = false; + rtc::Optional custom_call_order_filename; +}; + +// Holds a few statistics about a series of TickIntervals. +struct TickIntervalStats { + TickIntervalStats() : min(std::numeric_limits::max()) {} + int64_t sum; + int64_t max; + int64_t min; +}; + +// Copies samples present in a ChannelBuffer into an AudioFrame. +void CopyToAudioFrame(const ChannelBuffer& src, AudioFrame* dest); + +// Provides common functionality for performing audioprocessing simulations. +class AudioProcessingSimulator { + public: + static const int kChunksPerSecond = 1000 / AudioProcessing::kChunkSizeMs; + + explicit AudioProcessingSimulator(const SimulationSettings& settings); + virtual ~AudioProcessingSimulator(); + + // Processes the data in the input. + virtual void Process() = 0; + + // Returns the execution time of all AudioProcessing calls. + const TickIntervalStats& proc_time() const { return proc_time_; } + + // Reports whether the processed recording was bitexact. + bool OutputWasBitexact() { return bitexact_output_; } + + size_t get_num_process_stream_calls() { return num_process_stream_calls_; } + size_t get_num_reverse_process_stream_calls() { + return num_reverse_process_stream_calls_; + } + + protected: + // RAII class for execution time measurement. Updates the provided + // TickIntervalStats based on the time between ScopedTimer creation and + // leaving the enclosing scope. + class ScopedTimer { + public: + explicit ScopedTimer(TickIntervalStats* proc_time) + : proc_time_(proc_time), start_time_(rtc::TimeNanos()) {} + + ~ScopedTimer(); + + private: + TickIntervalStats* const proc_time_; + int64_t start_time_; + }; + + TickIntervalStats* mutable_proc_time() { return &proc_time_; } + void ProcessStream(bool fixed_interface); + void ProcessReverseStream(bool fixed_interface); + void CreateAudioProcessor(); + void DestroyAudioProcessor(); + void SetupBuffersConfigsOutputs(int input_sample_rate_hz, + int output_sample_rate_hz, + int reverse_input_sample_rate_hz, + int reverse_output_sample_rate_hz, + int input_num_channels, + int output_num_channels, + int reverse_input_num_channels, + int reverse_output_num_channels); + + const SimulationSettings settings_; + std::unique_ptr ap_; + + std::unique_ptr> in_buf_; + std::unique_ptr> out_buf_; + std::unique_ptr> reverse_in_buf_; + std::unique_ptr> reverse_out_buf_; + StreamConfig in_config_; + StreamConfig out_config_; + StreamConfig reverse_in_config_; + StreamConfig reverse_out_config_; + std::unique_ptr buffer_reader_; + std::unique_ptr reverse_buffer_reader_; + AudioFrame rev_frame_; + AudioFrame fwd_frame_; + bool bitexact_output_ = true; + + private: + void SetupOutput(); + + size_t num_process_stream_calls_ = 0; + size_t num_reverse_process_stream_calls_ = 0; + size_t output_reset_counter_ = 0; + std::unique_ptr buffer_writer_; + std::unique_ptr reverse_buffer_writer_; + TickIntervalStats proc_time_; + std::ofstream residual_echo_likelihood_graph_writer_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioProcessingSimulator); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_AUDIO_PROCESSING_SIMULATOR_H_ diff --git a/include/webrtc/modules/audio_processing/test/bitexactness_tools.h b/include/webrtc/modules/audio_processing/test/bitexactness_tools.h index d4c09d4..4ddc7e3 100644 --- a/include/webrtc/modules/audio_processing/test/bitexactness_tools.h +++ b/include/webrtc/modules/audio_processing/test/bitexactness_tools.h @@ -16,7 +16,7 @@ #include "webrtc/base/array_view.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" -#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/test/gtest.h" namespace webrtc { namespace test { diff --git a/include/webrtc/modules/audio_processing/test/debug_dump_replayer.h b/include/webrtc/modules/audio_processing/test/debug_dump_replayer.h index 0902254..3bf886c 100644 --- a/include/webrtc/modules/audio_processing/test/debug_dump_replayer.h +++ b/include/webrtc/modules/audio_processing/test/debug_dump_replayer.h @@ -14,10 +14,14 @@ #include #include +#include "webrtc/base/ignore_wundef.h" #include "webrtc/common_audio/channel_buffer.h" -#include "webrtc/modules/audio_processing/debug.pb.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" +RTC_PUSH_IGNORING_WUNDEF() +#include "webrtc/modules/audio_processing/debug.pb.h" +RTC_POP_IGNORING_WUNDEF() + namespace webrtc { namespace test { diff --git a/include/webrtc/modules/audio_processing/test/echo_canceller_test_tools.h b/include/webrtc/modules/audio_processing/test/echo_canceller_test_tools.h new file mode 100644 index 0000000..59e1cad --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/echo_canceller_test_tools.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_ECHO_CANCELLER_TEST_TOOLS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_ECHO_CANCELLER_TEST_TOOLS_H_ + +#include +#include + +#include "webrtc/base/array_view.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/random.h" + +namespace webrtc { + +// Randomizes the elements in a vector with values -32767.f:32767.f. +void RandomizeSampleVector(Random* random_generator, rtc::ArrayView v); + +// Class for delaying a signal a fixed number of samples. +template +class DelayBuffer { + public: + explicit DelayBuffer(size_t delay) : buffer_(delay) {} + ~DelayBuffer() = default; + + // Produces a delayed signal copy of x. + void Delay(rtc::ArrayView x, rtc::ArrayView x_delayed); + + private: + std::vector buffer_; + size_t next_insert_index_ = 0; + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayBuffer); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_ECHO_CANCELLER_TEST_TOOLS_H_ diff --git a/include/webrtc/modules/audio_processing/test/performance_timer.h b/include/webrtc/modules/audio_processing/test/performance_timer.h new file mode 100644 index 0000000..5921fae --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/performance_timer.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_PERFORMANCE_TIMER_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_PERFORMANCE_TIMER_H_ + +#include + +#include "webrtc/base/optional.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { +namespace test { + +class PerformanceTimer { + public: + explicit PerformanceTimer(int num_frames_to_process); + ~PerformanceTimer(); + + void StartTimer(); + void StopTimer(); + + double GetDurationAverage() const; + double GetDurationStandardDeviation() const; + + private: + webrtc::Clock* clock_; + rtc::Optional start_timestamp_us_; + std::vector timestamps_us_; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_PERFORMANCE_TIMER_H_ diff --git a/include/webrtc/modules/audio_processing/test/protobuf_utils.h b/include/webrtc/modules/audio_processing/test/protobuf_utils.h index 3ab90b7..e132c94 100644 --- a/include/webrtc/modules/audio_processing/test/protobuf_utils.h +++ b/include/webrtc/modules/audio_processing/test/protobuf_utils.h @@ -13,7 +13,11 @@ #include +#include "webrtc/base/ignore_wundef.h" + +RTC_PUSH_IGNORING_WUNDEF() #include "webrtc/modules/audio_processing/debug.pb.h" +RTC_POP_IGNORING_WUNDEF() namespace webrtc { diff --git a/include/webrtc/modules/audio_processing/test/simulator_buffers.h b/include/webrtc/modules/audio_processing/test/simulator_buffers.h new file mode 100644 index 0000000..9dff1e6 --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/simulator_buffers.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_SIMULATOR_BUFFERS_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_SIMULATOR_BUFFERS_H_ + +#include +#include + +#include "webrtc/base/random.h" +#include "webrtc/modules/audio_processing/audio_buffer.h" +#include "webrtc/modules/audio_processing/include/audio_processing.h" + +namespace webrtc { +namespace test { + +struct SimulatorBuffers { + SimulatorBuffers(int render_input_sample_rate_hz, + int capture_input_sample_rate_hz, + int render_output_sample_rate_hz, + int capture_output_sample_rate_hz, + size_t num_render_input_channels, + size_t num_capture_input_channels, + size_t num_render_output_channels, + size_t num_capture_output_channels); + ~SimulatorBuffers(); + + void CreateConfigAndBuffer(int sample_rate_hz, + size_t num_channels, + Random* rand_gen, + std::unique_ptr* buffer, + StreamConfig* config, + std::vector* buffer_data, + std::vector* buffer_data_samples); + + void UpdateInputBuffers(); + + std::unique_ptr render_input_buffer; + std::unique_ptr capture_input_buffer; + std::unique_ptr render_output_buffer; + std::unique_ptr capture_output_buffer; + StreamConfig render_input_config; + StreamConfig capture_input_config; + StreamConfig render_output_config; + StreamConfig capture_output_config; + std::vector render_input; + std::vector render_input_samples; + std::vector capture_input; + std::vector capture_input_samples; + std::vector render_output; + std::vector render_output_samples; + std::vector capture_output; + std::vector capture_output_samples; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_SIMULATOR_BUFFERS_H_ diff --git a/include/webrtc/modules/audio_processing/test/test_utils.h b/include/webrtc/modules/audio_processing/test/test_utils.h index 5de67cf..ca66520 100644 --- a/include/webrtc/modules/audio_processing/test/test_utils.h +++ b/include/webrtc/modules/audio_processing/test/test_utils.h @@ -47,6 +47,7 @@ class RawFile final { class ChannelBufferWavReader final { public: explicit ChannelBufferWavReader(std::unique_ptr file); + ~ChannelBufferWavReader(); // Reads data from the file according to the |buffer| format. Returns false if // a full buffer can't be read from the file. @@ -63,6 +64,8 @@ class ChannelBufferWavReader final { class ChannelBufferWavWriter final { public: explicit ChannelBufferWavWriter(std::unique_ptr file); + ~ChannelBufferWavWriter(); + void Write(const ChannelBuffer& buffer); private: diff --git a/include/webrtc/modules/audio_processing/test/wav_based_simulator.h b/include/webrtc/modules/audio_processing/test/wav_based_simulator.h new file mode 100644 index 0000000..c1fcf61 --- /dev/null +++ b/include/webrtc/modules/audio_processing/test/wav_based_simulator.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_TEST_WAV_BASED_SIMULATOR_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_TEST_WAV_BASED_SIMULATOR_H_ + +#include + +#include "webrtc/modules/audio_processing/test/audio_processing_simulator.h" + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { +namespace test { + +// Used to perform an audio processing simulation from wav files. +class WavBasedSimulator final : public AudioProcessingSimulator { + public: + explicit WavBasedSimulator(const SimulationSettings& settings); + ~WavBasedSimulator() override; + + // Processes the WAV input. + void Process() override; + + private: + enum SimulationEventType { + kProcessStream, + kProcessReverseStream, + }; + + void Initialize(); + bool HandleProcessStreamCall(); + bool HandleProcessReverseStreamCall(); + void PrepareProcessStreamCall(); + void PrepareReverseProcessStreamCall(); + static std::vector GetDefaultEventChain(); + static std::vector GetCustomEventChain( + const std::string& filename); + + std::vector call_chain_; + int last_specified_microphone_level_ = 100; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WavBasedSimulator); +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_TEST_WAV_BASED_SIMULATOR_H_ diff --git a/include/webrtc/modules/audio_processing/three_band_filter_bank.h b/include/webrtc/modules/audio_processing/three_band_filter_bank.h index eb9b99e..24e7831 100644 --- a/include/webrtc/modules/audio_processing/three_band_filter_bank.h +++ b/include/webrtc/modules/audio_processing/three_band_filter_bank.h @@ -35,6 +35,7 @@ namespace webrtc { class ThreeBandFilterBank final { public: explicit ThreeBandFilterBank(size_t length); + ~ThreeBandFilterBank(); // Splits |in| into 3 downsampled frequency bands in |out|. // |length| is the |in| length. Each of the 3 bands of |out| has to have a diff --git a/include/webrtc/modules/audio_processing/utility/ooura_fft.h b/include/webrtc/modules/audio_processing/utility/ooura_fft.h new file mode 100644 index 0000000..a1b9f04 --- /dev/null +++ b/include/webrtc/modules/audio_processing/utility/ooura_fft.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_H_ + +#include "webrtc/typedefs.h" + +namespace webrtc { + +#if defined(WEBRTC_ARCH_X86_FAMILY) +void cft1st_128_SSE2(float* a); +void cftmdl_128_SSE2(float* a); +void rftfsub_128_SSE2(float* a); +void rftbsub_128_SSE2(float* a); +#endif + +#if defined(MIPS_FPU_LE) +void cft1st_128_mips(float* a); +void cftmdl_128_mips(float* a); +void rftfsub_128_mips(float* a); +void rftbsub_128_mips(float* a); +#endif + +#if defined(WEBRTC_HAS_NEON) +void cft1st_128_neon(float* a); +void cftmdl_128_neon(float* a); +void rftfsub_128_neon(float* a); +void rftbsub_128_neon(float* a); +#endif + +class OouraFft { + public: + OouraFft(); + ~OouraFft(); + void Fft(float* a) const; + void InverseFft(float* a) const; + + private: + void cft1st_128(float* a) const; + void cftmdl_128(float* a) const; + void rftfsub_128(float* a) const; + void rftbsub_128(float* a) const; + + void cftfsub_128(float* a) const; + void cftbsub_128(float* a) const; + void bitrv2_128(float* a) const; + bool use_sse2_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_H_ diff --git a/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_common.h b/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_common.h new file mode 100644 index 0000000..548027c --- /dev/null +++ b/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_common.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_COMMON_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_COMMON_H_ + +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" + +namespace webrtc { + +// This tables used to be computed at run-time. For example, refer to: +// https://code.google.com/p/webrtc/source/browse/trunk/webrtc/modules/audio_processing/utility/apm_rdft.c?r=6564 +// to see the initialization code. +// Constants shared by all paths (C, SSE2, NEON). +const float rdft_w[64] = { + 1.0000000000f, 0.0000000000f, 0.7071067691f, 0.7071067691f, 0.9238795638f, + 0.3826834559f, 0.3826834559f, 0.9238795638f, 0.9807852507f, 0.1950903237f, + 0.5555702448f, 0.8314695954f, 0.8314695954f, 0.5555702448f, 0.1950903237f, + 0.9807852507f, 0.9951847196f, 0.0980171412f, 0.6343933344f, 0.7730104327f, + 0.8819212914f, 0.4713967443f, 0.2902846634f, 0.9569403529f, 0.9569403529f, + 0.2902846634f, 0.4713967443f, 0.8819212914f, 0.7730104327f, 0.6343933344f, + 0.0980171412f, 0.9951847196f, 0.7071067691f, 0.4993977249f, 0.4975923598f, + 0.4945882559f, 0.4903926253f, 0.4850156307f, 0.4784701765f, 0.4707720280f, + 0.4619397819f, 0.4519946277f, 0.4409606457f, 0.4288643003f, 0.4157347977f, + 0.4016037583f, 0.3865052164f, 0.3704755902f, 0.3535533845f, 0.3357794881f, + 0.3171966672f, 0.2978496552f, 0.2777851224f, 0.2570513785f, 0.2356983721f, + 0.2137775421f, 0.1913417280f, 0.1684449315f, 0.1451423317f, 0.1214900985f, + 0.0975451618f, 0.0733652338f, 0.0490085706f, 0.0245338380f, +}; + +// Constants used by the C and MIPS paths. +const float rdft_wk3ri_first[16] = { + 1.000000000f, 0.000000000f, 0.382683456f, 0.923879564f, + 0.831469536f, 0.555570245f, -0.195090353f, 0.980785251f, + 0.956940353f, 0.290284693f, 0.098017156f, 0.995184720f, + 0.634393334f, 0.773010492f, -0.471396863f, 0.881921172f, +}; +const float rdft_wk3ri_second[16] = { + -0.707106769f, 0.707106769f, -0.923879564f, -0.382683456f, + -0.980785251f, 0.195090353f, -0.555570245f, -0.831469536f, + -0.881921172f, 0.471396863f, -0.773010492f, -0.634393334f, + -0.995184720f, -0.098017156f, -0.290284693f, -0.956940353f, +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_COMMON_H_ diff --git a/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h b/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h new file mode 100644 index 0000000..1ed646d --- /dev/null +++ b/include/webrtc/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_NEON_SSE2_H_ +#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_NEON_SSE2_H_ + +#include "webrtc/modules/audio_processing/utility/ooura_fft.h" + +#ifdef _MSC_VER /* visual c++ */ +#define ALIGN16_BEG __declspec(align(16)) +#define ALIGN16_END +#else /* gcc or icc */ +#define ALIGN16_BEG +#define ALIGN16_END __attribute__((aligned(16))) +#endif + +namespace webrtc { + +// These tables used to be computed at run-time. For example, refer to: +// https://code.google.com/p/webrtc/source/browse/trunk/webrtc/modules/audio_processing/utility/apm_rdft.c?r=6564 +// to see the initialization code. +#if defined(WEBRTC_ARCH_X86_FAMILY) || defined(WEBRTC_HAS_NEON) +// Constants used by SSE2 and NEON but initialized in the C path. +const ALIGN16_BEG float ALIGN16_END k_swap_sign[4] = {-1.f, 1.f, -1.f, 1.f}; + +ALIGN16_BEG const float ALIGN16_END rdft_wk1r[32] = { + 1.000000000f, 1.000000000f, 0.707106769f, 0.707106769f, 0.923879564f, + 0.923879564f, 0.382683456f, 0.382683456f, 0.980785251f, 0.980785251f, + 0.555570245f, 0.555570245f, 0.831469595f, 0.831469595f, 0.195090324f, + 0.195090324f, 0.995184720f, 0.995184720f, 0.634393334f, 0.634393334f, + 0.881921291f, 0.881921291f, 0.290284663f, 0.290284663f, 0.956940353f, + 0.956940353f, 0.471396744f, 0.471396744f, 0.773010433f, 0.773010433f, + 0.098017141f, 0.098017141f, +}; +ALIGN16_BEG const float ALIGN16_END rdft_wk2r[32] = { + 1.000000000f, 1.000000000f, -0.000000000f, -0.000000000f, 0.707106769f, + 0.707106769f, -0.707106769f, -0.707106769f, 0.923879564f, 0.923879564f, + -0.382683456f, -0.382683456f, 0.382683456f, 0.382683456f, -0.923879564f, + -0.923879564f, 0.980785251f, 0.980785251f, -0.195090324f, -0.195090324f, + 0.555570245f, 0.555570245f, -0.831469595f, -0.831469595f, 0.831469595f, + 0.831469595f, -0.555570245f, -0.555570245f, 0.195090324f, 0.195090324f, + -0.980785251f, -0.980785251f, +}; +ALIGN16_BEG const float ALIGN16_END rdft_wk3r[32] = { + 1.000000000f, 1.000000000f, -0.707106769f, -0.707106769f, 0.382683456f, + 0.382683456f, -0.923879564f, -0.923879564f, 0.831469536f, 0.831469536f, + -0.980785251f, -0.980785251f, -0.195090353f, -0.195090353f, -0.555570245f, + -0.555570245f, 0.956940353f, 0.956940353f, -0.881921172f, -0.881921172f, + 0.098017156f, 0.098017156f, -0.773010492f, -0.773010492f, 0.634393334f, + 0.634393334f, -0.995184720f, -0.995184720f, -0.471396863f, -0.471396863f, + -0.290284693f, -0.290284693f, +}; +ALIGN16_BEG const float ALIGN16_END rdft_wk1i[32] = { + -0.000000000f, 0.000000000f, -0.707106769f, 0.707106769f, -0.382683456f, + 0.382683456f, -0.923879564f, 0.923879564f, -0.195090324f, 0.195090324f, + -0.831469595f, 0.831469595f, -0.555570245f, 0.555570245f, -0.980785251f, + 0.980785251f, -0.098017141f, 0.098017141f, -0.773010433f, 0.773010433f, + -0.471396744f, 0.471396744f, -0.956940353f, 0.956940353f, -0.290284663f, + 0.290284663f, -0.881921291f, 0.881921291f, -0.634393334f, 0.634393334f, + -0.995184720f, 0.995184720f, +}; +ALIGN16_BEG const float ALIGN16_END rdft_wk2i[32] = { + -0.000000000f, 0.000000000f, -1.000000000f, 1.000000000f, -0.707106769f, + 0.707106769f, -0.707106769f, 0.707106769f, -0.382683456f, 0.382683456f, + -0.923879564f, 0.923879564f, -0.923879564f, 0.923879564f, -0.382683456f, + 0.382683456f, -0.195090324f, 0.195090324f, -0.980785251f, 0.980785251f, + -0.831469595f, 0.831469595f, -0.555570245f, 0.555570245f, -0.555570245f, + 0.555570245f, -0.831469595f, 0.831469595f, -0.980785251f, 0.980785251f, + -0.195090324f, 0.195090324f, +}; +ALIGN16_BEG const float ALIGN16_END rdft_wk3i[32] = { + -0.000000000f, 0.000000000f, -0.707106769f, 0.707106769f, -0.923879564f, + 0.923879564f, 0.382683456f, -0.382683456f, -0.555570245f, 0.555570245f, + -0.195090353f, 0.195090353f, -0.980785251f, 0.980785251f, 0.831469536f, + -0.831469536f, -0.290284693f, 0.290284693f, -0.471396863f, 0.471396863f, + -0.995184720f, 0.995184720f, 0.634393334f, -0.634393334f, -0.773010492f, + 0.773010492f, 0.098017156f, -0.098017156f, -0.881921172f, 0.881921172f, + 0.956940353f, -0.956940353f, +}; +ALIGN16_BEG const float ALIGN16_END cftmdl_wk1r[4] = { + 0.707106769f, 0.707106769f, 0.707106769f, -0.707106769f, +}; +#endif + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_NEON_SSE2_H_ diff --git a/include/webrtc/modules/audio_processing/vad/vad_audio_proc.h b/include/webrtc/modules/audio_processing/vad/vad_audio_proc.h index a8ecc7b..1f27b29 100644 --- a/include/webrtc/modules/audio_processing/vad/vad_audio_proc.h +++ b/include/webrtc/modules/audio_processing/vad/vad_audio_proc.h @@ -50,25 +50,28 @@ class VadAudioProc { // For every 30 ms we compute 3 spectral peak there for 3 LPC analysis. // LPC is computed over 15 ms of windowed audio. For every 10 ms sub-frame // we need 5 ms of past signal to create the input of LPC analysis. - static const size_t kNumPastSignalSamples = - static_cast(kSampleRateHz / 200); + enum : size_t { + kNumPastSignalSamples = static_cast(kSampleRateHz / 200) + }; // TODO(turajs): maybe defining this at a higher level (maybe enum) so that // all the code recognize it as "no-error." - static const int kNoError = 0; - - static const size_t kNum10msSubframes = 3; - static const size_t kNumSubframeSamples = - static_cast(kSampleRateHz / 100); - static const size_t kNumSamplesToProcess = - kNum10msSubframes * - kNumSubframeSamples; // Samples in 30 ms @ given sampling rate. - static const size_t kBufferLength = - kNumPastSignalSamples + kNumSamplesToProcess; - static const size_t kIpLength = kDftSize >> 1; - static const size_t kWLength = kDftSize >> 1; - - static const size_t kLpcOrder = 16; + enum : int { kNoError = 0 }; + + enum : size_t { kNum10msSubframes = 3 }; + enum : size_t { + kNumSubframeSamples = static_cast(kSampleRateHz / 100) + }; + enum : size_t { + // Samples in 30 ms @ given sampling rate. + kNumSamplesToProcess = kNum10msSubframes * kNumSubframeSamples + }; + enum : size_t { + kBufferLength = kNumPastSignalSamples + kNumSamplesToProcess + }; + enum : size_t { kIpLength = kDftSize >> 1 }; + enum : size_t { kWLength = kDftSize >> 1 }; + enum : size_t { kLpcOrder = 16 }; size_t ip_[kIpLength]; float w_fft_[kWLength]; diff --git a/include/webrtc/modules/audio_processing/vad/voice_activity_detector.h b/include/webrtc/modules/audio_processing/vad/voice_activity_detector.h index 25f10dd..5fb5e59 100644 --- a/include/webrtc/modules/audio_processing/vad/voice_activity_detector.h +++ b/include/webrtc/modules/audio_processing/vad/voice_activity_detector.h @@ -27,6 +27,7 @@ namespace webrtc { class VoiceActivityDetector { public: VoiceActivityDetector(); + ~VoiceActivityDetector(); // Processes each audio chunk and estimates the voice probability. The maximum // supported sample rate is 32kHz. diff --git a/include/webrtc/modules/bitrate_controller/bitrate_controller_impl.h b/include/webrtc/modules/bitrate_controller/bitrate_controller_impl.h index 5a61379..7ee6b19 100644 --- a/include/webrtc/modules/bitrate_controller/bitrate_controller_impl.h +++ b/include/webrtc/modules/bitrate_controller/bitrate_controller_impl.h @@ -19,6 +19,7 @@ #include #include +#include #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" @@ -30,7 +31,9 @@ class BitrateControllerImpl : public BitrateController { public: // TODO(perkj): BitrateObserver has been deprecated and is not used in WebRTC. // |observer| is left for project that is not yet updated. - BitrateControllerImpl(Clock* clock, BitrateObserver* observer); + BitrateControllerImpl(Clock* clock, + BitrateObserver* observer, + RtcEventLog* event_log); virtual ~BitrateControllerImpl() {} bool AvailableBandwidth(uint32_t* bandwidth) const override; @@ -46,17 +49,20 @@ class BitrateControllerImpl : public BitrateController { int min_bitrate_bps, int max_bitrate_bps) override; - void UpdateDelayBasedEstimate(uint32_t bitrate_bps) override; + void ResetBitrates(int bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps) override; - void SetReservedBitrate(uint32_t reserved_bitrate_bps) override; - void SetEventLog(RtcEventLog* event_log) override; + void SetReservedBitrate(uint32_t reserved_bitrate_bps) override; // Returns true if the parameters have changed since the last call. bool GetNetworkParameters(uint32_t* bitrate, uint8_t* fraction_loss, int64_t* rtt) override; + void OnDelayBasedBweResult(const DelayBasedBwe::Result& result) override; + int64_t TimeUntilNextProcess() override; void Process() override; @@ -64,7 +70,7 @@ class BitrateControllerImpl : public BitrateController { class RtcpBandwidthObserverImpl; // Called by BitrateObserver's direct from the RTCP module. - void OnReceivedEstimatedBitrate(uint32_t bitrate); + void OnReceiverEstimatedBitrate(uint32_t bitrate); void OnReceivedRtcpReceiverReport(uint8_t fraction_loss, int64_t rtt, @@ -82,6 +88,7 @@ class BitrateControllerImpl : public BitrateController { Clock* const clock_; BitrateObserver* const observer_; int64_t last_bitrate_update_ms_; + RtcEventLog* const event_log_; rtc::CriticalSection critsect_; SendSideBandwidthEstimation bandwidth_estimation_ GUARDED_BY(critsect_); diff --git a/include/webrtc/modules/bitrate_controller/include/bitrate_controller.h b/include/webrtc/modules/bitrate_controller/include/bitrate_controller.h index a61cf6a..7400d7d 100644 --- a/include/webrtc/modules/bitrate_controller/include/bitrate_controller.h +++ b/include/webrtc/modules/bitrate_controller/include/bitrate_controller.h @@ -17,6 +17,7 @@ #include +#include "webrtc/modules/congestion_controller/delay_based_bwe.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/pacing/paced_sender.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" @@ -55,8 +56,11 @@ class BitrateController : public Module { // TODO(perkj): BitrateObserver has been deprecated and is not used in WebRTC. // Remove this method once other other projects does not use it. static BitrateController* CreateBitrateController(Clock* clock, - BitrateObserver* observer); - static BitrateController* CreateBitrateController(Clock* clock); + BitrateObserver* observer, + RtcEventLog* event_log); + + static BitrateController* CreateBitrateController(Clock* clock, + RtcEventLog* event_log); virtual ~BitrateController() {} @@ -70,9 +74,11 @@ class BitrateController : public Module { int min_bitrate_bps, int max_bitrate_bps) = 0; - virtual void UpdateDelayBasedEstimate(uint32_t bitrate_bps) = 0; + virtual void ResetBitrates(int bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps) = 0; - virtual void SetEventLog(RtcEventLog* event_log) = 0; + virtual void OnDelayBasedBweResult(const DelayBasedBwe::Result& result) = 0; // Gets the available payload bandwidth in bits per second. Note that // this bandwidth excludes packet headers. diff --git a/include/webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h b/include/webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h index da6169e..d4a12ec 100644 --- a/include/webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h +++ b/include/webrtc/modules/bitrate_controller/include/mock/mock_bitrate_controller.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_MOCK_MOCK_BITRATE_CONTROLLER_H_ #define WEBRTC_MODULES_BITRATE_CONTROLLER_INCLUDE_MOCK_MOCK_BITRATE_CONTROLLER_H_ -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" +#include "webrtc/test/gmock.h" namespace webrtc { namespace test { @@ -35,7 +35,10 @@ class MockBitrateController : public BitrateController { void(int start_bitrate_bps, int min_bitrate_bps, int max_bitrate_bps)); + MOCK_METHOD3(ResetBitrates, + void(int bitrate_bps, int min_bitrate_bps, int max_bitrate_bps)); MOCK_METHOD1(UpdateDelayBasedEstimate, void(uint32_t bitrate_bps)); + MOCK_METHOD1(UpdateProbeBitrate, void(uint32_t bitrate_bps)); MOCK_METHOD1(SetEventLog, void(RtcEventLog* event_log)); MOCK_CONST_METHOD1(AvailableBandwidth, bool(uint32_t* bandwidth)); MOCK_METHOD1(SetReservedBitrate, void(uint32_t reserved_bitrate_bps)); diff --git a/include/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/include/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 402d22a..9529068 100644 --- a/include/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/include/webrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -26,7 +26,8 @@ class RtcEventLog; class SendSideBandwidthEstimation { public: - SendSideBandwidthEstimation(); + SendSideBandwidthEstimation() = delete; + explicit SendSideBandwidthEstimation(RtcEventLog* event_log); virtual ~SendSideBandwidthEstimation(); void CurrentEstimate(int* bitrate, uint8_t* loss, int64_t* rtt) const; @@ -53,8 +54,6 @@ class SendSideBandwidthEstimation { void SetMinMaxBitrate(int min_bitrate, int max_bitrate); int GetMinBitrate() const; - void SetEventLog(RtcEventLog* event_log); - private: enum UmaState { kNoUpdate, kFirstDone, kDone }; @@ -83,8 +82,11 @@ class SendSideBandwidthEstimation { int64_t last_low_bitrate_log_ms_; bool has_decreased_since_last_fraction_loss_; - int64_t time_last_receiver_block_ms_; + int64_t last_feedback_ms_; + int64_t last_packet_report_ms_; + int64_t last_timeout_ms_; uint8_t last_fraction_loss_; + uint8_t last_logged_fraction_loss_; int64_t last_round_trip_time_ms_; uint32_t bwe_incoming_; @@ -96,6 +98,8 @@ class SendSideBandwidthEstimation { UmaState uma_update_state_; std::vector rampup_uma_stats_updated_; RtcEventLog* event_log_; + int64_t last_rtc_event_log_ms_; + bool in_timeout_experiment_; }; } // namespace webrtc #endif // WEBRTC_MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_ diff --git a/include/webrtc/modules/congestion_controller/delay_based_bwe.h b/include/webrtc/modules/congestion_controller/delay_based_bwe.h new file mode 100644 index 0000000..c02182b --- /dev/null +++ b/include/webrtc/modules/congestion_controller/delay_based_bwe.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_H_ + +#include +#include +#include + +#include "webrtc/base/checks.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/rate_statistics.h" +#include "webrtc/base/thread_checker.h" +#include "webrtc/modules/congestion_controller/median_slope_estimator.h" +#include "webrtc/modules/congestion_controller/probe_bitrate_estimator.h" +#include "webrtc/modules/congestion_controller/probing_interval_estimator.h" +#include "webrtc/modules/congestion_controller/trendline_estimator.h" +#include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h" +#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/modules/remote_bitrate_estimator/inter_arrival.h" +#include "webrtc/modules/remote_bitrate_estimator/overuse_detector.h" +#include "webrtc/modules/remote_bitrate_estimator/overuse_estimator.h" + +namespace webrtc { + +class RtcEventLog; + +class DelayBasedBwe { + public: + static const int64_t kStreamTimeOutMs = 2000; + + struct Result { + Result() : updated(false), probe(false), target_bitrate_bps(0) {} + Result(bool probe, uint32_t target_bitrate_bps) + : updated(true), probe(probe), target_bitrate_bps(target_bitrate_bps) {} + bool updated; + bool probe; + uint32_t target_bitrate_bps; + }; + + DelayBasedBwe(RtcEventLog* event_log, Clock* clock); + virtual ~DelayBasedBwe() {} + + Result IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector); + void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms); + bool LatestEstimate(std::vector* ssrcs, + uint32_t* bitrate_bps) const; + void SetStartBitrate(int start_bitrate_bps); + void SetMinBitrate(int min_bitrate_bps); + int64_t GetProbingIntervalMs() const; + + private: + // Computes a bayesian estimate of the throughput given acks containing + // the arrival time and payload size. Samples which are far from the current + // estimate or are based on few packets are given a smaller weight, as they + // are considered to be more likely to have been caused by, e.g., delay spikes + // unrelated to congestion. + class BitrateEstimator { + public: + BitrateEstimator(); + void Update(int64_t now_ms, int bytes); + rtc::Optional bitrate_bps() const; + + private: + float UpdateWindow(int64_t now_ms, int bytes, int rate_window_ms); + int sum_; + int64_t current_win_ms_; + int64_t prev_time_ms_; + float bitrate_estimate_; + float bitrate_estimate_var_; + RateStatistics old_estimator_; + const bool in_experiment_; + }; + + Result IncomingPacketInfo(const PacketInfo& info); + Result OnLongFeedbackDelay(int64_t arrival_time_ms); + // Updates the current remote rate estimate and returns true if a valid + // estimate exists. + bool UpdateEstimate(int64_t packet_arrival_time_ms, + int64_t now_ms, + rtc::Optional acked_bitrate_bps, + uint32_t* target_bitrate_bps); + const bool in_trendline_experiment_; + const bool in_median_slope_experiment_; + + rtc::ThreadChecker network_thread_; + RtcEventLog* const event_log_; + Clock* const clock_; + std::unique_ptr inter_arrival_; + std::unique_ptr kalman_estimator_; + std::unique_ptr trendline_estimator_; + std::unique_ptr median_slope_estimator_; + OveruseDetector detector_; + BitrateEstimator receiver_incoming_bitrate_; + int64_t last_update_ms_; + int64_t last_seen_packet_ms_; + bool uma_recorded_; + AimdRateControl rate_control_; + ProbeBitrateEstimator probe_bitrate_estimator_; + size_t trendline_window_size_; + double trendline_smoothing_coeff_; + double trendline_threshold_gain_; + ProbingIntervalEstimator probing_interval_estimator_; + size_t median_slope_window_size_; + double median_slope_threshold_gain_; + int consecutive_delayed_feedbacks_; + uint32_t last_logged_bitrate_; + BandwidthUsage last_logged_state_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayBasedBwe); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_H_ diff --git a/include/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h b/include/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h new file mode 100644 index 0000000..5833a69 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/delay_based_bwe_unittest_helper.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_UNITTEST_HELPER_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_UNITTEST_HELPER_H_ + +#include +#include +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/congestion_controller/delay_based_bwe.h" +#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/test/gtest.h" + +namespace webrtc { +namespace test { + +class TestBitrateObserver : public RemoteBitrateObserver { + public: + TestBitrateObserver() : updated_(false), latest_bitrate_(0) {} + virtual ~TestBitrateObserver() {} + + void OnReceiveBitrateChanged(const std::vector& ssrcs, + uint32_t bitrate) override; + + void Reset() { updated_ = false; } + + bool updated() const { return updated_; } + + uint32_t latest_bitrate() const { return latest_bitrate_; } + + private: + bool updated_; + uint32_t latest_bitrate_; +}; + +class RtpStream { + public: + enum { kSendSideOffsetUs = 1000000 }; + + RtpStream(int fps, int bitrate_bps); + + // Generates a new frame for this stream. If called too soon after the + // previous frame, no frame will be generated. The frame is split into + // packets. + int64_t GenerateFrame(int64_t time_now_us, std::vector* packets); + + // The send-side time when the next frame can be generated. + int64_t next_rtp_time() const; + + void set_bitrate_bps(int bitrate_bps); + + int bitrate_bps() const; + + static bool Compare(const std::unique_ptr& lhs, + const std::unique_ptr& rhs); + + private: + int fps_; + int bitrate_bps_; + int64_t next_rtp_time_; + uint16_t sequence_number_; + + RTC_DISALLOW_COPY_AND_ASSIGN(RtpStream); +}; + +class StreamGenerator { + public: + StreamGenerator(int capacity, int64_t time_now); + + // Add a new stream. + void AddStream(RtpStream* stream); + + // Set the link capacity. + void set_capacity_bps(int capacity_bps); + + // Divides |bitrate_bps| among all streams. The allocated bitrate per stream + // is decided by the initial allocation ratios. + void SetBitrateBps(int bitrate_bps); + + // Set the RTP timestamp offset for the stream identified by |ssrc|. + void set_rtp_timestamp_offset(uint32_t ssrc, uint32_t offset); + + // TODO(holmer): Break out the channel simulation part from this class to make + // it possible to simulate different types of channels. + int64_t GenerateFrame(std::vector* packets, int64_t time_now_us); + + private: + // Capacity of the simulated channel in bits per second. + int capacity_; + // The time when the last packet arrived. + int64_t prev_arrival_time_us_; + // All streams being transmitted on this simulated channel. + std::vector> streams_; + + RTC_DISALLOW_COPY_AND_ASSIGN(StreamGenerator); +}; +} // namespace test + +class DelayBasedBweTest : public ::testing::Test { + public: + DelayBasedBweTest(); + virtual ~DelayBasedBweTest(); + + protected: + void AddDefaultStream(); + + // Helpers to insert a single packet into the delay-based BWE. + void IncomingFeedback(int64_t arrival_time_ms, + int64_t send_time_ms, + uint16_t sequence_number, + size_t payload_size); + void IncomingFeedback(int64_t arrival_time_ms, + int64_t send_time_ms, + uint16_t sequence_number, + size_t payload_size, + const PacedPacketInfo& pacing_info); + + // Generates a frame of packets belonging to a stream at a given bitrate and + // with a given ssrc. The stream is pushed through a very simple simulated + // network, and is then given to the receive-side bandwidth estimator. + // Returns true if an over-use was seen, false otherwise. + // The StreamGenerator::updated() should be used to check for any changes in + // target bitrate after the call to this function. + bool GenerateAndProcessFrame(uint32_t ssrc, uint32_t bitrate_bps); + + // Run the bandwidth estimator with a stream of |number_of_frames| frames, or + // until it reaches |target_bitrate|. + // Can for instance be used to run the estimator for some time to get it + // into a steady state. + uint32_t SteadyStateRun(uint32_t ssrc, + int number_of_frames, + uint32_t start_bitrate, + uint32_t min_bitrate, + uint32_t max_bitrate, + uint32_t target_bitrate); + + void TestTimestampGroupingTestHelper(); + + void TestWrappingHelper(int silence_time_s); + + void InitialBehaviorTestHelper(uint32_t expected_converge_bitrate); + void RateIncreaseReorderingTestHelper(uint32_t expected_bitrate); + void RateIncreaseRtpTimestampsTestHelper(int expected_iterations); + void CapacityDropTestHelper(int number_of_streams, + bool wrap_time_stamp, + uint32_t expected_bitrate_drop_delta, + int64_t receiver_clock_offset_change_ms); + + static const uint32_t kDefaultSsrc; + + SimulatedClock clock_; // Time at the receiver. + test::TestBitrateObserver bitrate_observer_; + std::unique_ptr bitrate_estimator_; + std::unique_ptr stream_generator_; + int64_t arrival_time_offset_ms_; + bool first_update_; + + RTC_DISALLOW_COPY_AND_ASSIGN(DelayBasedBweTest); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_DELAY_BASED_BWE_UNITTEST_HELPER_H_ diff --git a/include/webrtc/modules/congestion_controller/include/congestion_controller.h b/include/webrtc/modules/congestion_controller/include/congestion_controller.h index da8719d..500966b 100644 --- a/include/webrtc/modules/congestion_controller/include/congestion_controller.h +++ b/include/webrtc/modules/congestion_controller/include/congestion_controller.h @@ -12,15 +12,17 @@ #define WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_CONGESTION_CONTROLLER_H_ #include +#include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/criticalsection.h" #include "webrtc/common_types.h" +#include "webrtc/modules/congestion_controller/transport_feedback_adapter.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/pacing/packet_router.h" #include "webrtc/modules/pacing/paced_sender.h" #include "webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h" -#include "webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h" namespace rtc { struct SentPacket; @@ -29,11 +31,12 @@ struct SentPacket; namespace webrtc { class BitrateController; -class BitrateObserver; class Clock; -class ProcessThread; +class ProbeController; +class RateLimiter; class RemoteBitrateEstimator; class RemoteBitrateObserver; +class RtcEventLog; class TransportFeedbackObserver; class CongestionController : public CallStatsObserver, public Module { @@ -47,40 +50,63 @@ class CongestionController : public CallStatsObserver, public Module { public: virtual void OnNetworkChanged(uint32_t bitrate_bps, uint8_t fraction_loss, // 0 - 255. - int64_t rtt_ms) = 0; + int64_t rtt_ms, + int64_t probing_interval_ms) = 0; protected: virtual ~Observer() {} }; - // Deprecated - // TODO(perkj): Remove once no other clients use this ctor. - CongestionController(Clock* clock, - BitrateObserver* bitrate_observer, - RemoteBitrateObserver* remote_bitrate_observer); CongestionController(Clock* clock, Observer* observer, - RemoteBitrateObserver* remote_bitrate_observer); + RemoteBitrateObserver* remote_bitrate_observer, + RtcEventLog* event_log, + PacketRouter* packet_router); CongestionController(Clock* clock, Observer* observer, RemoteBitrateObserver* remote_bitrate_observer, - std::unique_ptr packet_router, + RtcEventLog* event_log, + PacketRouter* packet_router, std::unique_ptr pacer); virtual ~CongestionController(); + virtual void OnReceivedPacket(int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header); + virtual void SetBweBitrates(int min_bitrate_bps, int start_bitrate_bps, int max_bitrate_bps); + // Resets both the BWE state and the bitrate estimator. Note the first + // argument is the bitrate_bps. + virtual void ResetBweAndBitrates(int bitrate_bps, + int min_bitrate_bps, + int max_bitrate_bps); virtual void SignalNetworkState(NetworkState state); + virtual void SetTransportOverhead(size_t transport_overhead_bytes_per_packet); + virtual BitrateController* GetBitrateController() const; virtual RemoteBitrateEstimator* GetRemoteBitrateEstimator( bool send_side_bwe); virtual int64_t GetPacerQueuingDelayMs() const; + // TODO(nisse): Delete this accessor function. The pacer should be + // internal to the congestion controller. virtual PacedSender* pacer() { return pacer_.get(); } - virtual PacketRouter* packet_router() { return packet_router_.get(); } virtual TransportFeedbackObserver* GetTransportFeedbackObserver(); - - void SetAllocatedSendBitrate(int allocated_bitrate_bps, - int padding_bitrate_bps); + RateLimiter* GetRetransmissionRateLimiter(); + void EnablePeriodicAlrProbing(bool enable); + + // SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec + // settings. + // |min_send_bitrate_bps| is the total minimum send bitrate required by all + // sending streams. This is the minimum bitrate the PacedSender will use. + // Note that CongestionController::OnNetworkChanged can still be called with + // a lower bitrate estimate. + // |max_padding_bitrate_bps| is the max bitrate the send streams request for + // padding. This can be higher than the current network estimate and tells + // the PacedSender how much it should max pad unless there is real packets to + // send. + void SetAllocatedSendBitrateLimits(int min_send_bitrate_bps, + int max_padding_bitrate_bps); virtual void OnSentPacket(const rtc::SentPacket& sent_packet); @@ -92,7 +118,44 @@ class CongestionController : public CallStatsObserver, public Module { void Process() override; private: - void Init(); + class WrappingBitrateEstimator : public RemoteBitrateEstimator { + public: + WrappingBitrateEstimator(RemoteBitrateObserver* observer, Clock* clock); + + virtual ~WrappingBitrateEstimator() {} + + void IncomingPacket(int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header) override; + + void Process() override; + + int64_t TimeUntilNextProcess() override; + + void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; + + void RemoveStream(unsigned int ssrc) override; + + bool LatestEstimate(std::vector* ssrcs, + unsigned int* bitrate_bps) const override; + + void SetMinBitrate(int min_bitrate_bps) override; + + private: + void PickEstimatorFromHeader(const RTPHeader& header) + EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + void PickEstimator() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + RemoteBitrateObserver* observer_; + Clock* const clock_; + rtc::CriticalSection crit_sect_; + std::unique_ptr rbe_; + bool using_absolute_send_time_; + uint32_t packets_since_absolute_send_time_; + int min_bitrate_bps_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WrappingBitrateEstimator); + }; + void MaybeTriggerOnNetworkChanged(); bool IsSendQueueFull() const; @@ -102,13 +165,16 @@ class CongestionController : public CallStatsObserver, public Module { int64_t rtt); Clock* const clock_; Observer* const observer_; - const std::unique_ptr packet_router_; + PacketRouter* const packet_router_; const std::unique_ptr pacer_; - const std::unique_ptr remote_bitrate_estimator_; const std::unique_ptr bitrate_controller_; + const std::unique_ptr probe_controller_; + const std::unique_ptr retransmission_rate_limiter_; + WrappingBitrateEstimator remote_bitrate_estimator_; RemoteEstimatorProxy remote_estimator_proxy_; TransportFeedbackAdapter transport_feedback_adapter_; int min_bitrate_bps_; + int max_bitrate_bps_; rtc::CriticalSection critsect_; uint32_t last_reported_bitrate_bps_ GUARDED_BY(critsect_); uint8_t last_reported_fraction_loss_ GUARDED_BY(critsect_); diff --git a/include/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h b/include/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h index 20955ea..aefb2be 100644 --- a/include/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h +++ b/include/webrtc/modules/congestion_controller/include/mock/mock_congestion_controller.h @@ -11,28 +11,44 @@ #ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_MOCK_MOCK_CONGESTION_CONTROLLER_H_ #define WEBRTC_MODULES_CONGESTION_CONTROLLER_INCLUDE_MOCK_MOCK_CONGESTION_CONTROLLER_H_ -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/socket.h" +#include "webrtc/common_types.h" #include "webrtc/modules/congestion_controller/include/congestion_controller.h" +#include "webrtc/test/gmock.h" namespace webrtc { namespace test { class MockCongestionObserver : public CongestionController::Observer { public: - MOCK_METHOD3(OnNetworkChanged, + // TODO(minyue): remove this when old OnNetworkChanged is deprecated. See + // https://bugs.chromium.org/p/webrtc/issues/detail?id=6796 + using CongestionController::Observer::OnNetworkChanged; + + MOCK_METHOD4(OnNetworkChanged, void(uint32_t bitrate_bps, uint8_t fraction_loss, - int64_t rtt_ms)); + int64_t rtt_ms, + int64_t probing_interval_ms)); }; class MockCongestionController : public CongestionController { public: MockCongestionController(Clock* clock, Observer* observer, - RemoteBitrateObserver* remote_bitrate_observer) - : CongestionController(clock, observer, remote_bitrate_observer) {} + RemoteBitrateObserver* remote_bitrate_observer, + RtcEventLog* event_log, + PacketRouter* packet_router) + : CongestionController(clock, + observer, + remote_bitrate_observer, + event_log, + packet_router) {} + MOCK_METHOD3(OnReceivedPacket, + void(int64_t arrival_time_ms, + size_t payload_size, + const RTPHeader& header)); MOCK_METHOD3(SetBweBitrates, void(int min_bitrate_bps, int start_bitrate_bps, @@ -43,7 +59,6 @@ class MockCongestionController : public CongestionController { RemoteBitrateEstimator*(bool send_side_bwe)); MOCK_CONST_METHOD0(GetPacerQueuingDelayMs, int64_t()); MOCK_METHOD0(pacer, PacedSender*()); - MOCK_METHOD0(packet_router, PacketRouter*()); MOCK_METHOD0(GetTransportFeedbackObserver, TransportFeedbackObserver*()); MOCK_METHOD3(UpdatePacerBitrate, void(int bitrate_kbps, diff --git a/include/webrtc/modules/congestion_controller/median_slope_estimator.h b/include/webrtc/modules/congestion_controller/median_slope_estimator.h new file mode 100644 index 0000000..3a13ec7 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/median_slope_estimator.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_ + +#include +#include + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/numerics/percentile_filter.h" + +namespace webrtc { + +class MedianSlopeEstimator { + public: + // |window_size| is the number of points required to compute a trend line. + // |threshold_gain| is used to scale the trendline slope for comparison to + // the old threshold. Once the old estimator has been removed (or the + // thresholds been merged into the estimators), we can just set the + // threshold instead of setting a gain. + MedianSlopeEstimator(size_t window_size, double threshold_gain); + ~MedianSlopeEstimator(); + + // Update the estimator with a new sample. The deltas should represent deltas + // between timestamp groups as defined by the InterArrival class. + void Update(double recv_delta_ms, + double send_delta_ms, + int64_t arrival_time_ms); + + // Returns the estimated trend k multiplied by some gain. + // 0 < k < 1 -> the delay increases, queues are filling up + // k == 0 -> the delay does not change + // k < 0 -> the delay decreases, queues are being emptied + double trendline_slope() const { return trendline_ * threshold_gain_; } + + // Returns the number of deltas which the current estimator state is based on. + unsigned int num_of_deltas() const { return num_of_deltas_; } + + private: + struct DelayInfo { + DelayInfo(int64_t time, double delay, size_t slope_count) + : time(time), delay(delay) { + slopes.reserve(slope_count); + } + int64_t time; + double delay; + std::vector slopes; + }; + // Parameters. + const size_t window_size_; + const double threshold_gain_; + // Used by the existing threshold. + unsigned int num_of_deltas_; + // Theil-Sen robust line fitting + double accumulated_delay_; + std::deque delay_hist_; + PercentileFilter median_filter_; + double trendline_; + + RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_MEDIAN_SLOPE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/congestion_controller/probe_bitrate_estimator.h b/include/webrtc/modules/congestion_controller/probe_bitrate_estimator.h new file mode 100644 index 0000000..c25c727 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/probe_bitrate_estimator.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_ + +#include +#include + +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" + +namespace webrtc { + +class ProbeBitrateEstimator { + public: + ProbeBitrateEstimator(); + + // Should be called for every probe packet we receive feedback about. + // Returns the estimated bitrate if the probe completes a valid cluster. + int HandleProbeAndEstimateBitrate(const PacketInfo& packet_info); + + private: + struct AggregatedCluster { + int num_probes = 0; + int64_t first_send_ms = std::numeric_limits::max(); + int64_t last_send_ms = 0; + int64_t first_receive_ms = std::numeric_limits::max(); + int64_t last_receive_ms = 0; + int size_last_send = 0; + int size_first_receive = 0; + int size_total = 0; + }; + + // Erases old cluster data that was seen before |timestamp_ms|. + void EraseOldClusters(int64_t timestamp_ms); + + std::map clusters_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_BITRATE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/congestion_controller/probe_controller.h b/include/webrtc/modules/congestion_controller/probe_controller.h new file mode 100644 index 0000000..a4201e6 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/probe_controller.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_ + +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/common_types.h" +#include "webrtc/modules/pacing/paced_sender.h" + +namespace webrtc { + +class Clock; + +// This class controls initiation of probing to estimate initial channel +// capacity. There is also support for probing during a session when max +// bitrate is adjusted by an application. +class ProbeController { + public: + ProbeController(PacedSender* pacer, Clock* clock); + + void SetBitrates(int64_t min_bitrate_bps, + int64_t start_bitrate_bps, + int64_t max_bitrate_bps); + + void OnNetworkStateChanged(NetworkState state); + + void SetEstimatedBitrate(int64_t bitrate_bps); + + void EnablePeriodicAlrProbing(bool enable); + void Process(); + + private: + enum class State { + // Initial state where no probing has been triggered yet. + kInit, + // Waiting for probing results to continue further probing. + kWaitingForProbingResult, + // Probing is complete. + kProbingComplete, + }; + + void InitiateExponentialProbing() EXCLUSIVE_LOCKS_REQUIRED(critsect_); + void InitiateProbing(int64_t now_ms, + std::initializer_list bitrates_to_probe, + bool probe_further) EXCLUSIVE_LOCKS_REQUIRED(critsect_); + + rtc::CriticalSection critsect_; + PacedSender* const pacer_; + Clock* const clock_; + NetworkState network_state_ GUARDED_BY(critsect_); + State state_ GUARDED_BY(critsect_); + int64_t min_bitrate_to_probe_further_bps_ GUARDED_BY(critsect_); + int64_t time_last_probing_initiated_ms_ GUARDED_BY(critsect_); + int64_t estimated_bitrate_bps_ GUARDED_BY(critsect_); + int64_t start_bitrate_bps_ GUARDED_BY(critsect_); + int64_t max_bitrate_bps_ GUARDED_BY(critsect_); + int64_t last_alr_probing_time_ GUARDED_BY(critsect_); + bool enable_periodic_alr_probing_ GUARDED_BY(critsect_); + + // For WebRTC.BWE.MidCallProbing.* metric. + bool mid_call_probing_waiting_for_result_ GUARDED_BY(&critsect_); + int64_t mid_call_probing_bitrate_bps_ GUARDED_BY(&critsect_); + int64_t mid_call_probing_succcess_threshold_ GUARDED_BY(&critsect_); + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ProbeController); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBE_CONTROLLER_H_ diff --git a/include/webrtc/modules/congestion_controller/probing_interval_estimator.h b/include/webrtc/modules/congestion_controller/probing_interval_estimator.h new file mode 100644 index 0000000..993e0da --- /dev/null +++ b/include/webrtc/modules/congestion_controller/probing_interval_estimator.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBING_INTERVAL_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBING_INTERVAL_ESTIMATOR_H_ + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" +#include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h" + +namespace webrtc { + +class ProbingIntervalEstimator { + public: + explicit ProbingIntervalEstimator(const AimdRateControl* aimd_rate_control); + + ProbingIntervalEstimator(int64_t min_interval_ms, + int64_t max_interval_ms, + int64_t default_interval_ms, + const AimdRateControl* aimd_rate_control); + int64_t GetIntervalMs() const; + + private: + const int64_t min_interval_ms_; + const int64_t max_interval_ms_; + const int64_t default_interval_ms_; + const AimdRateControl* const aimd_rate_control_; + RTC_DISALLOW_COPY_AND_ASSIGN(ProbingIntervalEstimator); +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_PROBING_INTERVAL_ESTIMATOR_H_ diff --git a/include/webrtc/modules/congestion_controller/transport_feedback_adapter.h b/include/webrtc/modules/congestion_controller/transport_feedback_adapter.h new file mode 100644 index 0000000..7049706 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/transport_feedback_adapter.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_TRANSPORT_FEEDBACK_ADAPTER_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_TRANSPORT_FEEDBACK_ADAPTER_H_ + +#include +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/base/thread_checker.h" +#include "webrtc/modules/congestion_controller/delay_based_bwe.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" + +namespace webrtc { + +class BitrateController; +class RtcEventLog; +class ProcessThread; + +class TransportFeedbackAdapter : public TransportFeedbackObserver, + public CallStatsObserver { + public: + TransportFeedbackAdapter(RtcEventLog* event_log, + Clock* clock, + BitrateController* bitrate_controller); + virtual ~TransportFeedbackAdapter(); + + void InitBwe(); + // Implements TransportFeedbackObserver. + void AddPacket(uint16_t sequence_number, + size_t length, + const PacedPacketInfo& pacing_info) override; + void OnSentPacket(uint16_t sequence_number, int64_t send_time_ms); + + // TODO(holmer): This method should return DelayBasedBwe::Result so that we + // can get rid of the dependency on BitrateController. Requires changes + // to the CongestionController interface. + void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override; + std::vector GetTransportFeedbackVector() const override; + + // Implements CallStatsObserver. + void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; + + void SetStartBitrate(int start_bitrate_bps); + void SetMinBitrate(int min_bitrate_bps); + void SetTransportOverhead(int transport_overhead_bytes_per_packet); + + int64_t GetProbingIntervalMs() const; + + private: + std::vector GetPacketFeedbackVector( + const rtcp::TransportFeedback& feedback); + + const bool send_side_bwe_with_overhead_; + rtc::CriticalSection lock_; + rtc::CriticalSection bwe_lock_; + int transport_overhead_bytes_per_packet_ GUARDED_BY(&lock_); + SendTimeHistory send_time_history_ GUARDED_BY(&lock_); + std::unique_ptr delay_based_bwe_ GUARDED_BY(&bwe_lock_); + RtcEventLog* const event_log_; + Clock* const clock_; + int64_t current_offset_ms_; + int64_t last_timestamp_us_; + BitrateController* const bitrate_controller_; + std::vector last_packet_feedback_vector_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_TRANSPORT_FEEDBACK_ADAPTER_H_ diff --git a/include/webrtc/modules/congestion_controller/trendline_estimator.h b/include/webrtc/modules/congestion_controller/trendline_estimator.h new file mode 100644 index 0000000..f09ccb5 --- /dev/null +++ b/include/webrtc/modules/congestion_controller/trendline_estimator.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef WEBRTC_MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_ +#define WEBRTC_MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_ + +#include +#include + +#include +#include + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class TrendlineEstimator { + public: + // |window_size| is the number of points required to compute a trend line. + // |smoothing_coef| controls how much we smooth out the delay before fitting + // the trend line. |threshold_gain| is used to scale the trendline slope for + // comparison to the old threshold. Once the old estimator has been removed + // (or the thresholds been merged into the estimators), we can just set the + // threshold instead of setting a gain. + TrendlineEstimator(size_t window_size, + double smoothing_coef, + double threshold_gain); + ~TrendlineEstimator(); + + // Update the estimator with a new sample. The deltas should represent deltas + // between timestamp groups as defined by the InterArrival class. + void Update(double recv_delta_ms, + double send_delta_ms, + int64_t arrival_time_ms); + + // Returns the estimated trend k multiplied by some gain. + // 0 < k < 1 -> the delay increases, queues are filling up + // k == 0 -> the delay does not change + // k < 0 -> the delay decreases, queues are being emptied + double trendline_slope() const { return trendline_ * threshold_gain_; } + + // Returns the number of deltas which the current estimator state is based on. + unsigned int num_of_deltas() const { return num_of_deltas_; } + + private: + // Parameters. + const size_t window_size_; + const double smoothing_coef_; + const double threshold_gain_; + // Used by the existing threshold. + unsigned int num_of_deltas_; + // Keep the arrival times small by using the change from the first packet. + int64_t first_arrival_time_ms; + // Exponential backoff filtering. + double accumulated_delay_; + double smoothed_delay_; + // Linear least squares regression. + std::deque> delay_hist_; + double trendline_; + + RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator); +}; +} // namespace webrtc + +#endif // WEBRTC_MODULES_CONGESTION_CONTROLLER_TRENDLINE_ESTIMATOR_H_ diff --git a/include/webrtc/modules/desktop_capture/cropped_desktop_frame.h b/include/webrtc/modules/desktop_capture/cropped_desktop_frame.h index 29449e2..42ae587 100644 --- a/include/webrtc/modules/desktop_capture/cropped_desktop_frame.h +++ b/include/webrtc/modules/desktop_capture/cropped_desktop_frame.h @@ -15,10 +15,11 @@ namespace webrtc { -// Always takes ownership of |frame|. Returns NULL if |rect| is not contained -// by the bounds of |frame|. -DesktopFrame* CreateCroppedDesktopFrame(DesktopFrame* frame, - const DesktopRect& rect); +// Returns nullptr frame if |rect| is not contained by the bounds of |frame|. +std::unique_ptr CreateCroppedDesktopFrame( + std::unique_ptr frame, + const DesktopRect& rect); + } // namespace webrtc #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_CROPPED_DESKTOP_FRAME_H_ diff --git a/include/webrtc/modules/desktop_capture/cropping_window_capturer.h b/include/webrtc/modules/desktop_capture/cropping_window_capturer.h index dfeb447..5b5a41d 100644 --- a/include/webrtc/modules/desktop_capture/cropping_window_capturer.h +++ b/include/webrtc/modules/desktop_capture/cropping_window_capturer.h @@ -13,36 +13,36 @@ #include +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/modules/desktop_capture/desktop_capture_options.h" -#include "webrtc/modules/desktop_capture/screen_capturer.h" -#include "webrtc/modules/desktop_capture/window_capturer.h" namespace webrtc { // WindowCapturer implementation that uses a screen capturer to capture the // whole screen and crops the video frame to the window area when the captured // window is on top. -class CroppingWindowCapturer : public WindowCapturer, +class CroppingWindowCapturer : public DesktopCapturer, public DesktopCapturer::Callback { public: - static WindowCapturer* Create(const DesktopCaptureOptions& options); - virtual ~CroppingWindowCapturer(); + static std::unique_ptr CreateCapturer( + const DesktopCaptureOptions& options); + + ~CroppingWindowCapturer() override; // DesktopCapturer implementation. void Start(DesktopCapturer::Callback* callback) override; void SetSharedMemoryFactory( std::unique_ptr shared_memory_factory) override; - void Capture(const DesktopRegion& region) override; + void CaptureFrame() override; void SetExcludedWindow(WindowId window) override; - - // WindowCapturer implementation. - bool GetWindowList(WindowList* windows) override; - bool SelectWindow(WindowId id) override; - bool BringSelectedWindowToFront() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + bool FocusOnSelectedSource() override; // DesktopCapturer::Callback implementation, passed to |screen_capturer_| to // intercept the capture result. - void OnCaptureCompleted(DesktopFrame* frame) override; + void OnCaptureResult(DesktopCapturer::Result result, + std::unique_ptr frame) override; protected: explicit CroppingWindowCapturer(const DesktopCaptureOptions& options); @@ -64,9 +64,9 @@ class CroppingWindowCapturer : public WindowCapturer, private: DesktopCaptureOptions options_; DesktopCapturer::Callback* callback_; - std::unique_ptr window_capturer_; - std::unique_ptr screen_capturer_; - WindowId selected_window_; + std::unique_ptr window_capturer_; + std::unique_ptr screen_capturer_; + SourceId selected_window_; WindowId excluded_window_; }; diff --git a/include/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h b/include/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h index dcbe612..3e339e8 100644 --- a/include/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h +++ b/include/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h @@ -31,18 +31,19 @@ class DesktopAndCursorComposer : public DesktopCapturer, // of both arguments. DesktopAndCursorComposer(DesktopCapturer* desktop_capturer, MouseCursorMonitor* mouse_monitor); - virtual ~DesktopAndCursorComposer(); + ~DesktopAndCursorComposer() override; // DesktopCapturer interface. void Start(DesktopCapturer::Callback* callback) override; void SetSharedMemoryFactory( std::unique_ptr shared_memory_factory) override; - void Capture(const DesktopRegion& region) override; + void CaptureFrame() override; void SetExcludedWindow(WindowId window) override; private: // DesktopCapturer::Callback interface. - void OnCaptureCompleted(DesktopFrame* frame) override; + void OnCaptureResult(DesktopCapturer::Result result, + std::unique_ptr frame) override; // MouseCursorMonitor::Callback interface. void OnMouseCursor(MouseCursor* cursor) override; diff --git a/include/webrtc/modules/desktop_capture/desktop_capture_options.h b/include/webrtc/modules/desktop_capture/desktop_capture_options.h index 68bb588..22f3fd5 100644 --- a/include/webrtc/modules/desktop_capture/desktop_capture_options.h +++ b/include/webrtc/modules/desktop_capture/desktop_capture_options.h @@ -28,15 +28,19 @@ namespace webrtc { // capturers. class DesktopCaptureOptions { public: - // Creates an empty Options instance (e.g. without X display). - DesktopCaptureOptions(); - ~DesktopCaptureOptions(); - // Returns instance of DesktopCaptureOptions with default parameters. On Linux // also initializes X window connection. x_display() will be set to null if // X11 connection failed (e.g. DISPLAY isn't set). static DesktopCaptureOptions CreateDefault(); + DesktopCaptureOptions(); + DesktopCaptureOptions(const DesktopCaptureOptions& options); + DesktopCaptureOptions(DesktopCaptureOptions&& options); + ~DesktopCaptureOptions(); + + DesktopCaptureOptions& operator=(const DesktopCaptureOptions& options); + DesktopCaptureOptions& operator=(DesktopCaptureOptions&& options); + #if defined(USE_X11) SharedXDisplay* x_display() const { return x_display_; } void set_x_display(rtc::scoped_refptr x_display) { @@ -76,6 +80,16 @@ class DesktopCaptureOptions { disable_effects_ = disable_effects; } + // Flag that should be set if the consumer uses updated_region() and the + // capturer should try to provide correct updated_region() for the frames it + // generates (e.g. by comparing each frame with the previous one). + // TODO(zijiehe): WindowCapturer ignores this opinion until we merge + // ScreenCapturer and WindowCapturer interfaces. + bool detect_updated_region() const { return detect_updated_region_; } + void set_detect_updated_region(bool detect_updated_region) { + detect_updated_region_ = detect_updated_region; + } + #if defined(WEBRTC_WIN) bool allow_use_magnification_api() const { return allow_use_magnification_api_; @@ -83,6 +97,14 @@ class DesktopCaptureOptions { void set_allow_use_magnification_api(bool allow) { allow_use_magnification_api_ = allow; } + // Allowing directx based capturer or not, this capturer works on windows 7 + // with platform update / windows 8 or upper. + bool allow_directx_capturer() const { + return allow_directx_capturer_; + } + void set_allow_directx_capturer(bool enabled) { + allow_directx_capturer_ = enabled; + } #endif private: @@ -97,10 +119,16 @@ class DesktopCaptureOptions { #endif #if defined(WEBRTC_WIN) - bool allow_use_magnification_api_; + bool allow_use_magnification_api_ = false; + bool allow_directx_capturer_ = false; +#endif +#if defined(USE_X11) + bool use_update_notifications_ = false; +#else + bool use_update_notifications_ = true; #endif - bool use_update_notifications_; - bool disable_effects_; + bool disable_effects_ = true; + bool detect_updated_region_ = false; }; } // namespace webrtc diff --git a/include/webrtc/modules/desktop_capture/desktop_capture_types.h b/include/webrtc/modules/desktop_capture/desktop_capture_types.h index 3e41796..9a6162a 100644 --- a/include/webrtc/modules/desktop_capture/desktop_capture_types.h +++ b/include/webrtc/modules/desktop_capture/desktop_capture_types.h @@ -13,7 +13,6 @@ #include -#include "webrtc/modules/desktop_capture/desktop_geometry.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -40,4 +39,3 @@ const ScreenId kInvalidScreenId = -2; } // namespace webrtc #endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_TYPES_H_ - diff --git a/include/webrtc/modules/desktop_capture/desktop_capturer.h b/include/webrtc/modules/desktop_capture/desktop_capturer.h index ba70e01..71834a9 100644 --- a/include/webrtc/modules/desktop_capture/desktop_capturer.h +++ b/include/webrtc/modules/desktop_capture/desktop_capturer.h @@ -12,33 +12,69 @@ #define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_H_ #include +#include #include +#include +#include +#include +#include "webrtc/modules/desktop_capture/desktop_frame.h" #include "webrtc/modules/desktop_capture/desktop_capture_types.h" #include "webrtc/modules/desktop_capture/shared_memory.h" namespace webrtc { +class DesktopCaptureOptions; class DesktopFrame; -class DesktopRegion; // Abstract interface for screen and window capturers. class DesktopCapturer { public: + enum class Result { + // The frame was captured successfully. + SUCCESS, + + // There was a temporary error. The caller should continue calling + // CaptureFrame(), in the expectation that it will eventually recover. + ERROR_TEMPORARY, + + // Capture has failed and will keep failing if the caller tries calling + // CaptureFrame() again. + ERROR_PERMANENT, + + MAX_VALUE = ERROR_PERMANENT + }; + // Interface that must be implemented by the DesktopCapturer consumers. class Callback { public: - // Called after a frame has been captured. Handler must take ownership of - // |frame|. If capture has failed for any reason |frame| is set to NULL - // (e.g. the window has been closed). - virtual void OnCaptureCompleted(DesktopFrame* frame) = 0; + // Called after a frame has been captured. |frame| is not nullptr if and + // only if |result| is SUCCESS. + virtual void OnCaptureResult(Result result, + std::unique_ptr frame) = 0; protected: virtual ~Callback() {} }; - virtual ~DesktopCapturer() {} + typedef intptr_t SourceId; + + static_assert(std::is_same::value, + "SourceId should be a same type as ScreenId."); + + struct Source { + // The unique id to represent a Source of current DesktopCapturer. + SourceId id; + + // Title of the window or screen in UTF-8 encoding, maybe empty. This field + // should not be used to identify a source. + std::string title; + }; + + typedef std::vector SourceList; + + virtual ~DesktopCapturer(); // Called at the beginning of a capturing session. |callback| must remain // valid until capturer is destroyed. @@ -46,23 +82,60 @@ class DesktopCapturer { // Sets SharedMemoryFactory that will be used to create buffers for the // captured frames. The factory can be invoked on a thread other than the one - // where Capture() is called. It will be destroyed on the same thread. Shared - // memory is currently supported only by some DesktopCapturer implementations. + // where CaptureFrame() is called. It will be destroyed on the same thread. + // Shared memory is currently supported only by some DesktopCapturer + // implementations. virtual void SetSharedMemoryFactory( - std::unique_ptr shared_memory_factory) {} + std::unique_ptr shared_memory_factory); - // Captures next frame. |region| specifies region of the capture target that - // should be fresh in the resulting frame. The frame may also include fresh - // data for areas outside |region|. In that case capturer will include these - // areas in updated_region() of the frame. |region| is specified relative to - // the top left corner of the capture target. Pending capture operations are - // canceled when DesktopCapturer is deleted. - virtual void Capture(const DesktopRegion& region) = 0; + // Captures next frame, and involve callback provided by Start() function. + // Pending capture requests are canceled when DesktopCapturer is deleted. + virtual void CaptureFrame() = 0; // Sets the window to be excluded from the captured image in the future // Capture calls. Used to exclude the screenshare notification window for // screen capturing. - virtual void SetExcludedWindow(WindowId window) {} + virtual void SetExcludedWindow(WindowId window); + + // TODO(zijiehe): Following functions should be pure virtual. The default + // implementations are for backward compatibility only. Remove default + // implementations once all DesktopCapturer implementations in Chromium have + // implemented these functions. + + // Gets a list of sources current capturer supports. Returns false in case of + // a failure. + virtual bool GetSourceList(SourceList* sources); + + // Selects a source to be captured. Returns false in case of a failure (e.g. + // if there is no source with the specified type and id.) + virtual bool SelectSource(SourceId id); + + // Brings the selected source to the front and sets the input focus on it. + // Returns false in case of a failure or no source has been selected or the + // implementation does not support this functionality. + virtual bool FocusOnSelectedSource(); + + // Creates a DesktopCapturer instance which targets to capture windows. + static std::unique_ptr CreateWindowCapturer( + const DesktopCaptureOptions& options); + + // Creates a DesktopCapturer instance which targets to capture screens. + static std::unique_ptr CreateScreenCapturer( + const DesktopCaptureOptions& options); + + protected: + // CroppingWindowCapturer needs to create raw capturers without wrappers, so + // the following two functions are protected. + + // Creates a platform specific DesktopCapturer instance which targets to + // capture windows. + static std::unique_ptr CreateRawWindowCapturer( + const DesktopCaptureOptions& options); + + // Creates a platform specific DesktopCapturer instance which targets to + // capture screens. + static std::unique_ptr CreateRawScreenCapturer( + const DesktopCaptureOptions& options); }; } // namespace webrtc diff --git a/include/webrtc/modules/desktop_capture/desktop_capturer_differ_wrapper.h b/include/webrtc/modules/desktop_capture/desktop_capturer_differ_wrapper.h new file mode 100644 index 0000000..0747a4e --- /dev/null +++ b/include/webrtc/modules/desktop_capture/desktop_capturer_differ_wrapper.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_DIFFER_WRAPPER_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_DIFFER_WRAPPER_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/modules/desktop_capture/shared_desktop_frame.h" + +namespace webrtc { + +// DesktopCapturer wrapper that calculates updated_region() by comparing frames +// content. This class always expects the underlying DesktopCapturer +// implementation returns a superset of updated regions in DestkopFrame. If a +// DesktopCapturer implementation does not know the updated region, it should +// set updated_region() to full frame. +// +// This class marks entire frame as updated if the frame size or frame stride +// has been changed. +class DesktopCapturerDifferWrapper : public DesktopCapturer, + public DesktopCapturer::Callback { + public: + // Creates a DesktopCapturerDifferWrapper with a DesktopCapturer + // implementation, and takes its ownership. + explicit DesktopCapturerDifferWrapper( + std::unique_ptr base_capturer); + + ~DesktopCapturerDifferWrapper() override; + + // DesktopCapturer interface. + void Start(DesktopCapturer::Callback* callback) override; + void SetSharedMemoryFactory( + std::unique_ptr shared_memory_factory) override; + void CaptureFrame() override; + void SetExcludedWindow(WindowId window) override; + bool GetSourceList(SourceList* screens) override; + bool SelectSource(SourceId id) override; + bool FocusOnSelectedSource() override; + + private: + // DesktopCapturer::Callback interface. + void OnCaptureResult(Result result, + std::unique_ptr frame) override; + + const std::unique_ptr base_capturer_; + DesktopCapturer::Callback* callback_; + std::unique_ptr last_frame_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_DIFFER_WRAPPER_H_ diff --git a/include/webrtc/modules/desktop_capture/desktop_frame.h b/include/webrtc/modules/desktop_capture/desktop_frame.h index 5309123..d491135 100644 --- a/include/webrtc/modules/desktop_capture/desktop_frame.h +++ b/include/webrtc/modules/desktop_capture/desktop_frame.h @@ -58,7 +58,8 @@ class DesktopFrame { // Copies pixels from a buffer or another frame. |dest_rect| rect must lay // within bounds of this frame. - void CopyPixelsFrom(uint8_t* src_buffer, int src_stride, + void CopyPixelsFrom(const uint8_t* src_buffer, + int src_stride, const DesktopRect& dest_rect); void CopyPixelsFrom(const DesktopFrame& src_frame, const DesktopVector& src_pos, @@ -73,20 +74,20 @@ class DesktopFrame { uint8_t* data, SharedMemory* shared_memory); - const DesktopSize size_; - const int stride_; - // Ownership of the buffers is defined by the classes that inherit from this // class. They must guarantee that the buffer is not deleted before the frame // is deleted. uint8_t* const data_; SharedMemory* const shared_memory_; + private: + const DesktopSize size_; + const int stride_; + DesktopRegion updated_region_; DesktopVector dpi_; int64_t capture_time_ms_; - private: RTC_DISALLOW_COPY_AND_ASSIGN(DesktopFrame); }; @@ -110,14 +111,16 @@ class SharedMemoryDesktopFrame : public DesktopFrame { DesktopSize size, SharedMemoryFactory* shared_memory_factory); + static std::unique_ptr Create( + DesktopSize size, + std::unique_ptr shared_memory); + // Takes ownership of |shared_memory|. - // TODO(sergeyu): Remove this constructor and keep the second one. + // TODO(zijiehe): Hide constructors after fake_desktop_capturer.cc has been + // migrated, Create() is preferred. SharedMemoryDesktopFrame(DesktopSize size, int stride, SharedMemory* shared_memory); - SharedMemoryDesktopFrame(DesktopSize size, - int stride, - std::unique_ptr shared_memory); ~SharedMemoryDesktopFrame() override; private: diff --git a/include/webrtc/modules/desktop_capture/desktop_frame_generator.h b/include/webrtc/modules/desktop_capture/desktop_frame_generator.h new file mode 100644 index 0000000..2b767dc --- /dev/null +++ b/include/webrtc/modules/desktop_capture/desktop_frame_generator.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_GENERATOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_GENERATOR_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/shared_memory.h" + +namespace webrtc { + +// An interface to generate a DesktopFrame. +class DesktopFrameGenerator { + public: + DesktopFrameGenerator(); + virtual ~DesktopFrameGenerator(); + + virtual std::unique_ptr GetNextFrame( + SharedMemoryFactory* factory) = 0; +}; + +// An interface to paint a DesktopFrame. This interface is used by +// PainterDesktopFrameGenerator. +class DesktopFramePainter { + public: + DesktopFramePainter(); + virtual ~DesktopFramePainter(); + + virtual bool Paint(DesktopFrame* frame, DesktopRegion* updated_region) = 0; +}; + +// An implementation of DesktopFrameGenerator to take care about the +// DesktopFrame size, filling updated_region(), etc, but leaves the real +// painting work to a DesktopFramePainter implementation. +class PainterDesktopFrameGenerator final : public DesktopFrameGenerator { + public: + PainterDesktopFrameGenerator(); + ~PainterDesktopFrameGenerator() override; + + std::unique_ptr GetNextFrame( + SharedMemoryFactory* factory) override; + + // Sets the size of the frame which will be returned in next GetNextFrame() + // call. + DesktopSize* size(); + + // Decides whether BaseDesktopFrameGenerator returns a frame in next Capture() + // callback. If return_frame_ is true, BaseDesktopFrameGenerator will create a + // frame according to both size_ and SharedMemoryFactory input, and uses + // Paint() function to paint it. + void set_return_frame(bool return_frame); + + // Decides whether MockScreenCapturer returns a frame with updated regions. + // MockScreenCapturer will keep DesktopFrame::updated_region() empty if this + // field is false. + void set_provide_updated_region_hints(bool provide_updated_region_hints); + + // Decides whether MockScreenCapturer randomly enlarges updated regions in the + // DesktopFrame. Set this field to true to simulate an inaccurate updated + // regions' return from OS APIs. + void set_enlarge_updated_region(bool enlarge_updated_region); + + // The range to enlarge a updated region if |enlarge_updated_region_| is true. + // If this field is less than zero, it will be treated as zero, and + // |enlarge_updated_region_| will be ignored. + void set_enlarge_range(int enlarge_range); + + // Decides whether BaseDesktopFrameGenerator randomly add some updated regions + // in the DesktopFrame. Set this field to true to simulate an inaccurate + // updated regions' return from OS APIs. + void set_add_random_updated_region(bool add_random_updated_region); + + // Sets the painter object to do the real painting work, if no |painter_| has + // been set to this instance, the DesktopFrame returned by GetNextFrame() + // function will keep in an undefined but valid state. + // PainterDesktopFrameGenerator does not take ownership of the |painter|. + void set_desktop_frame_painter(DesktopFramePainter* painter); + + private: + DesktopSize size_; + bool return_frame_; + bool provide_updated_region_hints_; + bool enlarge_updated_region_; + int enlarge_range_; + bool add_random_updated_region_; + DesktopFramePainter* painter_; +}; + +// An implementation of DesktopFramePainter to paint black on +// mutable_updated_region(), and white elsewhere. +class BlackWhiteDesktopFramePainter final : public DesktopFramePainter { + public: + BlackWhiteDesktopFramePainter(); + ~BlackWhiteDesktopFramePainter() override; + + // The black regions of the frame which will be returned in next Paint() + // call. BlackWhiteDesktopFramePainter will draw a white frame, with black + // in the updated_region_. Each Paint() call will consume updated_region_. + DesktopRegion* updated_region(); + + // DesktopFramePainter interface. + bool Paint(DesktopFrame* frame, DesktopRegion* updated_region) override; + + private: + DesktopRegion updated_region_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_GENERATOR_H_ diff --git a/include/webrtc/modules/desktop_capture/desktop_frame_rotation.h b/include/webrtc/modules/desktop_capture/desktop_frame_rotation.h new file mode 100644 index 0000000..c0024aa --- /dev/null +++ b/include/webrtc/modules/desktop_capture/desktop_frame_rotation.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_ROTATION_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_ROTATION_H_ + +#include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" + +namespace webrtc { + +// Represents the rotation of a DesktopFrame. +enum class Rotation { + CLOCK_WISE_0, + CLOCK_WISE_90, + CLOCK_WISE_180, + CLOCK_WISE_270, +}; + +// Rotates input DesktopFrame |source|, copies pixel in an unrotated rectangle +// |source_rect| into the target rectangle of another DesktopFrame |target|. +// Target rectangle here is the rotated |source_rect| plus |target_offset|. +// |rotation| specifies |source| to |target| rotation. |source_rect| is in +// |source| coordinate. |target_offset| is in |target| coordinate. +// This function triggers check failure if |source| does not cover the +// |source_rect|, or |target| does not cover the rotated |rect|. +void RotateDesktopFrame(const DesktopFrame& source, + const DesktopRect& source_rect, + const Rotation& rotation, + const DesktopVector& target_offset, + DesktopFrame* target); + +// Returns a reverse rotation of |rotation|. +Rotation ReverseRotation(Rotation rotation); + +// Returns a rotated DesktopSize of |size|. +DesktopSize RotateSize(DesktopSize size, Rotation rotation); + +// Returns a rotated DesktopRect of |rect|. The |size| represents the size of +// the DesktopFrame which |rect| belongs in. +DesktopRect RotateRect(DesktopRect rect, DesktopSize size, Rotation rotation); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DESKTOP_FRAME_ROTATION_H_ diff --git a/include/webrtc/modules/desktop_capture/desktop_frame_win.h b/include/webrtc/modules/desktop_capture/desktop_frame_win.h index 3513e14..faf3c8d 100644 --- a/include/webrtc/modules/desktop_capture/desktop_frame_win.h +++ b/include/webrtc/modules/desktop_capture/desktop_frame_win.h @@ -25,10 +25,10 @@ namespace webrtc { // Frame data is stored in a GDI bitmap. class DesktopFrameWin : public DesktopFrame { public: - virtual ~DesktopFrameWin(); - static DesktopFrameWin* Create(DesktopSize size, - SharedMemoryFactory* shared_memory_factory, - HDC hdc); + ~DesktopFrameWin() override; + + static std::unique_ptr + Create(DesktopSize size, SharedMemoryFactory* shared_memory_factory, HDC hdc); HBITMAP bitmap() { return bitmap_; } diff --git a/include/webrtc/modules/desktop_capture/desktop_geometry.h b/include/webrtc/modules/desktop_capture/desktop_geometry.h index 047eeec..8e9b918 100644 --- a/include/webrtc/modules/desktop_capture/desktop_geometry.h +++ b/include/webrtc/modules/desktop_capture/desktop_geometry.h @@ -128,6 +128,16 @@ class DesktopRect { void Translate(int32_t dx, int32_t dy); void Translate(DesktopVector d) { Translate(d.x(), d.y()); }; + // Enlarges current DesktopRect by subtracting |left_offset| and |top_offset| + // from |left_| and |top_|, and adding |right_offset| and |bottom_offset| to + // |right_| and |bottom_|. This function does not normalize the result, so + // |left_| and |top_| may be less than zero or larger than |right_| and + // |bottom_|. + void Extend(int32_t left_offset, + int32_t top_offset, + int32_t right_offset, + int32_t bottom_offset); + private: DesktopRect(int32_t left, int32_t top, int32_t right, int32_t bottom) : left_(left), top_(top), right_(right), bottom_(bottom) { diff --git a/include/webrtc/modules/desktop_capture/differ.h b/include/webrtc/modules/desktop_capture/differ.h deleted file mode 100644 index 9ab059b..0000000 --- a/include/webrtc/modules/desktop_capture/differ.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_H_ -#define WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_H_ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/desktop_capture/desktop_region.h" - -namespace webrtc { - -// TODO(sergeyu): Simplify differ now that we are working with DesktopRegion. -// diff_info_ should no longer be needed, as we can put our data directly into -// the region that we are calculating. -// http://crbug.com/92379 -// TODO(sergeyu): Rename this class to something more sensible, e.g. -// ScreenCaptureFrameDifferencer. -class Differ { - public: - // Create a differ that operates on bitmaps with the specified width, height - // and bytes_per_pixel. - Differ(int width, int height, int bytes_per_pixel, int stride); - ~Differ(); - - int width() { return width_; } - int height() { return height_; } - int bytes_per_pixel() { return bytes_per_pixel_; } - int bytes_per_row() { return bytes_per_row_; } - - // Given the previous and current screen buffer, calculate the dirty region - // that encloses all of the changed pixels in the new screen. - void CalcDirtyRegion(const uint8_t* prev_buffer, const uint8_t* curr_buffer, - DesktopRegion* region); - - private: - // Allow tests to access our private parts. - friend class DifferTest; - - // Identify all of the blocks that contain changed pixels. - void MarkDirtyBlocks(const uint8_t* prev_buffer, const uint8_t* curr_buffer); - - // After the dirty blocks have been identified, this routine merges adjacent - // blocks into a region. - // The goal is to minimize the region that covers the dirty blocks. - void MergeBlocks(DesktopRegion* region); - - // Checks whether the upper-left portions of the buffers are equal. The size - // of the portion to check is specified by the |width| and |height| values. - // Note that if we force the capturer to always return images whose width and - // height are multiples of kBlockSize, then this will never be called. - bool PartialBlocksEqual(const uint8_t* prev_buffer, - const uint8_t* curr_buffer, - int stride, - int width, int height); - - // Dimensions of screen. - int width_; - int height_; - - // Number of bytes for each pixel in source and dest bitmap. - // (Yes, they must match.) - int bytes_per_pixel_; - - // Number of bytes in each row of the image (AKA: stride). - int bytes_per_row_; - - // Diff information for each block in the image. - std::unique_ptr diff_info_; - - // Dimensions and total size of diff info array. - int diff_info_width_; - int diff_info_height_; - int diff_info_size_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Differ); -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_H_ diff --git a/include/webrtc/modules/desktop_capture/differ_block.h b/include/webrtc/modules/desktop_capture/differ_block.h index e1d487d..97fe3bc 100644 --- a/include/webrtc/modules/desktop_capture/differ_block.h +++ b/include/webrtc/modules/desktop_capture/differ_block.h @@ -22,6 +22,17 @@ const int kBlockSize = 32; // Format: BGRA 32 bit. const int kBytesPerPixel = 4; +// Low level function to compare 2 vectors of pixels of size kBlockSize. Returns +// whether the blocks differ. +bool VectorDifference(const uint8_t* image1, const uint8_t* image2); + +// Low level function to compare 2 blocks of pixels of size +// (kBlockSize, |height|). Returns whether the blocks differ. +bool BlockDifference(const uint8_t* image1, + const uint8_t* image2, + int height, + int stride); + // Low level function to compare 2 blocks of pixels of size // (kBlockSize, kBlockSize). Returns whether the blocks differ. bool BlockDifference(const uint8_t* image1, diff --git a/include/webrtc/modules/desktop_capture/differ_block_sse2.h b/include/webrtc/modules/desktop_capture/differ_block_sse2.h deleted file mode 100644 index 90426da..0000000 --- a/include/webrtc/modules/desktop_capture/differ_block_sse2.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This header file is used only differ_block.h. It defines the SSE2 rountines -// for finding block difference. - -#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_BLOCK_SSE2_H_ -#define WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_BLOCK_SSE2_H_ - -#include - -namespace webrtc { - -// Find block difference of dimension 16x16. -extern bool BlockDifference_SSE2_W16(const uint8_t* image1, - const uint8_t* image2, - int stride); - -// Find block difference of dimension 32x32. -extern bool BlockDifference_SSE2_W32(const uint8_t* image1, - const uint8_t* image2, - int stride); - -} // namespace webrtc - -#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_BLOCK_SSE2_H_ diff --git a/include/webrtc/modules/desktop_capture/differ_vector_sse2.h b/include/webrtc/modules/desktop_capture/differ_vector_sse2.h new file mode 100644 index 0000000..353c6b9 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/differ_vector_sse2.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This header file is used only differ_block.h. It defines the SSE2 rountines +// for finding vector difference. + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_VECTOR_SSE2_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_VECTOR_SSE2_H_ + +#include + +namespace webrtc { + +// Find vector difference of dimension 16. +extern bool VectorDifference_SSE2_W16(const uint8_t* image1, + const uint8_t* image2); + +// Find vector difference of dimension 32. +extern bool VectorDifference_SSE2_W32(const uint8_t* image1, + const uint8_t* image2); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_DIFFER_VECTOR_SSE2_H_ diff --git a/include/webrtc/modules/desktop_capture/fake_desktop_capturer.h b/include/webrtc/modules/desktop_capture/fake_desktop_capturer.h new file mode 100644 index 0000000..9cab2d6 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/fake_desktop_capturer.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_FAKE_DESKTOP_CAPTURER_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_FAKE_DESKTOP_CAPTURER_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capture_types.h" +#include "webrtc/modules/desktop_capture/desktop_frame_generator.h" +#include "webrtc/modules/desktop_capture/shared_memory.h" + +namespace webrtc { + +// A fake implementation of DesktopCapturer or its derived interfaces to +// generate DesktopFrame for testing purpose. +// +// Consumers can provide a FrameGenerator instance to generate instances of +// DesktopFrame to return for each Capture() function call. +// If no FrameGenerator provided, FakeDesktopCapturer will always return a +// nullptr DesktopFrame. +// +// Double buffering is guaranteed by the FrameGenerator. FrameGenerator +// implements in desktop_frame_generator.h guarantee double buffering, they +// creates a new instance of DesktopFrame each time. +class FakeDesktopCapturer : public DesktopCapturer { + public: + FakeDesktopCapturer(); + ~FakeDesktopCapturer() override; + + // Decides the result which will be returned in next Capture() callback. + void set_result(DesktopCapturer::Result result); + + // Uses the |generator| provided as DesktopFrameGenerator, FakeDesktopCapturer + // does not take the ownership of |generator|. + void set_frame_generator(DesktopFrameGenerator* generator); + + // Count of DesktopFrame(s) have been returned by this instance. This field + // would never be negative. + int num_frames_captured() const; + + // Count of CaptureFrame() calls have been made. This field would never be + // negative. + int num_capture_attempts() const; + + // DesktopCapturer interface + void Start(DesktopCapturer::Callback* callback) override; + void CaptureFrame() override; + void SetSharedMemoryFactory( + std::unique_ptr shared_memory_factory) override; + bool GetSourceList(DesktopCapturer::SourceList* sources) override; + bool SelectSource(DesktopCapturer::SourceId id) override; + + private: + static constexpr DesktopCapturer::SourceId kWindowId = 1378277495; + static constexpr DesktopCapturer::SourceId kScreenId = 1378277496; + + DesktopCapturer::Callback* callback_ = nullptr; + std::unique_ptr shared_memory_factory_; + DesktopCapturer::Result result_ = Result::SUCCESS; + DesktopFrameGenerator* generator_ = nullptr; + int num_frames_captured_ = 0; + int num_capture_attempts_ = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_FAKE_DESKTOP_CAPTURER_H_ diff --git a/include/webrtc/modules/desktop_capture/fallback_desktop_capturer_wrapper.h b/include/webrtc/modules/desktop_capture/fallback_desktop_capturer_wrapper.h new file mode 100644 index 0000000..b6436ce --- /dev/null +++ b/include/webrtc/modules/desktop_capture/fallback_desktop_capturer_wrapper.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capture_types.h" +#include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/shared_memory.h" + +namespace webrtc { + +// A DesktopCapturer wrapper owns two DesktopCapturer implementations. If the +// main DesktopCapturer fails, it uses the secondary one instead. Two capturers +// are expected to return same SourceList, and the meaning of each SourceId is +// identical, otherwise FallbackDesktopCapturerWrapper may return frames from +// different sources. Using asynchronized DesktopCapturer implementations with +// SharedMemoryFactory is not supported, and may result crash or assertion +// failure. +class FallbackDesktopCapturerWrapper final : public DesktopCapturer, + public DesktopCapturer::Callback { + public: + FallbackDesktopCapturerWrapper( + std::unique_ptr main_capturer, + std::unique_ptr secondary_capturer); + ~FallbackDesktopCapturerWrapper() override; + + // DesktopCapturer interface. + void Start(DesktopCapturer::Callback* callback) override; + void SetSharedMemoryFactory( + std::unique_ptr shared_memory_factory) override; + void CaptureFrame() override; + void SetExcludedWindow(WindowId window) override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + bool FocusOnSelectedSource() override; + + private: + // DesktopCapturer::Callback interface. + void OnCaptureResult(Result result, + std::unique_ptr frame) override; + + const std::unique_ptr main_capturer_; + const std::unique_ptr secondary_capturer_; + std::unique_ptr shared_memory_factory_; + bool main_capturer_permanent_error_ = false; + DesktopCapturer::Callback* callback_ = nullptr; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_FALLBACK_DESKTOP_CAPTURER_WRAPPER_H_ diff --git a/include/webrtc/modules/desktop_capture/mac/desktop_configuration.h b/include/webrtc/modules/desktop_capture/mac/desktop_configuration.h index bb2339b..d54d0fb 100644 --- a/include/webrtc/modules/desktop_capture/mac/desktop_configuration.h +++ b/include/webrtc/modules/desktop_capture/mac/desktop_configuration.h @@ -12,7 +12,6 @@ #define WEBRTC_MODULES_DESKTOP_CAPTURE_MAC_DESKTOP_CONFIGURATION_H_ #include -#include #include #include "webrtc/typedefs.h" @@ -23,9 +22,15 @@ namespace webrtc { // Describes the configuration of a specific display. struct MacDisplayConfiguration { MacDisplayConfiguration(); + MacDisplayConfiguration(const MacDisplayConfiguration& other); + MacDisplayConfiguration(MacDisplayConfiguration&& other); + ~MacDisplayConfiguration(); + + MacDisplayConfiguration& operator=(const MacDisplayConfiguration& other); + MacDisplayConfiguration& operator=(MacDisplayConfiguration&& other); // Cocoa identifier for this display. - CGDirectDisplayID id; + CGDirectDisplayID id = 0; // Bounds of this display in Density-Independent Pixels (DIPs). DesktopRect bounds; @@ -34,7 +39,7 @@ struct MacDisplayConfiguration { DesktopRect pixel_bounds; // Scale factor from DIPs to physical pixels. - float dip_to_pixel_scale; + float dip_to_pixel_scale = 1.0f; }; typedef std::vector MacDisplayConfigurations; @@ -45,11 +50,16 @@ struct MacDesktopConfiguration { enum Origin { BottomLeftOrigin, TopLeftOrigin }; MacDesktopConfiguration(); + MacDesktopConfiguration(const MacDesktopConfiguration& other); + MacDesktopConfiguration(MacDesktopConfiguration&& other); ~MacDesktopConfiguration(); + MacDesktopConfiguration& operator=(const MacDesktopConfiguration& other); + MacDesktopConfiguration& operator=(MacDesktopConfiguration&& other); + // Returns the desktop & display configurations in Cocoa-style "bottom-up" // (the origin is the bottom-left of the primary monitor, and coordinates - // increase as you move up the screen) or Carbon-style "top-down" coordinates. + // increase as you move up the screen). static MacDesktopConfiguration GetCurrent(Origin origin); // Returns true if the given desktop configuration equals this one. @@ -67,7 +77,7 @@ struct MacDesktopConfiguration { DesktopRect pixel_bounds; // Scale factor from DIPs to physical pixels. - float dip_to_pixel_scale; + float dip_to_pixel_scale = 1.0f; // Configurations of the displays making up the desktop area. MacDisplayConfigurations displays; diff --git a/include/webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h b/include/webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h index 838966d..7a10b42 100644 --- a/include/webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h +++ b/include/webrtc/modules/desktop_capture/mac/full_screen_chrome_window_detector.h @@ -14,7 +14,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/desktop_capture/window_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/system_wrappers/include/atomic32.h" namespace webrtc { @@ -57,8 +57,8 @@ class FullScreenChromeWindowDetector { // |previous_window_list_| is taken at least 500ms before the next Capture() // call. If we only save the last result, we may get false positive (i.e. // full-screen window exists in the list) if Capture() is called too soon. - WindowCapturer::WindowList current_window_list_; - WindowCapturer::WindowList previous_window_list_; + DesktopCapturer::SourceList current_window_list_; + DesktopCapturer::SourceList previous_window_list_; int64_t last_update_time_ns_; RTC_DISALLOW_COPY_AND_ASSIGN(FullScreenChromeWindowDetector); diff --git a/include/webrtc/modules/desktop_capture/mac/window_list_utils.h b/include/webrtc/modules/desktop_capture/mac/window_list_utils.h index d56166f..7cc4571 100644 --- a/include/webrtc/modules/desktop_capture/mac/window_list_utils.h +++ b/include/webrtc/modules/desktop_capture/mac/window_list_utils.h @@ -13,17 +13,17 @@ #include +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/modules/desktop_capture/mac/desktop_configuration.h" -#include "webrtc/modules/desktop_capture/window_capturer.h" namespace webrtc { -// A helper function to get the on-screen windows. -bool GetWindowList(WindowCapturer::WindowList* windows); +// Another helper function to get the on-screen windows. +bool GetWindowList(DesktopCapturer::SourceList* windows, bool ignore_minimized); // Returns true if the window is occupying a full screen. bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config, - CFDictionaryRef window); + CFDictionaryRef window); // Returns true if the window is minimized. bool IsWindowMinimized(CGWindowID id); diff --git a/include/webrtc/modules/desktop_capture/mock_desktop_capturer_callback.h b/include/webrtc/modules/desktop_capture/mock_desktop_capturer_callback.h new file mode 100644 index 0000000..720075d --- /dev/null +++ b/include/webrtc/modules/desktop_capture/mock_desktop_capturer_callback.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_MOCK_DESKTOP_CAPTURER_CALLBACK_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_MOCK_DESKTOP_CAPTURER_CALLBACK_H_ + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" + +#include + +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockDesktopCapturerCallback : public DesktopCapturer::Callback { + public: + MockDesktopCapturerCallback(); + ~MockDesktopCapturerCallback() override; + + MOCK_METHOD2(OnCaptureResultPtr, + void(DesktopCapturer::Result result, + std::unique_ptr* frame)); + void OnCaptureResult(DesktopCapturer::Result result, + std::unique_ptr frame) final; + + private: + RTC_DISALLOW_COPY_AND_ASSIGN(MockDesktopCapturerCallback); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_MOCK_DESKTOP_CAPTURER_CALLBACK_H_ diff --git a/include/webrtc/modules/desktop_capture/resolution_change_detector.h b/include/webrtc/modules/desktop_capture/resolution_change_detector.h new file mode 100644 index 0000000..6ccf8a7 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/resolution_change_detector.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_RESOLUTION_CHANGE_DETECTOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_RESOLUTION_CHANGE_DETECTOR_H_ + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" + +namespace webrtc { + +class ResolutionChangeDetector { + public: + bool IsChanged(DesktopSize size); + void Reset(); + + private: + DesktopSize last_size_; + bool initialized_ = false; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_RESOLUTION_CHANGE_DETECTOR_H_ diff --git a/include/webrtc/modules/desktop_capture/rgba_color.h b/include/webrtc/modules/desktop_capture/rgba_color.h new file mode 100644 index 0000000..1236d03 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/rgba_color.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_RGBA_COLOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_RGBA_COLOR_H_ + +#include + +#include "webrtc/modules/desktop_capture/desktop_frame.h" + +namespace webrtc { + +// A four-byte structure to store a color in BGRA format. This structure also +// provides functions to be created from uint8_t array, say, +// DesktopFrame::data(). It always uses BGRA order for internal storage to match +// DesktopFrame::data(). +// +// This struct is for testing purpose only, and should not be used in production +// logic. +struct RgbaColor final { + // Creates a color with BGRA channels. + RgbaColor(uint8_t blue, uint8_t green, uint8_t red, uint8_t alpha); + + // Creates a color with BGR channels, and set alpha channel to 255 (opaque). + RgbaColor(uint8_t blue, uint8_t green, uint8_t red); + + // Creates a color from four-byte in BGRA order, i.e. DesktopFrame::data(). + explicit RgbaColor(const uint8_t* bgra); + + // Creates a color from BGRA channels in a uint format. Consumers should make + // sure the memory order of the uint32_t is always BGRA from left to right, no + // matter the system endian. This function creates an equivalent RgbaColor + // instance from the ToUInt32() result of another RgbaColor instance. + explicit RgbaColor(uint32_t bgra); + + // Returns true if |this| and |right| is the same color. + bool operator==(const RgbaColor& right) const; + + // Returns true if |this| and |right| are different colors. + bool operator!=(const RgbaColor& right) const; + + uint32_t ToUInt32() const; + + uint8_t blue; + uint8_t green; + uint8_t red; + uint8_t alpha; +}; +static_assert( + DesktopFrame::kBytesPerPixel == sizeof(RgbaColor), + "A pixel in DesktopFrame should be safe to be represented by a RgbaColor"); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_RGBA_COLOR_H_ diff --git a/include/webrtc/modules/desktop_capture/screen_capture_frame_queue.h b/include/webrtc/modules/desktop_capture/screen_capture_frame_queue.h index 97f3b81..b7945b0 100644 --- a/include/webrtc/modules/desktop_capture/screen_capture_frame_queue.h +++ b/include/webrtc/modules/desktop_capture/screen_capture_frame_queue.h @@ -49,8 +49,8 @@ class ScreenCaptureFrameQueue { // Replaces the current frame with a new one allocated by the caller. The // existing frame (if any) is destroyed. Takes ownership of |frame|. - void ReplaceCurrentFrame(FrameType* frame) { - frames_[current_].reset(frame); + void ReplaceCurrentFrame(std::unique_ptr frame) { + frames_[current_] = std::move(frame); } // Marks all frames obsolete and resets the previous frame pointer. No diff --git a/include/webrtc/modules/desktop_capture/screen_capturer.h b/include/webrtc/modules/desktop_capture/screen_capturer.h deleted file mode 100644 index 48ecc31..0000000 --- a/include/webrtc/modules/desktop_capture/screen_capturer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_H_ -#define WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_H_ - -#include - -#include "webrtc/modules/desktop_capture/desktop_capture_types.h" -#include "webrtc/modules/desktop_capture/desktop_capturer.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class DesktopCaptureOptions; - -// Class used to capture video frames asynchronously. -// -// The full capture sequence is as follows: -// -// (1) Start -// This is when pre-capture steps are executed, such as flagging the -// display to prevent it from sleeping during a session. -// -// (2) CaptureFrame -// This is where the bits for the invalid rects are packaged up and sent -// to the encoder. -// A screen capture is performed if needed. For example, Windows requires -// a capture to calculate the diff from the previous screen, whereas the -// Mac version does not. -// -// Implementation has to ensure the following guarantees: -// 1. Double buffering -// Since data can be read while another capture action is happening. -class ScreenCapturer : public DesktopCapturer { - public: - // Use a struct to represent a screen although it has only an id for now, - // because we may want to add more fields (e.g. description) in the future. - struct Screen { - ScreenId id; - }; - typedef std::vector ScreenList; - - virtual ~ScreenCapturer() {} - - // Creates a platform-specific capturer. - static ScreenCapturer* Create(const DesktopCaptureOptions& options); - - // Get the list of screens (not containing kFullDesktopScreenId). Returns - // false in case of a failure. - virtual bool GetScreenList(ScreenList* screens) = 0; - - // Select the screen to be captured. Returns false in case of a failure (e.g. - // if there is no screen with the specified id). If this is never called, the - // full desktop is captured. - virtual bool SelectScreen(ScreenId id) = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_H_ diff --git a/include/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h b/include/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h deleted file mode 100644 index 7264249..0000000 --- a/include/webrtc/modules/desktop_capture/screen_capturer_mock_objects.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_MOCK_OBJECTS_H_ -#define WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_MOCK_OBJECTS_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/desktop_capture/screen_capturer.h" - -namespace webrtc { - -class MockScreenCapturer : public ScreenCapturer { - public: - MockScreenCapturer() {} - virtual ~MockScreenCapturer() {} - - MOCK_METHOD1(Start, void(Callback* callback)); - MOCK_METHOD1(Capture, void(const DesktopRegion& region)); - MOCK_METHOD1(GetScreenList, bool(ScreenList* screens)); - MOCK_METHOD1(SelectScreen, bool(ScreenId id)); - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(MockScreenCapturer); -}; - -class MockScreenCapturerCallback : public ScreenCapturer::Callback { - public: - MockScreenCapturerCallback() {} - virtual ~MockScreenCapturerCallback() {} - - MOCK_METHOD1(OnCaptureCompleted, void(DesktopFrame*)); - - private: - RTC_DISALLOW_COPY_AND_ASSIGN(MockScreenCapturerCallback); -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_MOCK_OBJECTS_H_ diff --git a/include/webrtc/modules/desktop_capture/screen_drawer.h b/include/webrtc/modules/desktop_capture/screen_drawer.h new file mode 100644 index 0000000..cde9a2e --- /dev/null +++ b/include/webrtc/modules/desktop_capture/screen_drawer.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_DRAWER_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_DRAWER_H_ + +#include + +#include + +#include "webrtc/modules/desktop_capture/rgba_color.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" + +namespace webrtc { + +// A cross-process lock to ensure only one ScreenDrawer can be used at a certain +// time. +class ScreenDrawerLock { + public: + virtual ~ScreenDrawerLock(); + + static std::unique_ptr Create(); + + protected: + ScreenDrawerLock(); +}; + +// A set of basic platform dependent functions to draw various shapes on the +// screen. +class ScreenDrawer { + public: + // Creates a ScreenDrawer for the current platform, returns nullptr if no + // ScreenDrawer implementation available. + // If the implementation cannot guarantee two ScreenDrawer instances won't + // impact each other, this function may block current thread until another + // ScreenDrawer has been destroyed. + static std::unique_ptr Create(); + + ScreenDrawer(); + virtual ~ScreenDrawer(); + + // Returns the region inside which DrawRectangle() function are expected to + // work, in capturer coordinates (assuming ScreenCapturer::SelectScreen has + // not been called). This region may exclude regions of the screen reserved by + // the OS for things like menu bars or app launchers. + virtual DesktopRect DrawableRegion() = 0; + + // Draws a rectangle to cover |rect| with |color|. Note, rect.bottom() and + // rect.right() two lines are not included. The part of |rect| which is out of + // DrawableRegion() will be ignored. + virtual void DrawRectangle(DesktopRect rect, RgbaColor color) = 0; + + // Clears all content on the screen by filling the area with black. + virtual void Clear() = 0; + + // Blocks current thread until OS finishes previous DrawRectangle() actions. + // ScreenCapturer should be able to capture the changes after this function + // finish. + virtual void WaitForPendingDraws() = 0; + + // Returns true if incomplete shapes previous actions required may be drawn on + // the screen after a WaitForPendingDraws() call. i.e. Though the complete + // shapes will eventually be drawn on the screen, due to some OS limitations, + // these shapes may be partially appeared sometimes. + virtual bool MayDrawIncompleteShapes() = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_SCREEN_DRAWER_H_ diff --git a/include/webrtc/modules/desktop_capture/shared_desktop_frame.h b/include/webrtc/modules/desktop_capture/shared_desktop_frame.h index 4f6a2bb..f4c3b67 100644 --- a/include/webrtc/modules/desktop_capture/shared_desktop_frame.h +++ b/include/webrtc/modules/desktop_capture/shared_desktop_frame.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_DESKTOP_CAPTURE_SHARED_DESKTOP_FRAME_H_ #include "webrtc/base/constructormagic.h" +#include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/modules/desktop_capture/desktop_frame.h" @@ -21,22 +22,27 @@ namespace webrtc { // sharing the same buffer. class SharedDesktopFrame : public DesktopFrame { public: - virtual ~SharedDesktopFrame(); + ~SharedDesktopFrame() override; + static std::unique_ptr Wrap( + std::unique_ptr desktop_frame); + + // Deprecated. + // TODO(sergeyu): remove this method. static SharedDesktopFrame* Wrap(DesktopFrame* desktop_frame); // Returns the underlying instance of DesktopFrame. DesktopFrame* GetUnderlyingFrame(); // Creates a clone of this object. - SharedDesktopFrame* Share(); + std::unique_ptr Share(); // Checks if the frame is currently shared. If it returns false it's // guaranteed that there are no clones of the object. bool IsShared(); private: - class Core; + typedef rtc::RefCountedObject> Core; SharedDesktopFrame(rtc::scoped_refptr core); diff --git a/include/webrtc/modules/desktop_capture/shared_memory.h b/include/webrtc/modules/desktop_capture/shared_memory.h index 6e15f23..e654d95 100644 --- a/include/webrtc/modules/desktop_capture/shared_memory.h +++ b/include/webrtc/modules/desktop_capture/shared_memory.h @@ -20,6 +20,7 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/thread_checker.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/desktop_capture/test_utils.h b/include/webrtc/modules/desktop_capture/test_utils.h new file mode 100644 index 0000000..ca27298 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/test_utils.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_TEST_UTILS_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_TEST_UTILS_H_ + +#include "webrtc/modules/desktop_capture/desktop_frame.h" + +namespace webrtc { + +// Clears a DesktopFrame |frame| by setting its data() into 0. +void ClearDesktopFrame(DesktopFrame* frame); + +// Compares size() and data() of two DesktopFrames |left| and |right|. +bool DesktopFrameDataEquals(const DesktopFrame& left, + const DesktopFrame& right); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_TEST_UTILS_H_ diff --git a/include/webrtc/modules/desktop_capture/win/d3d_device.h b/include/webrtc/modules/desktop_capture/win/d3d_device.h new file mode 100644 index 0000000..41efa84 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/d3d_device.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_D3D_DEVICE_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_D3D_DEVICE_H_ + +#include +#include +#include +#include + +#include + +namespace webrtc { + +// A wrapper of ID3D11Device and its corresponding context and IDXGIAdapter. +// This class represents one video card in the system. +class D3dDevice { + public: + D3dDevice(const D3dDevice& other); + D3dDevice(D3dDevice&& other); + ~D3dDevice(); + + ID3D11Device* d3d_device() const { return d3d_device_.Get(); } + + ID3D11DeviceContext* context() const { return context_.Get(); } + + IDXGIDevice* dxgi_device() const { return dxgi_device_.Get(); } + + IDXGIAdapter* dxgi_adapter() const { return dxgi_adapter_.Get(); } + + // Returns all D3dDevice instances on the system. Returns an empty vector if + // anything wrong. + static std::vector EnumDevices(); + + private: + // Instances of D3dDevice should only be created by EnumDevices() static + // function. + D3dDevice(); + + // Initializes the D3dDevice from an IDXGIAdapter. + bool Initialize(const Microsoft::WRL::ComPtr& adapter); + + Microsoft::WRL::ComPtr d3d_device_; + Microsoft::WRL::ComPtr context_; + Microsoft::WRL::ComPtr dxgi_device_; + Microsoft::WRL::ComPtr dxgi_adapter_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_D3D_DEVICE_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h b/include/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h new file mode 100644 index 0000000..a1ef043 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_ADAPTER_DUPLICATOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_ADAPTER_DUPLICATOR_H_ + +#include + +#include + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/shared_desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/d3d_device.h" +#include "webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h" + +namespace webrtc { + +// A container of DxgiOutputDuplicators to duplicate monitors attached to a +// single video card. +class DxgiAdapterDuplicator { + public: + struct Context { + Context(); + Context(const Context& other); + ~Context(); + + // Child DxgiOutputDuplicator::Context belongs to this + // DxgiAdapterDuplicator::Context. + std::vector contexts; + }; + + // Creates an instance of DxgiAdapterDuplicator from a D3dDevice. Only + // DxgiDuplicatorController can create an instance. + explicit DxgiAdapterDuplicator(const D3dDevice& device); + + // Move constructor, to make it possible to store instances of + // DxgiAdapterDuplicator in std::vector<>. + DxgiAdapterDuplicator(DxgiAdapterDuplicator&& other); + + ~DxgiAdapterDuplicator(); + + // Initializes the DxgiAdapterDuplicator from a D3dDevice. + bool Initialize(); + + // Sequentially calls Duplicate function of all the DxgiOutputDuplicator + // instances owned by this instance, and writes into |target|. + bool Duplicate(Context* context, SharedDesktopFrame* target); + + // Captures one monitor and writes into |target|. |monitor_id| should be + // between [0, screen_count()). + bool DuplicateMonitor(Context* context, + int monitor_id, + SharedDesktopFrame* target); + + // Returns desktop rect covered by this DxgiAdapterDuplicator. + DesktopRect desktop_rect() const { return desktop_rect_; } + + // Returns the size of one screen owned by this DxgiAdapterDuplicator. |id| + // should be between [0, screen_count()). + DesktopRect ScreenRect(int id) const; + + // Returns the count of screens owned by this DxgiAdapterDuplicator. These + // screens can be retrieved by an interger in the range of + // [0, screen_count()). + int screen_count() const; + + void Setup(Context* context); + + void Unregister(const Context* const context); + + // The minimum num_frames_captured() returned by |duplicators_|. + int64_t GetNumFramesCaptured() const; + + private: + bool DoInitialize(); + + const D3dDevice device_; + std::vector duplicators_; + DesktopRect desktop_rect_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_ADAPTER_DUPLICATOR_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/include/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h new file mode 100644 index 0000000..310eff0 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ + +#include + +#include +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/resolution_change_detector.h" +#include "webrtc/modules/desktop_capture/shared_desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/d3d_device.h" +#include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h" + +namespace webrtc { + +// A controller for all the objects we need to call Windows DirectX capture APIs +// It's a singleton because only one IDXGIOutputDuplication instance per monitor +// is allowed per application. +// +// Consumers should create a DxgiDuplicatorController::Context and keep it +// throughout their lifetime, and pass it when calling Duplicate(). Consumers +// can also call IsSupported() to determine whether the system supports DXGI +// duplicator or not. If a previous IsSupported() function call returns true, +// but a later Duplicate() returns false, this usually means the display mode is +// changing. Consumers should retry after a while. (Typically 50 milliseconds, +// but according to hardware performance, this time may vary.) +class DxgiDuplicatorController { + public: + // A context to store the status of a single consumer of + // DxgiDuplicatorController. + class Context { + public: + Context(); + // Unregister this Context instance from all Dxgi duplicators during + // destructing. + ~Context(); + + // Reset current Context, so it will be reinitialized next time. + void Reset(); + + private: + friend class DxgiDuplicatorController; + + // A Context will have an exactly same |identity_| as + // DxgiDuplicatorController, to ensure it has been correctly setted up after + // each DxgiDuplicatorController::Initialize(). + int identity_ = 0; + + // Child DxgiAdapterDuplicator::Context belongs to this Context. + std::vector contexts_; + }; + + // A collection of D3d information we are interested on, which may impact + // capturer performance or reliability. + struct D3dInfo { + // Each video adapter has its own D3D_FEATURE_LEVEL, so this structure + // contains the minimum and maximium D3D_FEATURE_LEVELs current system + // supports. + // Both fields can be 0, which is the default value to indicate no valid + // D3D_FEATURE_LEVEL has been retrieved from underlying OS APIs. + D3D_FEATURE_LEVEL min_feature_level; + D3D_FEATURE_LEVEL max_feature_level; + + // TODO(zijiehe): Add more fields, such as manufacturer name, mode, driver + // version. + }; + + // Returns the singleton instance of DxgiDuplicatorController. + static DxgiDuplicatorController* Instance(); + + // Destructs current instance. We need to make sure COM components and their + // containers are destructed in correct order. + ~DxgiDuplicatorController(); + + // All the following functions implicitly call Initialize() function if + // current instance has not been initialized. + + // Detects whether the system supports DXGI based capturer. + bool IsSupported(); + + // Calls Deinitialize() function with lock. Consumers can call this function + // to force the DxgiDuplicatorController to be reinitialized to avoid an + // expected failure in next Duplicate() call. + void Reset(); + + // Returns a copy of D3dInfo composed by last Initialize() function call. + bool RetrieveD3dInfo(D3dInfo* info); + + // Captures current screen and writes into target. Since we are using double + // buffering, |last_frame|.updated_region() is used to represent the not + // updated regions in current |target| frame, which should also be copied this + // time. + // TODO(zijiehe): Windows cannot guarantee the frames returned by each + // IDXGIOutputDuplication are synchronized. But we are using a totally + // different threading model than the way Windows suggested, it's hard to + // synchronize them manually. We should find a way to do it. + bool Duplicate(Context* context, SharedDesktopFrame* target); + + // Captures one monitor and writes into target. |monitor_id| should >= 0. If + // |monitor_id| is greater than the total screen count of all the Duplicators, + // this function returns false. + bool DuplicateMonitor(Context* context, + int monitor_id, + SharedDesktopFrame* target); + + // Returns dpi of current system. Returns an empty DesktopVector if system + // does not support DXGI based capturer. + DesktopVector dpi(); + + // Returns entire desktop size. Returns an empty DesktopRect if system does + // not support DXGI based capturer. + DesktopRect desktop_rect(); + + // Returns a DesktopSize to cover entire desktop_rect. This may be different + // than desktop_rect().size(), since top-left screen does not need to start + // from (0, 0). + DesktopSize desktop_size(); + + // Returns the size of one screen. |monitor_id| should be >= 0. If system does + // not support DXGI based capturer, or |monitor_id| is greater than the total + // screen count of all the Duplicators, this function returns an empty + // DesktopRect. + DesktopRect ScreenRect(int id); + + // Returns the count of screens on the system. These screens can be retrieved + // by an integer in the range of [0, ScreenCount()). If system does not + // support DXGI based capturer, this function returns 0. + int ScreenCount(); + + private: + // Context calls private Unregister(Context*) function during + // destructing. + friend class Context; + + // A private constructor to ensure consumers to use + // DxgiDuplicatorController::Instance(). + DxgiDuplicatorController(); + + // Unregisters Context from this instance and all DxgiAdapterDuplicator(s) + // it owns. + void Unregister(const Context* const context); + + // All functions below should be called in |lock_| locked scope. + + // If current instance has not been initialized, executes DoInitialize + // function, and returns initialize result. Otherwise directly returns true. + bool Initialize(); + + bool DoInitialize(); + + // Clears all COM components referred by this instance. So next Duplicate() + // call will eventually initialize this instance again. + void Deinitialize(); + + // A helper function to check whether a Context has been expired. + bool ContextExpired(const Context* const context) const; + + // Updates Context if needed. + void Setup(Context* context); + + // Does the real duplication work. |monitor_id < 0| to capture entire screen. + bool DoDuplicate(Context* context, + int monitor_id, + SharedDesktopFrame* target); + + bool DoDuplicateUnlocked(Context* context, + int monitor_id, + SharedDesktopFrame* target); + + // Captures all monitors. + bool DoDuplicateAll(Context* context, SharedDesktopFrame* target); + + // Captures one monitor. + bool DoDuplicateOne(Context* context, + int monitor_id, + SharedDesktopFrame* target); + + // The minimum GetNumFramesCaptured() returned by |duplicators_|. + int64_t GetNumFramesCaptured() const; + + int ScreenCountUnlocked(); + + // Retries DoDuplicateAll() for several times until GetNumFramesCaptured() is + // large enough. Returns false if DoDuplicateAll() returns false, or + // GetNumFramesCaptured() has never reached the requirement. + // According to http://crbug.com/682112, dxgi capturer returns a black frame + // during first several capture attempts. + bool EnsureFrameCaptured(Context* context, SharedDesktopFrame* target); + + // This lock must be locked whenever accessing any of the following objects. + rtc::CriticalSection lock_; + + // A self-incremented integer to compare with the one in Context, to + // ensure a Context has been initialized after DxgiDuplicatorController. + int identity_ = 0; + DesktopRect desktop_rect_; + DesktopVector dpi_; + std::vector duplicators_; + D3dInfo d3d_info_; + ResolutionChangeDetector resolution_change_detector_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_DUPLICATOR_CONTROLLER_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h b/include/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h new file mode 100644 index 0000000..5a7053a --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_output_duplicator.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_ + +#include +#include +#include +#include + +#include +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/desktop_frame_rotation.h" +#include "webrtc/modules/desktop_capture/shared_desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/d3d_device.h" +#include "webrtc/modules/desktop_capture/win/dxgi_texture.h" + +namespace webrtc { + +// Duplicates the content on one IDXGIOutput, i.e. one monitor attached to one +// video card. None of functions in this class is thread-safe. +class DxgiOutputDuplicator { + public: + struct Context { + // The updated region DxgiOutputDuplicator::DetectUpdatedRegion() output + // during last Duplicate() function call. It's a DesktopRegion translated by + // offset of each DxgiOutputDuplicator instance. + DesktopRegion updated_region; + }; + + // Creates an instance of DxgiOutputDuplicator from a D3dDevice and one of its + // IDXGIOutput1. Caller must maintain the lifetime of device, to make sure it + // outlives this instance. Only DxgiAdapterDuplicator can create an instance. + DxgiOutputDuplicator(const D3dDevice& device, + const Microsoft::WRL::ComPtr& output, + const DXGI_OUTPUT_DESC& desc); + + // To allow this class to work with vector. + DxgiOutputDuplicator(DxgiOutputDuplicator&& other); + + // Destructs this instance. We need to make sure texture_ has been released + // before duplication_. + ~DxgiOutputDuplicator(); + + // Initializes duplication_ object. + bool Initialize(); + + // Copies the content of current IDXGIOutput to the |target|. To improve the + // performance, this function copies only regions merged from + // |context|->updated_region and DetectUpdatedRegion(). The |offset| decides + // the offset in the |target| where the content should be copied to. i.e. this + // function copies the content to the rectangle of (offset.x(), offset.y()) to + // (offset.x() + desktop_rect_.width(), offset.y() + desktop_rect_.height()). + // Returns false in case of a failure. + bool Duplicate(Context* context, + DesktopVector offset, + SharedDesktopFrame* target); + + // Returns the desktop rect covered by this DxgiOutputDuplicator. + DesktopRect desktop_rect() const { return desktop_rect_; } + + void Setup(Context* context); + + void Unregister(const Context* const context); + + // How many frames have been captured by this DxigOutputDuplicator. + int64_t num_frames_captured() const; + + private: + // Detects updated region translated by offset from IDXGIOutput1. This + // function will set the |updated_region| as entire DesktopRect starts from + // offset if it failed to execute Windows APIs. + void DetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + DesktopVector offset, + DesktopRegion* updated_region); + + // Returns untranslated updated region, which are directly returned by Windows + // APIs. Returns false in case of a failure. + bool DoDetectUpdatedRegion(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + DesktopRegion* updated_region); + + bool ReleaseFrame(); + + // Initializes duplication_ instance. Expects duplication_ is in empty status. + // Returns false if system does not support IDXGIOutputDuplication. + bool DuplicateOutput(); + + // Returns a DesktopRect with the same size of desktop_size_, but translated + // by offset. + DesktopRect TranslatedDesktopRect(DesktopVector offset); + + // Spreads changes from |context| to other registered Context(s) in + // contexts_. + void SpreadContextChange(const Context* const context); + + const D3dDevice device_; + const Microsoft::WRL::ComPtr output_; + const DesktopRect desktop_rect_; + Microsoft::WRL::ComPtr duplication_; + DXGI_OUTDUPL_DESC desc_; + std::vector metadata_; + std::unique_ptr texture_; + Rotation rotation_; + DesktopSize unrotated_size_; + + // After each AcquireNextFrame() function call, updated_region_(s) of all + // active Context(s) need to be updated. Since they have missed the + // change this time. And during next Duplicate() function call, their + // updated_region_ will be merged and copied. + std::vector contexts_; + + // The last full frame of this output and its offset. If on AcquireNextFrame() + // failed because of timeout, i.e. no update, we can copy content from + // |last_frame_|. + std::unique_ptr last_frame_; + DesktopVector last_frame_offset_; + + int64_t num_frames_captured_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_OUTPUT_DUPLICATOR_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_texture.h b/include/webrtc/modules/desktop_capture/win/dxgi_texture.h new file mode 100644 index 0000000..6f3e29b --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_texture.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_H_ + +#include +#include + +#include + +#include "webrtc/modules/desktop_capture/desktop_frame.h" +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/resolution_change_detector.h" + +namespace webrtc { + +class DesktopRegion; + +// A texture copied or mapped from a DXGI_OUTDUPL_FRAME_INFO and IDXGIResource. +class DxgiTexture { + public: + // Creates a DxgiTexture instance, which represents the |desktop_size| area of + // entire screen -- usually a monitor on the system. + DxgiTexture(); + + virtual ~DxgiTexture(); + + // Copies selected regions of a frame represented by frame_info and resource. + // Returns false if anything wrong. + bool CopyFrom(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + IDXGIResource* resource); + + const DesktopSize& desktop_size() const { return desktop_size_; } + + uint8_t* bits() const { return static_cast(rect_.pBits); } + + int pitch() const { return static_cast(rect_.Pitch); } + + // Releases the resource currently holds by this instance. Returns false if + // anything wrong, and this instance should be deprecated in this state. bits, + // pitch and AsDesktopFrame are only valid after a success CopyFrom() call, + // but before Release() call. + bool Release(); + + // Returns a DesktopFrame snapshot of a DxgiTexture instance. This + // DesktopFrame is used to copy a DxgiTexture content to another DesktopFrame + // only. And it should not outlive its DxgiTexture instance. + const DesktopFrame& AsDesktopFrame(); + + protected: + DXGI_MAPPED_RECT* rect(); + + virtual bool CopyFromTexture(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + ID3D11Texture2D* texture) = 0; + + virtual bool DoRelease() = 0; + + private: + DXGI_MAPPED_RECT rect_ = {0}; + DesktopSize desktop_size_; + std::unique_ptr frame_; + ResolutionChangeDetector resolution_change_detector_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_texture_mapping.h b/include/webrtc/modules/desktop_capture/win/dxgi_texture_mapping.h new file mode 100644 index 0000000..0291a90 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_texture_mapping.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_MAPPING_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_MAPPING_H_ + +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/win/dxgi_texture.h" + +namespace webrtc { + +// A DxgiTexture which directly maps bitmap from IDXGIResource. This class is +// used when DXGI_OUTDUPL_DESC.DesktopImageInSystemMemory is true. (This usually +// means the video card shares main memory with CPU, instead of having its own +// individual memory.) +class DxgiTextureMapping : public DxgiTexture { + public: + // Creates a DxgiTextureMapping instance. Caller must maintain the lifetime + // of input |duplication| to make sure it outlives this instance. + explicit DxgiTextureMapping(IDXGIOutputDuplication* duplication); + + ~DxgiTextureMapping() override; + + protected: + bool CopyFromTexture(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + ID3D11Texture2D* texture) override; + + bool DoRelease() override; + + private: + IDXGIOutputDuplication* const duplication_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_MAPPING_H_ diff --git a/include/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h b/include/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h new file mode 100644 index 0000000..a7e9b86 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/dxgi_texture_staging.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_STAGING_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_STAGING_H_ + +#include +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/win/d3d_device.h" +#include "webrtc/modules/desktop_capture/win/dxgi_texture.h" + +namespace webrtc { + +// A pair of an ID3D11Texture2D and an IDXGISurface. We need an ID3D11Texture2D +// instance to copy GPU texture to RAM, but an IDXGISurface instance to map the +// texture into a bitmap buffer. These two instances are pointing to a same +// object. +// +// An ID3D11Texture2D is created by an ID3D11Device, so a DxgiTexture cannot be +// shared between two DxgiAdapterDuplicators. +class DxgiTextureStaging : public DxgiTexture { + public: + // Creates a DxgiTextureStaging instance. Caller must maintain the lifetime + // of input device to make sure it outlives this instance. + explicit DxgiTextureStaging(const D3dDevice& device); + + ~DxgiTextureStaging() override; + + protected: + // Copies selected regions of a frame represented by frame_info and texture. + // Returns false if anything wrong. + bool CopyFromTexture(const DXGI_OUTDUPL_FRAME_INFO& frame_info, + ID3D11Texture2D* texture) override; + + bool DoRelease() override; + + private: + // Initializes stage_ from a CPU inaccessible IDXGIResource. Returns false if + // it failed to execute Windows APIs, or the size of the texture is not + // consistent with desktop_rect. + bool InitializeStage(ID3D11Texture2D* texture); + + // Makes sure stage_ and surface_ are always pointing to a same object. + // We need an ID3D11Texture2D instance for + // ID3D11DeviceContext::CopySubresourceRegion, but an IDXGISurface for + // IDXGISurface::Map. + void AssertStageAndSurfaceAreSameObject(); + + const DesktopRect desktop_rect_; + const D3dDevice device_; + Microsoft::WRL::ComPtr stage_; + Microsoft::WRL::ComPtr surface_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DXGI_TEXTURE_STAGING_H_ diff --git a/include/webrtc/modules/desktop_capture/win/screen_capture_utils.h b/include/webrtc/modules/desktop_capture/win/screen_capture_utils.h index 42473e0..751588b 100644 --- a/include/webrtc/modules/desktop_capture/win/screen_capture_utils.h +++ b/include/webrtc/modules/desktop_capture/win/screen_capture_utils.h @@ -11,24 +11,25 @@ #ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURE_UTILS_H_ #define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURE_UTILS_H_ -#include "webrtc/modules/desktop_capture/screen_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" namespace webrtc { // Output the list of active screens into |screens|. Returns true if succeeded, // or false if it fails to enumerate the display devices. -bool GetScreenList(ScreenCapturer::ScreenList* screens); +bool GetScreenList(DesktopCapturer::SourceList* screens); // Returns true if |screen| is a valid screen. The screen device key is // returned through |device_key| if the screen is valid. The device key can be // used in GetScreenRect to verify the screen matches the previously obtained // id. -bool IsScreenValid(ScreenId screen, std::wstring* device_key); +bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key); // Get the rect of the screen identified by |screen|, relative to the primary // display's top-left. If the screen device key does not match |device_key|, or // the screen does not exist, or any error happens, an empty rect is returned. -DesktopRect GetScreenRect(ScreenId screen, const std::wstring& device_key); +DesktopRect GetScreenRect(DesktopCapturer::SourceId screen, + const std::wstring& device_key); } // namespace webrtc diff --git a/include/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h new file mode 100644 index 0000000..a48bda9 --- /dev/null +++ b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_DIRECTX_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_DIRECTX_H_ + +#include + +#include +#include + +#include "webrtc/modules/desktop_capture/desktop_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capture_options.h" +#include "webrtc/modules/desktop_capture/desktop_region.h" +#include "webrtc/modules/desktop_capture/resolution_change_detector.h" +#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" +#include "webrtc/modules/desktop_capture/shared_desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h" + +namespace webrtc { + +// ScreenCapturerWinDirectx captures 32bit RGBA using DirectX. +class ScreenCapturerWinDirectx : public DesktopCapturer { + public: + using D3dInfo = DxgiDuplicatorController::D3dInfo; + + // Whether the system supports DirectX based capturing. + static bool IsSupported(); + + // Returns a most recent D3dInfo composed by + // DxgiDuplicatorController::Initialize() function. This function implicitly + // calls DxgiDuplicatorController::Initialize() if it has not been + // initialized. This function returns false and output parameter is kept + // unchanged if DxgiDuplicatorController::Initialize() failed. + // The D3dInfo may change based on hardware configuration even without + // restarting the hardware and software. Refer to https://goo.gl/OOCppq. So + // consumers should not cache the result returned by this function. + static bool RetrieveD3dInfo(D3dInfo* info); + + explicit ScreenCapturerWinDirectx(const DesktopCaptureOptions& options); + + ~ScreenCapturerWinDirectx() override; + + void Start(Callback* callback) override; + void SetSharedMemoryFactory( + std::unique_ptr shared_memory_factory) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + + private: + // Returns desktop size of selected screen. + DesktopSize SelectedDesktopSize() const; + + ScreenCaptureFrameQueue frames_; + std::unique_ptr shared_memory_factory_; + Callback* callback_ = nullptr; + DxgiDuplicatorController::Context context_; + SourceId current_screen_id_ = kFullDesktopScreenId; + ResolutionChangeDetector resolution_change_detector_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinDirectx); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_SCREEN_CAPTURER_WIN_DIRECTX_H_ diff --git a/include/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h index 5a50580..05c0283 100644 --- a/include/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h +++ b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h @@ -13,35 +13,34 @@ #include -#include "webrtc/modules/desktop_capture/screen_capturer.h" - #include #include "webrtc/base/constructormagic.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" -#include "webrtc/modules/desktop_capture/screen_capturer_helper.h" #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" #include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" namespace webrtc { -class Differ; - // ScreenCapturerWinGdi captures 32bit RGB using GDI. // // ScreenCapturerWinGdi is double-buffered as required by ScreenCapturer. -class ScreenCapturerWinGdi : public ScreenCapturer { +// This class does not detect DesktopFrame::updated_region(), the field is +// always set to the entire frame rectangle. ScreenCapturerDifferWrapper should +// be used if that functionality is necessary. +class ScreenCapturerWinGdi : public DesktopCapturer { public: explicit ScreenCapturerWinGdi(const DesktopCaptureOptions& options); - virtual ~ScreenCapturerWinGdi(); + ~ScreenCapturerWinGdi() override; // Overridden from ScreenCapturer: void Start(Callback* callback) override; void SetSharedMemoryFactory( std::unique_ptr shared_memory_factory) override; - void Capture(const DesktopRegion& region) override; - bool GetScreenList(ScreenList* screens) override; - bool SelectScreen(ScreenId id) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; private: typedef HRESULT (WINAPI * DwmEnableCompositionFunc)(UINT); @@ -56,20 +55,16 @@ class ScreenCapturerWinGdi : public ScreenCapturer { // Capture the current cursor shape. void CaptureCursor(); - Callback* callback_; + Callback* callback_ = nullptr; std::unique_ptr shared_memory_factory_; - ScreenId current_screen_id_; + SourceId current_screen_id_ = kFullDesktopScreenId; std::wstring current_device_key_; - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - ScreenCapturerHelper helper_; - ScopedThreadDesktop desktop_; // GDI resources used for screen capture. - HDC desktop_dc_; - HDC memory_dc_; + HDC desktop_dc_ = NULL; + HDC memory_dc_ = NULL; // Queue of the frames buffers. ScreenCaptureFrameQueue queue_; @@ -78,14 +73,8 @@ class ScreenCapturerWinGdi : public ScreenCapturer { // the primary display's top-left. DesktopRect desktop_dc_rect_; - // Class to calculate the difference between two screen bitmaps. - std::unique_ptr differ_; - - HMODULE dwmapi_library_; - DwmEnableCompositionFunc composition_func_; - - // Used to suppress duplicate logging of SetThreadExecutionState errors. - bool set_thread_execution_state_failed_; + HMODULE dwmapi_library_ = NULL; + DwmEnableCompositionFunc composition_func_ = nullptr; RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinGdi); }; diff --git a/include/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h index 623c8a3..7f1f55a 100644 --- a/include/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h +++ b/include/webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h @@ -18,8 +18,8 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" -#include "webrtc/modules/desktop_capture/screen_capturer.h" #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" #include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" @@ -29,28 +29,27 @@ namespace webrtc { class DesktopFrame; class DesktopRect; -class Differ; // Captures the screen using the Magnification API to support window exclusion. // Each capturer must run on a dedicated thread because it uses thread local // storage for redirecting the library callback. Also the thread must have a UI // message loop to handle the window messages for the magnifier window. -class ScreenCapturerWinMagnifier : public ScreenCapturer { +// +// This class does not detect DesktopFrame::updated_region(), the field is +// always set to the entire frame rectangle. ScreenCapturerDifferWrapper should +// be used if that functionality is necessary. +class ScreenCapturerWinMagnifier : public DesktopCapturer { public: - // |fallback_capturer| will be used to capture the screen if a non-primary - // screen is being captured, or the OS does not support Magnification API, or - // the magnifier capturer fails (e.g. in Windows8 Metro mode). - explicit ScreenCapturerWinMagnifier( - std::unique_ptr fallback_capturer); - virtual ~ScreenCapturerWinMagnifier(); + ScreenCapturerWinMagnifier(); + ~ScreenCapturerWinMagnifier() override; // Overridden from ScreenCapturer: void Start(Callback* callback) override; void SetSharedMemoryFactory( std::unique_ptr shared_memory_factory) override; - void Capture(const DesktopRegion& region) override; - bool GetScreenList(ScreenList* screens) override; - bool SelectScreen(ScreenId id) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* screens) override; + bool SelectSource(SourceId id) override; void SetExcludedWindow(WindowId window) override; private: @@ -100,55 +99,40 @@ class ScreenCapturerWinMagnifier : public ScreenCapturer { // Makes sure the current frame exists and matches |size|. void CreateCurrentFrameIfNecessary(const DesktopSize& size); - // Start the fallback capturer and select the screen. - void StartFallbackCapturer(); - static Atomic32 tls_index_; - std::unique_ptr fallback_capturer_; - bool fallback_capturer_started_; - Callback* callback_; + Callback* callback_ = nullptr; std::unique_ptr shared_memory_factory_; - ScreenId current_screen_id_; + ScreenId current_screen_id_ = kFullDesktopScreenId; std::wstring current_device_key_; - HWND excluded_window_; - - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - ScreenCapturerHelper helper_; + HWND excluded_window_ = NULL; // Queue of the frames buffers. ScreenCaptureFrameQueue queue_; - // Class to calculate the difference between two screen bitmaps. - std::unique_ptr differ_; - - // Used to suppress duplicate logging of SetThreadExecutionState errors. - bool set_thread_execution_state_failed_; - ScopedThreadDesktop desktop_; // Used for getting the screen dpi. - HDC desktop_dc_; + HDC desktop_dc_ = NULL; - HMODULE mag_lib_handle_; - MagInitializeFunc mag_initialize_func_; - MagUninitializeFunc mag_uninitialize_func_; - MagSetWindowSourceFunc set_window_source_func_; - MagSetWindowFilterListFunc set_window_filter_list_func_; - MagSetImageScalingCallbackFunc set_image_scaling_callback_func_; + HMODULE mag_lib_handle_ = NULL; + MagInitializeFunc mag_initialize_func_ = nullptr; + MagUninitializeFunc mag_uninitialize_func_ = nullptr; + MagSetWindowSourceFunc set_window_source_func_ = nullptr; + MagSetWindowFilterListFunc set_window_filter_list_func_ = nullptr; + MagSetImageScalingCallbackFunc set_image_scaling_callback_func_ = nullptr; // The hidden window hosting the magnifier control. - HWND host_window_; + HWND host_window_ = NULL; // The magnifier control that captures the screen. - HWND magnifier_window_; + HWND magnifier_window_ = NULL; // True if the magnifier control has been successfully initialized. - bool magnifier_initialized_; + bool magnifier_initialized_ = false; // True if the last OnMagImageScalingCallback was called and handled // successfully. Reset at the beginning of each CaptureImage call. - bool magnifier_capture_succeeded_; + bool magnifier_capture_succeeded_ = true; RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerWinMagnifier); }; diff --git a/include/webrtc/modules/desktop_capture/window_capturer.h b/include/webrtc/modules/desktop_capture/window_capturer.h deleted file mode 100644 index eb9b9fe..0000000 --- a/include/webrtc/modules/desktop_capture/window_capturer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_H_ -#define WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_H_ - -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/desktop_capture/desktop_capture_types.h" -#include "webrtc/modules/desktop_capture/desktop_capturer.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class DesktopCaptureOptions; - -class WindowCapturer : public DesktopCapturer { - public: - typedef webrtc::WindowId WindowId; - - struct Window { - WindowId id; - - // Title of the window in UTF-8 encoding. - std::string title; - }; - - typedef std::vector WindowList; - - static WindowCapturer* Create(const DesktopCaptureOptions& options); - - virtual ~WindowCapturer() {} - - // Get list of windows. Returns false in case of a failure. - virtual bool GetWindowList(WindowList* windows) = 0; - - // Select window to be captured. Returns false in case of a failure (e.g. if - // there is no window with the specified id). - virtual bool SelectWindow(WindowId id) = 0; - - // Bring the selected window to the front. Returns false in case of a - // failure or no window selected. - virtual bool BringSelectedWindowToFront() = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_H_ - diff --git a/include/webrtc/modules/desktop_capture/x11/shared_x_display.h b/include/webrtc/modules/desktop_capture/x11/shared_x_display.h index 6cade2d..648f67a 100644 --- a/include/webrtc/modules/desktop_capture/x11/shared_x_display.h +++ b/include/webrtc/modules/desktop_capture/x11/shared_x_display.h @@ -14,15 +14,17 @@ #include #include -#include -#include - #include #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/system_wrappers/include/atomic32.h" +// Including Xlib.h will involve evil defines (Bool, Status, True, False), which +// easily conflict with other headers. +typedef struct _XDisplay Display; +typedef union _XEvent XEvent; + namespace webrtc { // A ref-counted object to store XDisplay connection. diff --git a/include/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h b/include/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h index b868b04..2a177c4 100644 --- a/include/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h +++ b/include/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h @@ -55,7 +55,7 @@ class XServerPixelBuffer { // where the full-screen data is captured by Synchronize(), this simply // returns the pointer without doing any more work. The caller must ensure // that |rect| is not larger than window_size(). - void CaptureRect(const DesktopRect& rect, DesktopFrame* frame); + bool CaptureRect(const DesktopRect& rect, DesktopFrame* frame); private: void InitShm(const XWindowAttributes& attributes); @@ -70,13 +70,14 @@ class XServerPixelBuffer { const DesktopRect& rect, DesktopFrame* frame); - Display* display_; - Window window_; + Display* display_ = nullptr; + Window window_ = 0; DesktopSize window_size_; - XImage* x_image_; - XShmSegmentInfo* shm_segment_info_; - Pixmap shm_pixmap_; - GC shm_gc_; + XImage* x_image_ = nullptr; + XShmSegmentInfo* shm_segment_info_ = nullptr; + Pixmap shm_pixmap_ = 0; + GC shm_gc_ = nullptr; + bool xshm_get_image_succeeded_ = false; RTC_DISALLOW_COPY_AND_ASSIGN(XServerPixelBuffer); }; diff --git a/include/webrtc/modules/include/module_common_types.h b/include/webrtc/modules/include/module_common_types.h index 3572cd6..98f7a38 100644 --- a/include/webrtc/modules/include/module_common_types.h +++ b/include/webrtc/modules/include/module_common_types.h @@ -17,9 +17,14 @@ #include #include +#include "webrtc/api/video/video_rotation.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/deprecation.h" +#include "webrtc/base/safe_conversions.h" #include "webrtc/common_types.h" -#include "webrtc/common_video/rotation.h" +#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_globals.h" +#include "webrtc/modules/video_coding/codecs/vp9/include/vp9_globals.h" +#include "webrtc/modules/video_coding/codecs/h264/include/h264_globals.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -31,244 +36,6 @@ struct RTPAudioHeader { size_t channel; // number of channels 2 = stereo }; -const int16_t kNoPictureId = -1; -const int16_t kMaxOneBytePictureId = 0x7F; // 7 bits -const int16_t kMaxTwoBytePictureId = 0x7FFF; // 15 bits -const int16_t kNoTl0PicIdx = -1; -const uint8_t kNoTemporalIdx = 0xFF; -const uint8_t kNoSpatialIdx = 0xFF; -const uint8_t kNoGofIdx = 0xFF; -const uint8_t kNumVp9Buffers = 8; -const size_t kMaxVp9RefPics = 3; -const size_t kMaxVp9FramesInGof = 0xFF; // 8 bits -const size_t kMaxVp9NumberOfSpatialLayers = 8; -const int kNoKeyIdx = -1; - -struct RTPVideoHeaderVP8 { - void InitRTPVideoHeaderVP8() { - nonReference = false; - pictureId = kNoPictureId; - tl0PicIdx = kNoTl0PicIdx; - temporalIdx = kNoTemporalIdx; - layerSync = false; - keyIdx = kNoKeyIdx; - partitionId = 0; - beginningOfPartition = false; - } - - bool nonReference; // Frame is discardable. - int16_t pictureId; // Picture ID index, 15 bits; - // kNoPictureId if PictureID does not exist. - int16_t tl0PicIdx; // TL0PIC_IDX, 8 bits; - // kNoTl0PicIdx means no value provided. - uint8_t temporalIdx; // Temporal layer index, or kNoTemporalIdx. - bool layerSync; // This frame is a layer sync frame. - // Disabled if temporalIdx == kNoTemporalIdx. - int keyIdx; // 5 bits; kNoKeyIdx means not used. - int partitionId; // VP8 partition ID - bool beginningOfPartition; // True if this packet is the first - // in a VP8 partition. Otherwise false -}; - -enum TemporalStructureMode { - kTemporalStructureMode1, // 1 temporal layer structure - i.e., IPPP... - kTemporalStructureMode2, // 2 temporal layers 01... - kTemporalStructureMode3, // 3 temporal layers 0212... - kTemporalStructureMode4 // 3 temporal layers 02120212... -}; - -struct GofInfoVP9 { - void SetGofInfoVP9(TemporalStructureMode tm) { - switch (tm) { - case kTemporalStructureMode1: - num_frames_in_gof = 1; - temporal_idx[0] = 0; - temporal_up_switch[0] = false; - num_ref_pics[0] = 1; - pid_diff[0][0] = 1; - break; - case kTemporalStructureMode2: - num_frames_in_gof = 2; - temporal_idx[0] = 0; - temporal_up_switch[0] = false; - num_ref_pics[0] = 1; - pid_diff[0][0] = 2; - - temporal_idx[1] = 1; - temporal_up_switch[1] = true; - num_ref_pics[1] = 1; - pid_diff[1][0] = 1; - break; - case kTemporalStructureMode3: - num_frames_in_gof = 4; - temporal_idx[0] = 0; - temporal_up_switch[0] = false; - num_ref_pics[0] = 1; - pid_diff[0][0] = 4; - - temporal_idx[1] = 2; - temporal_up_switch[1] = true; - num_ref_pics[1] = 1; - pid_diff[1][0] = 1; - - temporal_idx[2] = 1; - temporal_up_switch[2] = true; - num_ref_pics[2] = 1; - pid_diff[2][0] = 2; - - temporal_idx[3] = 2; - temporal_up_switch[3] = false; - num_ref_pics[3] = 2; - pid_diff[3][0] = 1; - pid_diff[3][1] = 2; - break; - case kTemporalStructureMode4: - num_frames_in_gof = 8; - temporal_idx[0] = 0; - temporal_up_switch[0] = false; - num_ref_pics[0] = 1; - pid_diff[0][0] = 4; - - temporal_idx[1] = 2; - temporal_up_switch[1] = true; - num_ref_pics[1] = 1; - pid_diff[1][0] = 1; - - temporal_idx[2] = 1; - temporal_up_switch[2] = true; - num_ref_pics[2] = 1; - pid_diff[2][0] = 2; - - temporal_idx[3] = 2; - temporal_up_switch[3] = false; - num_ref_pics[3] = 2; - pid_diff[3][0] = 1; - pid_diff[3][1] = 2; - - temporal_idx[4] = 0; - temporal_up_switch[0] = false; - num_ref_pics[4] = 1; - pid_diff[4][0] = 4; - - temporal_idx[5] = 2; - temporal_up_switch[1] = false; - num_ref_pics[5] = 2; - pid_diff[5][0] = 1; - pid_diff[5][1] = 2; - - temporal_idx[6] = 1; - temporal_up_switch[2] = false; - num_ref_pics[6] = 2; - pid_diff[6][0] = 2; - pid_diff[6][1] = 4; - - temporal_idx[7] = 2; - temporal_up_switch[3] = false; - num_ref_pics[7] = 2; - pid_diff[7][0] = 1; - pid_diff[7][1] = 2; - break; - default: - assert(false); - } - } - - void CopyGofInfoVP9(const GofInfoVP9& src) { - num_frames_in_gof = src.num_frames_in_gof; - for (size_t i = 0; i < num_frames_in_gof; ++i) { - temporal_idx[i] = src.temporal_idx[i]; - temporal_up_switch[i] = src.temporal_up_switch[i]; - num_ref_pics[i] = src.num_ref_pics[i]; - for (uint8_t r = 0; r < num_ref_pics[i]; ++r) { - pid_diff[i][r] = src.pid_diff[i][r]; - } - } - } - - size_t num_frames_in_gof; - uint8_t temporal_idx[kMaxVp9FramesInGof]; - bool temporal_up_switch[kMaxVp9FramesInGof]; - uint8_t num_ref_pics[kMaxVp9FramesInGof]; - uint8_t pid_diff[kMaxVp9FramesInGof][kMaxVp9RefPics]; - uint16_t pid_start; -}; - -struct RTPVideoHeaderVP9 { - void InitRTPVideoHeaderVP9() { - inter_pic_predicted = false; - flexible_mode = false; - beginning_of_frame = false; - end_of_frame = false; - ss_data_available = false; - picture_id = kNoPictureId; - max_picture_id = kMaxTwoBytePictureId; - tl0_pic_idx = kNoTl0PicIdx; - temporal_idx = kNoTemporalIdx; - spatial_idx = kNoSpatialIdx; - temporal_up_switch = false; - inter_layer_predicted = false; - gof_idx = kNoGofIdx; - num_ref_pics = 0; - num_spatial_layers = 1; - } - - bool inter_pic_predicted; // This layer frame is dependent on previously - // coded frame(s). - bool flexible_mode; // This frame is in flexible mode. - bool beginning_of_frame; // True if this packet is the first in a VP9 layer - // frame. - bool end_of_frame; // True if this packet is the last in a VP9 layer frame. - bool ss_data_available; // True if SS data is available in this payload - // descriptor. - int16_t picture_id; // PictureID index, 15 bits; - // kNoPictureId if PictureID does not exist. - int16_t max_picture_id; // Maximum picture ID index; either 0x7F or 0x7FFF; - int16_t tl0_pic_idx; // TL0PIC_IDX, 8 bits; - // kNoTl0PicIdx means no value provided. - uint8_t temporal_idx; // Temporal layer index, or kNoTemporalIdx. - uint8_t spatial_idx; // Spatial layer index, or kNoSpatialIdx. - bool temporal_up_switch; // True if upswitch to higher frame rate is possible - // starting from this frame. - bool inter_layer_predicted; // Frame is dependent on directly lower spatial - // layer frame. - - uint8_t gof_idx; // Index to predefined temporal frame info in SS data. - - uint8_t num_ref_pics; // Number of reference pictures used by this layer - // frame. - uint8_t pid_diff[kMaxVp9RefPics]; // P_DIFF signaled to derive the PictureID - // of the reference pictures. - int16_t ref_picture_id[kMaxVp9RefPics]; // PictureID of reference pictures. - - // SS data. - size_t num_spatial_layers; // Always populated. - bool spatial_layer_resolution_present; - uint16_t width[kMaxVp9NumberOfSpatialLayers]; - uint16_t height[kMaxVp9NumberOfSpatialLayers]; - GofInfoVP9 gof; -}; - -// The packetization types that we support: single, aggregated, and fragmented. -enum H264PacketizationTypes { - kH264SingleNalu, // This packet contains a single NAL unit. - kH264StapA, // This packet contains STAP-A (single time - // aggregation) packets. If this packet has an - // associated NAL unit type, it'll be for the - // first such aggregated packet. - kH264FuA, // This packet contains a FU-A (fragmentation - // unit) packet, meaning it is a part of a frame - // that was too large to fit into a single packet. -}; - -struct RTPVideoHeaderH264 { - uint8_t nalu_type; // The NAL unit type. If this is a header for a - // fragmented packet, it's the NAL unit type of - // the original data. If this is the header for an - // aggregated packet, it's the NAL unit type of - // the first NAL unit in the packet. - H264PacketizationTypes packetization_type; -}; - union RTPVideoTypeHeader { RTPVideoHeaderVP8 VP8; RTPVideoHeaderVP9 VP9; @@ -289,7 +56,12 @@ struct RTPVideoHeader { uint16_t height; VideoRotation rotation; - bool isFirstPacket; // first packet in frame + PlayoutDelay playout_delay; + + union { + bool is_first_packet_in_frame; + RTC_DEPRECATED bool isFirstPacket; // first packet in frame + }; uint8_t simulcastIdx; // Index if the simulcast encoder creating // this frame, 0 if not using simulcast. RtpVideoCodecTypes codec; @@ -504,8 +276,6 @@ class CallStatsObserver { * * - Stereo data is interleaved starting with the left channel. * - * - The +operator assume that you would never add exactly opposite frames when - * deciding the resulting state. To do this use the -operator. */ class AudioFrame { public: @@ -540,26 +310,29 @@ class AudioFrame { void CopyFrom(const AudioFrame& src); - void Mute(); - - AudioFrame& operator>>=(const int rhs); - AudioFrame& operator+=(const AudioFrame& rhs); + // These methods are deprecated. Use the functions in + // webrtc/audio/utility instead. These methods will exists for a + // short period of time until webrtc clients have updated. See + // webrtc:6548 for details. + RTC_DEPRECATED void Mute(); + RTC_DEPRECATED AudioFrame& operator>>=(const int rhs); + RTC_DEPRECATED AudioFrame& operator+=(const AudioFrame& rhs); int id_; // RTP timestamp of the first sample in the AudioFrame. - uint32_t timestamp_; + uint32_t timestamp_ = 0; // Time since the first frame in milliseconds. // -1 represents an uninitialized value. - int64_t elapsed_time_ms_; + int64_t elapsed_time_ms_ = -1; // NTP time of the estimated capture time in local timebase in milliseconds. // -1 represents an uninitialized value. - int64_t ntp_time_ms_; + int64_t ntp_time_ms_ = -1; int16_t data_[kMaxDataSizeSamples]; - size_t samples_per_channel_; - int sample_rate_hz_; - size_t num_channels_; - SpeechType speech_type_; - VADActivity vad_activity_; + size_t samples_per_channel_ = 0; + int sample_rate_hz_ = 0; + size_t num_channels_ = 0; + SpeechType speech_type_ = kUndefined; + VADActivity vad_activity_ = kVadUnknown; private: RTC_DISALLOW_COPY_AND_ASSIGN(AudioFrame); @@ -569,7 +342,6 @@ class AudioFrame { // See https://bugs.chromium.org/p/webrtc/issues/detail?id=5647. inline AudioFrame::AudioFrame() : data_() { - Reset(); } inline void AudioFrame::Reset() { @@ -643,18 +415,6 @@ inline AudioFrame& AudioFrame::operator>>=(const int rhs) { return *this; } -namespace { -inline int16_t ClampToInt16(int32_t input) { - if (input < -0x00008000) { - return -0x8000; - } else if (input > 0x00007FFF) { - return 0x7FFF; - } else { - return static_cast(input); - } -} -} - inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) { // Sanity check assert((num_channels_ > 0) && (num_channels_ < 3)); @@ -688,7 +448,7 @@ inline AudioFrame& AudioFrame::operator+=(const AudioFrame& rhs) { for (size_t i = 0; i < samples_per_channel_ * num_channels_; i++) { int32_t wrap_guard = static_cast(data_[i]) + static_cast(rhs.data_[i]); - data_[i] = ClampToInt16(wrap_guard); + data_[i] = rtc::saturated_cast(wrap_guard); } } return *this; @@ -769,6 +529,29 @@ class SequenceNumberUnwrapper { int64_t last_seq_; }; +struct PacedPacketInfo { + PacedPacketInfo() {} + PacedPacketInfo(int probe_cluster_id, + int probe_cluster_min_probes, + int probe_cluster_min_bytes) + : probe_cluster_id(probe_cluster_id), + probe_cluster_min_probes(probe_cluster_min_probes), + probe_cluster_min_bytes(probe_cluster_min_bytes) {} + + bool operator==(const PacedPacketInfo& rhs) const { + return send_bitrate_bps == rhs.send_bitrate_bps && + probe_cluster_id == rhs.probe_cluster_id && + probe_cluster_min_probes == rhs.probe_cluster_min_probes && + probe_cluster_min_bytes == rhs.probe_cluster_min_bytes; + } + + static constexpr int kNotAProbe = -1; + int send_bitrate_bps = -1; + int probe_cluster_id = kNotAProbe; + int probe_cluster_min_probes = -1; + int probe_cluster_min_bytes = -1; +}; + } // namespace webrtc #endif // WEBRTC_MODULES_INCLUDE_MODULE_COMMON_TYPES_H_ diff --git a/include/webrtc/modules/media_file/media_file_defines.h b/include/webrtc/modules/media_file/media_file_defines.h index a021a14..3113620 100644 --- a/include/webrtc/modules/media_file/media_file_defines.h +++ b/include/webrtc/modules/media_file/media_file_defines.h @@ -11,7 +11,6 @@ #ifndef WEBRTC_MODULES_MEDIA_FILE_MEDIA_FILE_DEFINES_H_ #define WEBRTC_MODULES_MEDIA_FILE_MEDIA_FILE_DEFINES_H_ -#include "webrtc/engine_configurations.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" diff --git a/include/webrtc/modules/pacing/alr_detector.h b/include/webrtc/modules/pacing/alr_detector.h new file mode 100644 index 0000000..d8870ff --- /dev/null +++ b/include/webrtc/modules/pacing/alr_detector.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_PACING_ALR_DETECTOR_H_ +#define WEBRTC_MODULES_PACING_ALR_DETECTOR_H_ + +#include "webrtc/base/rate_statistics.h" +#include "webrtc/common_types.h" +#include "webrtc/modules/pacing/paced_sender.h" +#include "webrtc/typedefs.h" + +namespace webrtc { + +// Application limited region detector is a class that utilizes signals of +// elapsed time and bytes sent to estimate whether network traffic is +// currently limited by the application's ability to generate traffic. +// +// AlrDetector provides a signal that can be utilized to adjust +// estimate bandwidth. +// Note: This class is not thread-safe. +class AlrDetector { + public: + AlrDetector(); + ~AlrDetector(); + + void OnBytesSent(size_t bytes_sent, int64_t now_ms); + + // Set current estimated bandwidth. + void SetEstimatedBitrate(int bitrate_bps); + + // Returns time in milliseconds when the current application-limited region + // started or empty result if the sender is currently not application-limited. + rtc::Optional GetApplicationLimitedRegionStartTime() const; + + private: + RateStatistics rate_; + int estimated_bitrate_bps_ = 0; + + // Non-empty in ALR state. + rtc::Optional alr_started_time_ms_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_PACING_ALR_DETECTOR_H_ diff --git a/include/webrtc/modules/pacing/bitrate_prober.h b/include/webrtc/modules/pacing/bitrate_prober.h index e8967ab..0690750 100644 --- a/include/webrtc/modules/pacing/bitrate_prober.h +++ b/include/webrtc/modules/pacing/bitrate_prober.h @@ -11,10 +11,10 @@ #ifndef WEBRTC_MODULES_PACING_BITRATE_PROBER_H_ #define WEBRTC_MODULES_PACING_BITRATE_PROBER_H_ -#include -#include #include +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -35,43 +35,73 @@ class BitrateProber { // Initializes a new probing session if the prober is allowed to probe. Does // not initialize the prober unless the packet size is large enough to probe // with. - void OnIncomingPacket(uint32_t bitrate_bps, - size_t packet_size, - int64_t now_ms); + void OnIncomingPacket(size_t packet_size); - // Returns the number of milliseconds until the next packet should be sent to + // Create a cluster used to probe for |bitrate_bps| with |num_probes| number + // of probes. + void CreateProbeCluster(int bitrate_bps, int64_t now_ms); + + // Returns the number of milliseconds until the next probe should be sent to // get accurate probing. int TimeUntilNextProbe(int64_t now_ms); - // Which cluster that is currently being used for probing. - int CurrentClusterId() const; + // Information about the current probing cluster. + PacedPacketInfo CurrentCluster() const; - // Returns the number of bytes that the prober recommends for the next probe - // packet. - size_t RecommendedPacketSize() const; + // Returns the minimum number of bytes that the prober recommends for + // the next probe. + size_t RecommendedMinProbeSize() const; - // Called to report to the prober that a packet has been sent, which helps the - // prober know when to move to the next packet in a probe. - void PacketSent(int64_t now_ms, size_t packet_size); + // Called to report to the prober that a probe has been sent. In case of + // multiple packets per probe, this call would be made at the end of sending + // the last packet in probe. |probe_size| is the total size of all packets + // in probe. + void ProbeSent(int64_t now_ms, size_t probe_size); private: - enum ProbingState { kDisabled, kAllowedToProbe, kProbing, kWait }; + enum class ProbingState { + // Probing will not be triggered in this state at all times. + kDisabled, + // Probing is enabled and ready to trigger on the first packet arrival. + kInactive, + // Probe cluster is filled with the set of data rates to be probed and + // probes are being sent. + kActive, + // Probing is enabled, but currently suspended until an explicit trigger + // to start probing again. + kSuspended, + }; + // A probe cluster consists of a set of probes. Each probe in turn can be + // divided into a number of packets to accommodate the MTU on the network. struct ProbeCluster { - int max_probe_packets = 0; - int sent_probe_packets = 0; - int probe_bitrate_bps = 0; - int id = -1; + PacedPacketInfo pace_info; + + int sent_probes = 0; + int sent_bytes = 0; + int64_t time_created_ms = -1; + int64_t time_started_ms = -1; + int retries = 0; }; + // Resets the state of the prober and clears any cluster/timing data tracked. + void ResetState(int64_t now_ms); + + int64_t GetNextProbeTime(const ProbeCluster& cluster); + ProbingState probing_state_; + // Probe bitrate per packet. These are used to compute the delta relative to // the previous probe packet based on the size and time when that packet was // sent. std::queue clusters_; - size_t packet_size_last_send_; - int64_t time_last_send_ms_; + + // Time the next probe should be sent when in kActive state. + int64_t next_probe_time_ms_; + int next_cluster_id_; }; + } // namespace webrtc + #endif // WEBRTC_MODULES_PACING_BITRATE_PROBER_H_ diff --git a/include/webrtc/modules/pacing/mock/mock_paced_sender.h b/include/webrtc/modules/pacing/mock/mock_paced_sender.h index bd7d7aa..1eee3f9 100644 --- a/include/webrtc/modules/pacing/mock/mock_paced_sender.h +++ b/include/webrtc/modules/pacing/mock/mock_paced_sender.h @@ -13,10 +13,9 @@ #include -#include "testing/gmock/include/gmock/gmock.h" - #include "webrtc/modules/pacing/paced_sender.h" #include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -29,10 +28,13 @@ class MockPacedSender : public PacedSender { int64_t capture_time_ms, size_t bytes, bool retransmission)); + MOCK_METHOD1(CreateProbeCluster, void(int)); MOCK_METHOD1(SetEstimatedBitrate, void(uint32_t)); MOCK_CONST_METHOD0(QueueInMs, int64_t()); MOCK_CONST_METHOD0(QueueInPackets, int()); MOCK_CONST_METHOD0(ExpectedQueueTimeMs, int64_t()); + MOCK_CONST_METHOD0(GetApplicationLimitedRegionStartTime, + rtc::Optional()); }; } // namespace webrtc diff --git a/include/webrtc/modules/pacing/paced_sender.h b/include/webrtc/modules/pacing/paced_sender.h index d42b9b3..196d85a 100644 --- a/include/webrtc/modules/pacing/paced_sender.h +++ b/include/webrtc/modules/pacing/paced_sender.h @@ -15,15 +15,18 @@ #include #include +#include "webrtc/base/optional.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { +class AlrDetector; class BitrateProber; class Clock; class CriticalSectionWrapper; +class ProbeClusterCreatedObserver; namespace paced_sender { class IntervalBudget; @@ -43,10 +46,11 @@ class PacedSender : public Module, public RtpPacketSender { uint16_t sequence_number, int64_t capture_time_ms, bool retransmission, - int probe_cluster_id) = 0; + const PacedPacketInfo& cluster_info) = 0; // Called when it's a good time to send a padding data. // Returns the number of bytes sent. - virtual size_t TimeToSendPadding(size_t bytes) = 0; + virtual size_t TimeToSendPadding(size_t bytes, + const PacedPacketInfo& cluster_info) = 0; protected: virtual ~PacketSender() {} @@ -64,13 +68,12 @@ class PacedSender : public Module, public RtpPacketSender { // overshoots from the encoder. static const float kDefaultPaceMultiplier; - static const size_t kMinProbePacketSize = 200; - - PacedSender(Clock* clock, - PacketSender* packet_sender); + PacedSender(Clock* clock, PacketSender* packet_sender); virtual ~PacedSender(); + virtual void CreateProbeCluster(int bitrate_bps); + // Temporarily pause all sending. void Pause(); @@ -89,13 +92,15 @@ class PacedSender : public Module, public RtpPacketSender { // |bitrate_bps| * kDefaultPaceMultiplier. virtual void SetEstimatedBitrate(uint32_t bitrate_bps); - // Sets the bitrate that has been allocated for encoders. - // |allocated_bitrate| might be higher that the estimated available network - // bitrate and if so, the pacer will send with |allocated_bitrate|. - // Padding packets will be utilized to reach |padding_bitrate| unless enough - // media packets are available. - void SetAllocatedSendBitrate(int allocated_bitrate_bps, - int padding_bitrate_bps); + // Sets the minimum send bitrate and maximum padding bitrate requested by send + // streams. + // |min_send_bitrate_bps| might be higher that the estimated available network + // bitrate and if so, the pacer will send with |min_send_bitrate_bps|. + // |max_padding_bitrate_bps| might be higher than the estimate available + // network bitrate and if so, the pacer will send padding packets to reach + // the min of the estimated available bitrate and |max_padding_bitrate_bps|. + void SetSendBitrateLimits(int min_send_bitrate_bps, + int max_padding_bitrate_bps); // Returns true if we send the packet now, else it will add the packet // information to the queue and call TimeToSendPacket when it's time to send. @@ -115,6 +120,14 @@ class PacedSender : public Module, public RtpPacketSender { // packets in the queue, given the current size and bitrate, ignoring prio. virtual int64_t ExpectedQueueTimeMs() const; + // Returns time in milliseconds when the current application-limited region + // started or empty result if the sender is currently not application-limited. + // + // Application Limited Region (ALR) refers to operating in a state where the + // traffic on network is limited due to application not having enough + // traffic to meet the current channel capacity. + virtual rtc::Optional GetApplicationLimitedRegionStartTime() const; + // Returns the average time since being enqueued, in milliseconds, for all // packets currently in the pacer queue, or 0 if queue is empty. virtual int64_t AverageQueueTimeMs(); @@ -128,19 +141,23 @@ class PacedSender : public Module, public RtpPacketSender { private: // Updates the number of bytes that can be sent for the next time interval. - void UpdateBytesPerInterval(int64_t delta_time_in_ms) + void UpdateBudgetWithElapsedTime(int64_t delta_time_in_ms) + EXCLUSIVE_LOCKS_REQUIRED(critsect_); + void UpdateBudgetWithBytesSent(size_t bytes) EXCLUSIVE_LOCKS_REQUIRED(critsect_); - bool SendPacket(const paced_sender::Packet& packet, int probe_cluster_id) + bool SendPacket(const paced_sender::Packet& packet, + const PacedPacketInfo& cluster_info) + EXCLUSIVE_LOCKS_REQUIRED(critsect_); + size_t SendPadding(size_t padding_needed, const PacedPacketInfo& cluster_info) EXCLUSIVE_LOCKS_REQUIRED(critsect_); - void SendPadding(size_t padding_needed) EXCLUSIVE_LOCKS_REQUIRED(critsect_); Clock* const clock_; PacketSender* const packet_sender_; + std::unique_ptr alr_detector_ GUARDED_BY(critsect_); std::unique_ptr critsect_; bool paused_ GUARDED_BY(critsect_); - bool probing_enabled_; // This is the media budget, keeping track of how many bits of media // we can pace out during the current interval. std::unique_ptr media_budget_ @@ -152,10 +169,12 @@ class PacedSender : public Module, public RtpPacketSender { GUARDED_BY(critsect_); std::unique_ptr prober_ GUARDED_BY(critsect_); + bool probing_send_failure_; // Actual configured bitrates (media_budget_ may temporarily be higher in // order to meet pace time constraint). uint32_t estimated_bitrate_bps_ GUARDED_BY(critsect_); uint32_t min_send_bitrate_kbps_ GUARDED_BY(critsect_); + uint32_t max_padding_bitrate_kbps_ GUARDED_BY(critsect_); uint32_t pacing_bitrate_kbps_ GUARDED_BY(critsect_); int64_t time_last_update_us_ GUARDED_BY(critsect_); diff --git a/include/webrtc/modules/pacing/packet_router.h b/include/webrtc/modules/pacing/packet_router.h index 81d8540..0dc3fb5 100644 --- a/include/webrtc/modules/pacing/packet_router.h +++ b/include/webrtc/modules/pacing/packet_router.h @@ -44,9 +44,10 @@ class PacketRouter : public PacedSender::PacketSender, uint16_t sequence_number, int64_t capture_timestamp, bool retransmission, - int probe_cluster_id) override; + const PacedPacketInfo& packet_info) override; - size_t TimeToSendPadding(size_t bytes) override; + size_t TimeToSendPadding(size_t bytes, + const PacedPacketInfo& packet_info) override; void SetTransportWideSequenceNumber(uint16_t sequence_number); uint16_t AllocateSequenceNumber() override; diff --git a/include/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h b/include/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h index 93ae219..03fc2d3 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/include/webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -24,15 +24,16 @@ namespace webrtc { class AimdRateControl { public: AimdRateControl(); - virtual ~AimdRateControl() {} + virtual ~AimdRateControl(); // Returns true if there is a valid estimate of the incoming bitrate, false // otherwise. bool ValidEstimate() const; + void SetStartBitrate(int start_bitrate_bps); void SetMinBitrate(int min_bitrate_bps); int64_t GetFeedbackInterval() const; // Returns true if the bitrate estimate hasn't been changed for more than - // an RTT, or if the incoming_bitrate is more than 5% above the current + // an RTT, or if the incoming_bitrate is less than half of the current // estimate. Should be used to decide if we should reduce the rate further // when over-using. bool TimeToReduceFurther(int64_t time_now, @@ -43,6 +44,12 @@ class AimdRateControl { void Update(const RateControlInput* input, int64_t now_ms); void SetEstimate(int bitrate_bps, int64_t now_ms); + // Returns the increase rate which is used when used bandwidth is near the + // maximal available bandwidth. + virtual int GetNearMaxIncreaseRateBps() const; + + virtual rtc::Optional GetLastBitrateDecreaseBps() const; + private: // Update the target bitrate according based on, among other things, // the current rate control state, the current target bitrate and the incoming @@ -51,13 +58,17 @@ class AimdRateControl { // in the "decrease" state the bitrate will be decreased to slightly below the // incoming bitrate. When in the "hold" state the bitrate will be kept // constant to allow built up queues to drain. - uint32_t ChangeBitrate(uint32_t current_bit_rate, - uint32_t incoming_bit_rate, + uint32_t ChangeBitrate(uint32_t current_bitrate, + uint32_t incoming_bitrate, int64_t now_ms); + // Clamps new_bitrate_bps to within the configured min bitrate and a linear + // function of the incoming bitrate, so that the new bitrate can't grow too + // large compared to the bitrate actually being received by the other end. + uint32_t ClampBitrate(uint32_t new_bitrate_bps, + uint32_t incoming_bitrate_bps) const; uint32_t MultiplicativeRateIncrease(int64_t now_ms, int64_t last_ms, uint32_t current_bitrate_bps) const; - uint32_t AdditiveRateIncrease(int64_t now_ms, int64_t last_ms, - int64_t response_time_ms) const; + uint32_t AdditiveRateIncrease(int64_t now_ms, int64_t last_ms) const; void UpdateChangePeriod(int64_t now_ms); void UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps); void ChangeState(const RateControlInput& input, int64_t now_ms); @@ -67,7 +78,6 @@ class AimdRateControl { uint32_t min_configured_bitrate_bps_; uint32_t max_configured_bitrate_bps_; uint32_t current_bitrate_bps_; - uint32_t max_hold_rate_bps_; float avg_max_bitrate_kbps_; float var_max_bitrate_kbps_; RateControlState rate_control_state_; @@ -79,8 +89,8 @@ class AimdRateControl { bool bitrate_is_initialized_; float beta_; int64_t rtt_; - int64_t time_of_last_log_; bool in_experiment_; + rtc::Optional last_decrease_; }; } // namespace webrtc diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h b/include/webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h index 3fb7e29..26bfb28 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/include/webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_BWE_DEFINES_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_BWE_DEFINES_H_ +#include "webrtc/base/optional.h" #include "webrtc/typedefs.h" #define BWE_MAX(a, b) ((a) > (b) ? (a) : (b)) @@ -18,8 +19,22 @@ namespace webrtc { +namespace congestion_controller { +int GetMinBitrateBps(); +} // namespace congestion_controller + static const int64_t kBitrateWindowMs = 1000; +extern const char* kBweTypeHistogram; + +enum BweNames { + kReceiverNoExtension = 0, + kReceiverTOffset = 1, + kReceiverAbsSendTime = 2, + kSendSideTransportSeqNum = 3, + kBweNamesMax = 4 +}; + enum BandwidthUsage { kBwNormal = 0, kBwUnderusing = 1, @@ -32,14 +47,14 @@ enum RateControlRegion { kRcNearMax, kRcAboveMax, kRcMaxUnknown }; struct RateControlInput { RateControlInput(BandwidthUsage bw_state, - uint32_t incoming_bitrate, + const rtc::Optional& incoming_bitrate, double noise_var) : bw_state(bw_state), incoming_bitrate(incoming_bitrate), noise_var(noise_var) {} BandwidthUsage bw_state; - uint32_t incoming_bitrate; + rtc::Optional incoming_bitrate; double noise_var; }; } // namespace webrtc diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_aimd_rate_control.h b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_aimd_rate_control.h new file mode 100644 index 0000000..822f91a --- /dev/null +++ b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_aimd_rate_control.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_AIMD_RATE_CONTROL_H_ +#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_AIMD_RATE_CONTROL_H_ + +#include "webrtc/modules/remote_bitrate_estimator/aimd_rate_control.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockAimdRateControl : public AimdRateControl { + public: + MOCK_CONST_METHOD0(GetNearMaxIncreaseRateBps, int()); + MOCK_CONST_METHOD0(GetLastBitrateDecreaseBps, rtc::Optional()); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_MOCK_MOCK_AIMD_RATE_CONTROL_H_ diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h index 2c35df8..b8cc8ef 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h +++ b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h @@ -13,8 +13,8 @@ #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -28,7 +28,7 @@ class MockRemoteBitrateEstimator : public RemoteBitrateEstimator { public: MOCK_METHOD1(IncomingPacketFeedbackVector, void(const std::vector&)); - MOCK_METHOD4(IncomingPacket, void(int64_t, size_t, const RTPHeader&, bool)); + MOCK_METHOD3(IncomingPacket, void(int64_t, size_t, const RTPHeader&)); MOCK_METHOD1(RemoveStream, void(uint32_t)); MOCK_CONST_METHOD2(LatestEstimate, bool(std::vector*, uint32_t*)); diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h index ae05912..c3fb6ac 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h +++ b/include/webrtc/modules/remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h @@ -13,8 +13,8 @@ #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/test/gmock.h" namespace webrtc { diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/include/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h index e56c273..29dd81b 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h +++ b/include/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h @@ -34,6 +34,7 @@ class RemoteBitrateObserver { // incoming streams. virtual void OnReceiveBitrateChanged(const std::vector& ssrcs, uint32_t bitrate) = 0; + virtual void OnProbeBitrate(uint32_t bitrate) {} virtual ~RemoteBitrateObserver() {} }; @@ -43,7 +44,6 @@ struct ReceiveBandwidthEstimatorStats {}; class RemoteBitrateEstimator : public CallStatsObserver, public Module { public: - static const int kDefaultMinBitrateBps = 30000; virtual ~RemoteBitrateEstimator() {} virtual void IncomingPacketFeedbackVector( @@ -58,8 +58,7 @@ class RemoteBitrateEstimator : public CallStatsObserver, public Module { // Note that |arrival_time_ms| can be of an arbitrary time base. virtual void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, - const RTPHeader& header, - bool was_paced) = 0; + const RTPHeader& header) = 0; // Removes all data for |ssrc|. virtual void RemoveStream(uint32_t ssrc) = 0; diff --git a/include/webrtc/modules/remote_bitrate_estimator/include/send_time_history.h b/include/webrtc/modules/remote_bitrate_estimator/include/send_time_history.h index a643c1f..2e7259d 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/include/send_time_history.h +++ b/include/webrtc/modules/remote_bitrate_estimator/include/send_time_history.h @@ -13,35 +13,42 @@ #include -#include "webrtc/base/constructormagic.h" #include "webrtc/base/basictypes.h" -#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/modules/include/module_common_types.h" namespace webrtc { +class Clock; +struct PacketInfo; class SendTimeHistory { public: - SendTimeHistory(Clock* clock, int64_t packet_age_limit); - virtual ~SendTimeHistory(); + SendTimeHistory(Clock* clock, int64_t packet_age_limit_ms); + ~SendTimeHistory(); + + void Clear(); + + // Cleanup old entries, then add new packet info with provided parameters. + void AddAndRemoveOld(uint16_t sequence_number, + size_t payload_size, + const PacedPacketInfo& pacing_info); + + // Updates packet info identified by |sequence_number| with |send_time_ms|. + // Return false if not found. + bool OnSentPacket(uint16_t sequence_number, int64_t send_time_ms); - void AddAndRemoveOld(uint16_t sequence_number, size_t length, bool was_paced); - bool OnSentPacket(uint16_t sequence_number, int64_t timestamp); // Look up PacketInfo for a sent packet, based on the sequence number, and - // populate all fields except for receive_time. The packet parameter must + // populate all fields except for arrival_time. The packet parameter must // thus be non-null and have the sequence_number field set. - bool GetInfo(PacketInfo* packet, bool remove); - void Clear(); + bool GetInfo(PacketInfo* packet_info, bool remove); private: - void EraseOld(); - void UpdateOldestSequenceNumber(); - Clock* const clock_; - const int64_t packet_age_limit_; - uint16_t oldest_sequence_number_; // Oldest may not be lowest. - std::map history_; + const int64_t packet_age_limit_ms_; + SequenceNumberUnwrapper seq_num_unwrapper_; + std::map history_; - RTC_DISALLOW_COPY_AND_ASSIGN(SendTimeHistory); + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendTimeHistory); }; } // namespace webrtc diff --git a/include/webrtc/modules/remote_bitrate_estimator/inter_arrival.h b/include/webrtc/modules/remote_bitrate_estimator/inter_arrival.h index 427bafc..088b925 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/inter_arrival.h +++ b/include/webrtc/modules/remote_bitrate_estimator/inter_arrival.h @@ -23,6 +23,11 @@ namespace webrtc { // a client defined rate. class InterArrival { public: + // After this many packet groups received out of order InterArrival will + // reset, assuming that clocks have made a jump. + static constexpr int kReorderedResetThreshold = 3; + static constexpr int64_t kArrivalTimeOffsetThresholdMs = 3000; + // A timestamp group is defined as all packets with a timestamp which are at // most timestamp_group_length_ticks older than the first timestamp in that // group. @@ -40,6 +45,7 @@ class InterArrival { // |packet_size_delta| (output) is the computed size delta. bool ComputeDeltas(uint32_t timestamp, int64_t arrival_time_ms, + int64_t system_time_ms, size_t packet_size, uint32_t* timestamp_delta, int64_t* arrival_time_delta_ms, @@ -61,6 +67,7 @@ class InterArrival { uint32_t first_timestamp; uint32_t timestamp; int64_t complete_time_ms; + int64_t last_system_time_ms; }; // Returns true if the packet with timestamp |timestamp| arrived in order. @@ -72,11 +79,14 @@ class InterArrival { bool BelongsToBurst(int64_t arrival_time_ms, uint32_t timestamp) const; + void Reset(); + const uint32_t kTimestampGroupLengthTicks; TimestampGroup current_timestamp_group_; TimestampGroup prev_timestamp_group_; double timestamp_to_ms_coeff_; bool burst_grouping_; + int num_consecutive_reordered_packets_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(InterArrival); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/overuse_detector.h b/include/webrtc/modules/remote_bitrate_estimator/overuse_detector.h index ce61e3b..03ddb1e 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/overuse_detector.h +++ b/include/webrtc/modules/remote_bitrate_estimator/overuse_detector.h @@ -24,7 +24,7 @@ bool AdaptiveThresholdExperimentIsDisabled(); class OveruseDetector { public: - explicit OveruseDetector(const OverUseDetectorOptions& options); + OveruseDetector(); virtual ~OveruseDetector(); // Update the detection state based on the estimated inter-arrival time delta @@ -49,9 +49,6 @@ class OveruseDetector { double k_up_; double k_down_; double overusing_time_threshold_; - // Must be first member variable. Cannot be const because we need to be - // copyable. - webrtc::OverUseDetectorOptions options_; double threshold_; int64_t last_update_ms_; double prev_offset_; diff --git a/include/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h b/include/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h index d671f39..895ed77 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h +++ b/include/webrtc/modules/remote_bitrate_estimator/overuse_estimator.h @@ -10,7 +10,7 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_ESTIMATOR_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_ESTIMATOR_H_ -#include +#include #include "webrtc/base/constructormagic.h" #include "webrtc/common_types.h" @@ -27,8 +27,11 @@ class OveruseEstimator { // between timestamp groups as defined by the InterArrival class. // |current_hypothesis| should be the hypothesis of the over-use detector at // this time. - void Update(int64_t t_delta, double ts_delta, int size_delta, - BandwidthUsage current_hypothesis); + void Update(int64_t t_delta, + double ts_delta, + int size_delta, + BandwidthUsage current_hypothesis, + int64_t now_ms); // Returns the estimated noise/jitter variance in ms^2. double var_noise() const { @@ -61,7 +64,7 @@ class OveruseEstimator { double process_noise_[2]; double avg_noise_; double var_noise_; - std::list ts_delta_hist_; + std::deque ts_delta_hist_; RTC_DISALLOW_COPY_AND_ASSIGN(OveruseEstimator); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h index a611909..6e37698 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h +++ b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h @@ -68,7 +68,8 @@ struct Cluster { class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator { public: - explicit RemoteBitrateEstimatorAbsSendTime(RemoteBitrateObserver* observer); + RemoteBitrateEstimatorAbsSendTime(RemoteBitrateObserver* observer, + Clock* clock); virtual ~RemoteBitrateEstimatorAbsSendTime() {} void IncomingPacketFeedbackVector( @@ -76,8 +77,7 @@ class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator { void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, - const RTPHeader& header, - bool was_paced) override; + const RTPHeader& header) override; // This class relies on Process() being called periodically (at least once // every other second) for streams to be timed out properly. Therefore it // shouldn't be detached from the ProcessThread except if it's about to be @@ -102,8 +102,7 @@ class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator { void IncomingPacketInfo(int64_t arrival_time_ms, uint32_t send_time_24bits, size_t payload_size, - uint32_t ssrc, - bool was_paced); + uint32_t ssrc); void ComputeClusters(std::list* clusters) const; @@ -119,17 +118,20 @@ class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator { void TimeoutStreams(int64_t now_ms) EXCLUSIVE_LOCKS_REQUIRED(&crit_); rtc::ThreadChecker network_thread_; + Clock* const clock_; RemoteBitrateObserver* const observer_; std::unique_ptr inter_arrival_; std::unique_ptr estimator_; OveruseDetector detector_; RateStatistics incoming_bitrate_; + bool incoming_bitrate_initialized_; std::vector recent_propagation_delta_ms_; std::vector recent_update_time_ms_; std::list probes_; size_t total_probes_received_; int64_t first_packet_time_ms_; int64_t last_update_ms_; + bool uma_recorded_; rtc::CriticalSection crit_; Ssrcs ssrcs_ GUARDED_BY(&crit_); diff --git a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h index 41d570b..31d7962 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h +++ b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h @@ -31,8 +31,7 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator { void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, - const RTPHeader& header, - bool was_paced) override; + const RTPHeader& header) override; void Process() override; int64_t TimeUntilNextProcess() override; void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; @@ -53,14 +52,20 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator { void GetSsrcs(std::vector* ssrcs) const SHARED_LOCKS_REQUIRED(crit_sect_.get()); + // Returns |remote_rate_| if the pointed to object exists, + // otherwise creates it. + AimdRateControl* GetRemoteRate() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get()); + Clock* clock_; SsrcOveruseEstimatorMap overuse_detectors_ GUARDED_BY(crit_sect_.get()); RateStatistics incoming_bitrate_ GUARDED_BY(crit_sect_.get()); + uint32_t last_valid_incoming_bitrate_ GUARDED_BY(crit_sect_.get()); std::unique_ptr remote_rate_ GUARDED_BY(crit_sect_.get()); RemoteBitrateObserver* observer_ GUARDED_BY(crit_sect_.get()); std::unique_ptr crit_sect_; int64_t last_process_time_; int64_t process_interval_ms_ GUARDED_BY(crit_sect_.get()); + bool uma_recorded_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RemoteBitrateEstimatorSingleStream); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h index 12ac9e8..460a3a9 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h +++ b/include/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_unittest_helper.h @@ -17,10 +17,10 @@ #include #include -#include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/constructormagic.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/test/gtest.h" namespace webrtc { namespace testing { @@ -79,7 +79,7 @@ class RtpStream { int64_t GenerateFrame(int64_t time_now_us, PacketList* packets); // The send-side time when the next frame can be generated. - double next_rtp_time() const; + int64_t next_rtp_time() const; // Generates an RTCP packet. RtcpPacket* Rtcp(int64_t time_now_us); @@ -112,7 +112,7 @@ class StreamGenerator { public: typedef std::list RtcpList; - StreamGenerator(int capacity, double time_now); + StreamGenerator(int capacity, int64_t time_now); ~StreamGenerator(); @@ -173,8 +173,7 @@ class RemoteBitrateEstimatorTest : public ::testing::Test { size_t payload_size, int64_t arrival_time, uint32_t rtp_timestamp, - uint32_t absolute_send_time, - bool was_paced); + uint32_t absolute_send_time); // Generates a frame of packets belonging to a stream at a given bitrate and // with a given ssrc. The stream is pushed through a very simple simulated @@ -204,15 +203,16 @@ class RemoteBitrateEstimatorTest : public ::testing::Test { void RateIncreaseRtpTimestampsTestHelper(int expected_iterations); void CapacityDropTestHelper(int number_of_streams, bool wrap_time_stamp, - uint32_t expected_bitrate_drop_delta); + uint32_t expected_bitrate_drop_delta, + int64_t receiver_clock_offset_change_ms); static const uint32_t kDefaultSsrc; - static const int kArrivalTimeClockOffsetMs = 60000; SimulatedClock clock_; // Time at the receiver. std::unique_ptr bitrate_observer_; std::unique_ptr bitrate_estimator_; std::unique_ptr stream_generator_; + int64_t arrival_time_offset_ms_; RTC_DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorTest); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h b/include/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h index 93d5244..71099bf 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h +++ b/include/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.h @@ -39,8 +39,7 @@ class RemoteEstimatorProxy : public RemoteBitrateEstimator { const std::vector& packet_feedback_vector) override; void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, - const RTPHeader& header, - bool was_paced) override; + const RTPHeader& header) override; void RemoveStream(uint32_t ssrc) override {} bool LatestEstimate(std::vector* ssrcs, unsigned int* bitrate_bps) const override; @@ -48,14 +47,17 @@ class RemoteEstimatorProxy : public RemoteBitrateEstimator { void SetMinBitrate(int min_bitrate_bps) override {} int64_t TimeUntilNextProcess() override; void Process() override; + void OnBitrateChanged(int bitrate); - static const int kDefaultProcessIntervalMs; + static const int kMinSendIntervalMs; + static const int kMaxSendIntervalMs; + static const int kDefaultSendIntervalMs; static const int kBackWindowMs; private: void OnPacketArrival(uint16_t sequence_number, int64_t arrival_time) EXCLUSIVE_LOCKS_REQUIRED(&lock_); - bool BuildFeedbackPacket(rtcp::TransportFeedback* feedback_packetket); + bool BuildFeedbackPacket(rtcp::TransportFeedback* feedback_packet); Clock* const clock_; PacketRouter* const packet_router_; @@ -69,6 +71,7 @@ class RemoteEstimatorProxy : public RemoteBitrateEstimator { int64_t window_start_seq_ GUARDED_BY(&lock_); // Map unwrapped seq -> time. std::map packet_arrival_times_ GUARDED_BY(&lock_); + int64_t send_interval_ms_ GUARDED_BY(&lock_); }; } // namespace webrtc diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/bwe.h b/include/webrtc/modules/remote_bitrate_estimator/test/bwe.h index fc3018f..4f87d39 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/bwe.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/bwe.h @@ -109,8 +109,8 @@ class LinkedSet { std::list list_; }; -const int kMinBitrateKbps = 50; -const int kMaxBitrateKbps = 2500; +const int kMinBitrateKbps = 10; +const int kMaxBitrateKbps = 25000; class BweSender : public Module { public: @@ -176,7 +176,7 @@ enum BandwidthEstimatorType { kNullEstimator, kNadaEstimator, kRembEstimator, - kFullSendSideEstimator, + kSendSideEstimator, kTcpEstimator }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h index 5fb3252..963b606 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h @@ -14,11 +14,12 @@ #include #include #include -#include "testing/gtest/include/gtest/gtest.h" + #include "webrtc/base/constructormagic.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h" +#include "webrtc/test/gtest.h" namespace webrtc { diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h index 1fe3a22..c5a16a6 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h @@ -24,7 +24,6 @@ #include #include -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/random.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" @@ -230,16 +229,16 @@ class RateCounterFilter : public PacketProcessor { RateCounterFilter(PacketProcessorListener* listener, int flow_id, const char* name, - const std::string& plot_name); + const std::string& algorithm_name); RateCounterFilter(PacketProcessorListener* listener, const FlowIds& flow_ids, const char* name, - const std::string& plot_name); + const std::string& algorithm_name); RateCounterFilter(PacketProcessorListener* listener, const FlowIds& flow_ids, const char* name, int64_t start_plotting_time_ms, - const std::string& plot_name); + const std::string& algorithm_name); virtual ~RateCounterFilter(); void LogStats(); @@ -250,10 +249,13 @@ class RateCounterFilter : public PacketProcessor { private: Stats packets_per_second_stats_; Stats kbps_stats_; - std::string name_; int64_t start_plotting_time_ms_; +#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE + int flow_id_ = 0; +#endif + std::string name_; // Algorithm name if single flow, Total link utilization if all flows. - std::string plot_name_; + std::string algorithm_name_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RateCounterFilter); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h index 53550fb..9262164 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h @@ -91,9 +91,13 @@ // |name| is a char*, std::string or uint32_t to name the plotted value. // |time| is an int64_t time in ms, or -1 to inherit time from previous context. // |value| is a double precision float to be plotted. +// |ssrc| identifies the source of a stream // |alg_name| is an optional argument, a string #define BWE_TEST_LOGGING_PLOT(figure, name, time, value) #define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) +#define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) +#define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \ + ssrc, alg_name) // Print to stdout in tab-separated format suitable for plotting, e.g.: // BAR figure Context1_Context2_Name x_left width value @@ -179,21 +183,38 @@ _4, _5); \ } while (0) -#define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \ - do { \ - __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ - static_cast(time), true); \ - webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value); \ +#define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \ + do { \ + __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ + static_cast(time), true); \ + webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value); \ } while (0) #define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) \ do { \ __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ static_cast(time), true); \ - webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value, \ + webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ alg_name); \ } while (0) +#define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) \ + do { \ + __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ + static_cast(time), true); \ + webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ + ssrc); \ + } while (0) + +#define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \ + ssrc, alg_name) \ + do { \ + __BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \ + static_cast(time), true); \ + webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \ + ssrc, alg_name); \ + } while (0) + #define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id) \ do { \ BWE_TEST_LOGGING_CONTEXT(name); \ @@ -259,8 +280,17 @@ class Logging { void SetGlobalEnable(bool enabled); void Log(const char format[], ...); - void Plot(int figure, double value); - void Plot(int figure, double value, const std::string& alg_name); + void Plot(int figure, const std::string& name, double value); + void Plot(int figure, + const std::string& name, + double value, + const std::string& alg_name); + void Plot(int figure, const std::string& name, double value, uint32_t ssrc); + void Plot(int figure, + const std::string& name, + double value, + uint32_t ssrc, + const std::string& alg_name); void PlotBar(int figure, const std::string& name, double value, int flow_id); void PlotBaselineBar(int figure, const std::string& name, diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h index 2a33440..c2c4f59 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h @@ -64,6 +64,8 @@ class NadaBweReceiver : public BweReceiver { class NadaBweSender : public BweSender { public: + static const int kMinNadaBitrateKbps; + NadaBweSender(int kbps, BitrateObserver* observer, Clock* clock); NadaBweSender(BitrateObserver* observer, Clock* clock); virtual ~NadaBweSender(); @@ -91,8 +93,6 @@ class NadaBweSender : public BweSender { private: Clock* const clock_; BitrateObserver* const observer_; - // Used as an upper bound for calling AcceleratedRampDown. - const float kMaxCongestionSignalMs = 40.0f + kMinBitrateKbps / 15; // Referred as R_min, default initialization for bitrate R_n. int64_t last_feedback_ms_ = 0; // Referred as delta_0, initialized as an upper bound. diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h index 3dc4f38..855dc6f 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.h @@ -16,6 +16,7 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" namespace webrtc { @@ -45,6 +46,7 @@ class RembBweSender : public BweSender { private: Clock* clock_; + ::testing::NiceMock event_log_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RembBweSender); }; @@ -68,12 +70,15 @@ class RembReceiver : public BweReceiver, public RemoteBitrateObserver { bool LatestEstimate(uint32_t* estimate_bps); std::string estimate_log_prefix_; - bool plot_estimate_; +#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE + bool plot_estimate_ = false; +#endif SimulatedClock clock_; std::unique_ptr recv_stats_; int64_t latest_estimate_bps_; int64_t last_feedback_ms_; std::unique_ptr estimator_; + RTCPReportBlock latest_report_block_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver); }; diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h index 51e29e3..90ec50f 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.h @@ -14,6 +14,7 @@ #include #include +#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h" #include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" @@ -21,10 +22,10 @@ namespace webrtc { namespace testing { namespace bwe { -class FullBweSender : public BweSender, public RemoteBitrateObserver { +class SendSideBweSender : public BweSender, public RemoteBitrateObserver { public: - FullBweSender(int kbps, BitrateObserver* observer, Clock* clock); - virtual ~FullBweSender(); + SendSideBweSender(int kbps, BitrateObserver* observer, Clock* clock); + virtual ~SendSideBweSender(); int GetFeedbackIntervalMs() const override; void GiveFeedback(const FeedbackPacket& feedback) override; @@ -36,7 +37,7 @@ class FullBweSender : public BweSender, public RemoteBitrateObserver { protected: std::unique_ptr bitrate_controller_; - std::unique_ptr rbe_; + std::unique_ptr bwe_; std::unique_ptr feedback_observer_; private: @@ -45,8 +46,11 @@ class FullBweSender : public BweSender, public RemoteBitrateObserver { SendTimeHistory send_time_history_; bool has_received_ack_; uint16_t last_acked_seq_num_; + int64_t last_log_time_ms_; + SequenceNumberUnwrapper seq_num_unwrapper_; + ::testing::NiceMock event_log_; - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FullBweSender); + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(SendSideBweSender); }; class SendSideBweReceiver : public BweReceiver { diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/metric_recorder.h b/include/webrtc/modules/remote_bitrate_estimator/test/metric_recorder.h index 81df278..72edd09 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/metric_recorder.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/metric_recorder.h @@ -16,7 +16,6 @@ #include #include -#include "webrtc/base/common.h" #include "webrtc/base/gtest_prod_util.h" namespace webrtc { diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/packet.h b/include/webrtc/modules/remote_bitrate_estimator/test/packet.h index 4a361c4..9aa596c 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/packet.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/packet.h @@ -42,8 +42,6 @@ class Packet { virtual void set_sender_timestamp_us(int64_t sender_timestamp_us) { sender_timestamp_us_ = sender_timestamp_us; } - virtual void set_paced(bool paced) { paced_ = paced; } - virtual bool paced() const { return paced_; } virtual int64_t creation_time_ms() const { return (creation_time_us_ + 500) / 1000; } @@ -58,7 +56,6 @@ class Packet { int64_t send_time_us_; // Time the packet left last processor touching it. int64_t sender_timestamp_us_; // Time the packet left the Sender. size_t payload_size_; // Size of the (non-existent, simulated) payload. - bool paced_; // True if sent through paced sender. }; class MediaPacket : public Packet { diff --git a/include/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h b/include/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h index 4990574..2bc3d01 100644 --- a/include/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h +++ b/include/webrtc/modules/remote_bitrate_estimator/test/packet_sender.h @@ -114,8 +114,9 @@ class PacedVideoSender : public VideoSender, public PacedSender::PacketSender { uint16_t sequence_number, int64_t capture_time_ms, bool retransmission, - int probe_cluster_id) override; - size_t TimeToSendPadding(size_t bytes) override; + const PacedPacketInfo& pacing_info) override; + size_t TimeToSendPadding(size_t bytes, + const PacedPacketInfo& pacing_info) override; // Implements BitrateObserver. void OnNetworkChanged(uint32_t target_bitrate_bps, diff --git a/include/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h b/include/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h deleted file mode 100644 index c97ef57..0000000 --- a/include/webrtc/modules/remote_bitrate_estimator/transport_feedback_adapter.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_ -#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_ - -#include -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/thread_annotations.h" -#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" - -namespace webrtc { - -class ProcessThread; -class RemoteBitrateEstimator; - -class TransportFeedbackAdapter : public TransportFeedbackObserver, - public CallStatsObserver, - public RemoteBitrateObserver { - public: - TransportFeedbackAdapter(BitrateController* bitrate_controller, Clock* clock); - virtual ~TransportFeedbackAdapter(); - - void SetBitrateEstimator(RemoteBitrateEstimator* rbe); - RemoteBitrateEstimator* GetBitrateEstimator() const { - return bitrate_estimator_.get(); - } - - // Implements TransportFeedbackObserver. - void AddPacket(uint16_t sequence_number, - size_t length, - bool was_paced) override; - void OnSentPacket(uint16_t sequence_number, int64_t send_time_ms); - void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override; - - // Implements CallStatsObserver. - void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override; - - private: - // Implements RemoteBitrateObserver. - void OnReceiveBitrateChanged(const std::vector& ssrcs, - uint32_t bitrate) override; - - rtc::CriticalSection lock_; - SendTimeHistory send_time_history_ GUARDED_BY(&lock_); - BitrateController* bitrate_controller_; - std::unique_ptr bitrate_estimator_; - Clock* const clock_; - int64_t current_offset_ms_; - int64_t last_timestamp_us_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TRANSPORT_FEEDBACK_ADAPTER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/include/flexfec_receiver.h b/include/webrtc/modules/rtp_rtcp/include/flexfec_receiver.h new file mode 100644 index 0000000..67dc813 --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/include/flexfec_receiver.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_RECEIVER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_RECEIVER_H_ + +#include + +#include "webrtc/base/basictypes.h" +#include "webrtc/base/sequenced_task_checker.h" +#include "webrtc/call/call.h" +#include "webrtc/modules/rtp_rtcp/include/ulpfec_receiver.h" +#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { + +// Callback interface for packets recovered by FlexFEC. The implementation +// should be able to demultiplex the recovered RTP packets based on SSRC. +class RecoveredPacketReceiver { + public: + virtual bool OnRecoveredPacket(const uint8_t* packet, size_t length) = 0; + + protected: + virtual ~RecoveredPacketReceiver() = default; +}; + +class FlexfecReceiver { + public: + FlexfecReceiver(uint32_t ssrc, + uint32_t protected_media_ssrc, + RecoveredPacketReceiver* recovered_packet_receiver); + ~FlexfecReceiver(); + + // Inserts a received packet (can be either media or FlexFEC) into the + // internal buffer, and sends the received packets to the erasure code. + // All newly recovered packets are sent back through the callback. + void OnRtpPacket(const RtpPacketReceived& packet); + + // Returns a counter describing the added and recovered packets. + FecPacketCounter GetPacketCounter() const; + + // Protected to aid testing. + protected: + bool AddReceivedPacket(const RtpPacketReceived& packet); + bool ProcessReceivedPackets(); + + private: + // Config. + const uint32_t ssrc_; + const uint32_t protected_media_ssrc_; + + // Erasure code interfacing and callback. + std::unique_ptr erasure_code_ + GUARDED_BY(sequence_checker_); + ForwardErrorCorrection::ReceivedPacketList received_packets_ + GUARDED_BY(sequence_checker_); + ForwardErrorCorrection::RecoveredPacketList recovered_packets_ + GUARDED_BY(sequence_checker_); + RecoveredPacketReceiver* const recovered_packet_receiver_; + + // Logging and stats. + Clock* const clock_; + int64_t last_recovered_packet_ms_ GUARDED_BY(sequence_checker_); + FecPacketCounter packet_counter_ GUARDED_BY(sequence_checker_); + + rtc::SequencedTaskChecker sequence_checker_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_RECEIVER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/include/flexfec_sender.h b/include/webrtc/modules/rtp_rtcp/include/flexfec_sender.h new file mode 100644 index 0000000..fa4bd6e --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/include/flexfec_sender.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_SENDER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_SENDER_H_ + +#include +#include + +#include "webrtc/base/basictypes.h" +#include "webrtc/base/random.h" +#include "webrtc/base/sequenced_task_checker.h" +#include "webrtc/config.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/include/flexfec_sender.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" +#include "webrtc/modules/rtp_rtcp/source/ulpfec_generator.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { + +class RtpPacketToSend; + +// Note that this class is not thread safe, and thus requires external +// synchronization. + +class FlexfecSender { + public: + FlexfecSender(int payload_type, + uint32_t ssrc, + uint32_t protected_media_ssrc, + const std::vector& rtp_header_extensions, + Clock* clock); + ~FlexfecSender(); + + uint32_t ssrc() const { return ssrc_; } + + // Sets the FEC rate, max frames sent before FEC packets are sent, + // and what type of generator matrices are used. + void SetFecParameters(const FecProtectionParams& params); + + // Adds a media packet to the internal buffer. When enough media packets + // have been added, the FEC packets are generated and stored internally. + // These FEC packets are then obtained by calling GetFecPackets(). + // Returns true if the media packet was successfully added. + bool AddRtpPacketAndGenerateFec(const RtpPacketToSend& packet); + + // Returns true if there are generated FEC packets available. + bool FecAvailable() const; + + // Returns generated FlexFEC packets. + std::vector> GetFecPackets(); + + // Returns the overhead, per packet, for FlexFEC. + size_t MaxPacketOverhead() const; + + private: + // Utility. + Clock* const clock_; + Random random_; + int64_t last_generated_packet_ms_; + + // Config. + const int payload_type_; + const uint32_t timestamp_offset_; + const uint32_t ssrc_; + const uint32_t protected_media_ssrc_; + // Sequence number of next packet to generate. + uint16_t seq_num_; + + // Implementation. + UlpfecGenerator ulpfec_generator_; + const RtpHeaderExtensionMap rtp_header_extension_map_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_FLEXFEC_SENDER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/include/receive_statistics.h b/include/webrtc/modules/rtp_rtcp/include/receive_statistics.h index cc21e22..90a848a 100644 --- a/include/webrtc/modules/rtp_rtcp/include/receive_statistics.h +++ b/include/webrtc/modules/rtp_rtcp/include/receive_statistics.h @@ -46,7 +46,7 @@ class StreamStatistician { typedef std::map StatisticianMap; -class ReceiveStatistics : public Module { +class ReceiveStatistics { public: virtual ~ReceiveStatistics() {} @@ -89,8 +89,6 @@ class NullReceiveStatistics : public ReceiveStatistics { size_t packet_length) override; StatisticianMap GetActiveStatisticians() const override; StreamStatistician* GetStatistician(uint32_t ssrc) const override; - int64_t TimeUntilNextProcess() override; - void Process() override; void SetMaxReorderingThreshold(int max_reordering_threshold) override; void RegisterRtcpStatisticsCallback( RtcpStatisticsCallback* callback) override; diff --git a/include/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h b/include/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h index 207e749..118df4c 100644 --- a/include/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h +++ b/include/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h @@ -14,7 +14,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" +#include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h" namespace webrtc { @@ -43,7 +43,7 @@ class RemoteNtpTimeEstimator { private: Clock* clock_; std::unique_ptr ts_extrapolator_; - RtcpList rtcp_list_; + RtpToNtpEstimator rtp_to_ntp_; int64_t last_timing_log_ms_; RTC_DISALLOW_COPY_AND_ASSIGN(RemoteNtpTimeEstimator); }; diff --git a/include/webrtc/modules/rtp_rtcp/include/rtp_cvo.h b/include/webrtc/modules/rtp_rtcp/include/rtp_cvo.h index 5d5c995..5fa0619 100644 --- a/include/webrtc/modules/rtp_rtcp/include/rtp_cvo.h +++ b/include/webrtc/modules/rtp_rtcp/include/rtp_cvo.h @@ -10,8 +10,8 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_CVO_H_ #define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_CVO_H_ +#include "webrtc/api/video/video_rotation.h" #include "webrtc/base/checks.h" -#include "webrtc/common_video/rotation.h" namespace webrtc { @@ -34,8 +34,10 @@ inline uint8_t ConvertVideoRotationToCVOByte(VideoRotation rotation) { return 0; } -inline VideoRotation ConvertCVOByteToVideoRotation(uint8_t rotation) { - switch (rotation) { +inline VideoRotation ConvertCVOByteToVideoRotation(uint8_t cvo_byte) { + // CVO byte: |0 0 0 0 C F R R|. + const uint8_t rotation_bits = cvo_byte & 0x3; + switch (rotation_bits) { case 0: return kVideoRotation_0; case 1: diff --git a/include/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h b/include/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h index a199755..668fe87 100644 --- a/include/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h +++ b/include/webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h @@ -13,68 +13,46 @@ #include #include +#include #include "webrtc/base/criticalsection.h" +#include "webrtc/base/deprecation.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" namespace webrtc { -// This strategy deals with the audio/video-specific aspects -// of payload handling. +struct CodecInst; +class VideoCodec; + +// TODO(magjed): Remove once external code is updated. class RTPPayloadStrategy { public: - virtual ~RTPPayloadStrategy() {} - - virtual bool CodecsMustBeUnique() const = 0; - - virtual bool PayloadIsCompatible(const RtpUtility::Payload& payload, - const uint32_t frequency, - const size_t channels, - const uint32_t rate) const = 0; - - virtual void UpdatePayloadRate(RtpUtility::Payload* payload, - const uint32_t rate) const = 0; - - virtual RtpUtility::Payload* CreatePayloadType( - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int8_t payloadType, - const uint32_t frequency, - const size_t channels, - const uint32_t rate) const = 0; - - virtual int GetPayloadTypeFrequency( - const RtpUtility::Payload& payload) const = 0; - - static RTPPayloadStrategy* CreateStrategy(const bool handling_audio); - - protected: - RTPPayloadStrategy() {} + static RTPPayloadStrategy* CreateStrategy(bool handling_audio) { + return nullptr; + } }; class RTPPayloadRegistry { public: - // The registry takes ownership of the strategy. - explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy); + RTPPayloadRegistry(); ~RTPPayloadRegistry(); + // TODO(magjed): Remove once external code is updated. + explicit RTPPayloadRegistry(RTPPayloadStrategy* rtp_payload_strategy) + : RTPPayloadRegistry() {} - int32_t RegisterReceivePayload( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - const int8_t payload_type, - const uint32_t frequency, - const size_t channels, - const uint32_t rate, - bool* created_new_payload_type); + // TODO(magjed): Split RTPPayloadRegistry into separate Audio and Video class + // and simplify the code. http://crbug/webrtc/6743. + int32_t RegisterReceivePayload(const CodecInst& audio_codec, + bool* created_new_payload_type); + int32_t RegisterReceivePayload(const VideoCodec& video_codec); - int32_t DeRegisterReceivePayload( - const int8_t payload_type); + int32_t DeRegisterReceivePayload(int8_t payload_type); - int32_t ReceivePayloadType( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - const uint32_t frequency, - const size_t channels, - const uint32_t rate, - int8_t* payload_type) const; + int32_t ReceivePayloadType(const CodecInst& audio_codec, + int8_t* payload_type) const; + int32_t ReceivePayloadType(const VideoCodec& video_codec, + int8_t* payload_type) const; bool RtxEnabled() const; @@ -90,7 +68,7 @@ class RTPPayloadRegistry { const uint8_t* packet, size_t* packet_length, uint32_t original_ssrc, - const RTPHeader& header) const; + const RTPHeader& header); bool IsRed(const RTPHeader& header) const; @@ -118,13 +96,9 @@ class RTPPayloadRegistry { // Returns true if the new media payload type has not changed. bool ReportMediaPayloadType(uint8_t media_payload_type); - int8_t red_payload_type() const { - rtc::CritScope cs(&crit_sect_); - return red_payload_type_; - } + int8_t red_payload_type() const { return GetPayloadTypeWithName("red"); } int8_t ulpfec_payload_type() const { - rtc::CritScope cs(&crit_sect_); - return ulpfec_payload_type_; + return GetPayloadTypeWithName("ulpfec"); } int8_t last_received_payload_type() const { rtc::CritScope cs(&crit_sect_); @@ -140,45 +114,30 @@ class RTPPayloadRegistry { return last_received_media_payload_type_; } - bool use_rtx_payload_mapping_on_restore() const { - rtc::CritScope cs(&crit_sect_); - return use_rtx_payload_mapping_on_restore_; - } - - void set_use_rtx_payload_mapping_on_restore(bool val) { - rtc::CritScope cs(&crit_sect_); - use_rtx_payload_mapping_on_restore_ = val; - } + RTC_DEPRECATED void set_use_rtx_payload_mapping_on_restore(bool val) {} private: // Prunes the payload type map of the specific payload type, if it exists. void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - const size_t payload_name_length, - const uint32_t frequency, - const size_t channels, - const uint32_t rate); + const CodecInst& audio_codec); bool IsRtxInternal(const RTPHeader& header) const; + // Returns the payload type for the payload with name |payload_name|, or -1 if + // no such payload is registered. + int8_t GetPayloadTypeWithName(const char* payload_name) const; rtc::CriticalSection crit_sect_; - RtpUtility::PayloadTypeMap payload_type_map_; - std::unique_ptr rtp_payload_strategy_; - int8_t red_payload_type_; - int8_t ulpfec_payload_type_; + std::map payload_type_map_; int8_t incoming_payload_type_; - int8_t last_received_payload_type_; - int8_t last_received_media_payload_type_; + int8_t last_received_payload_type_; + int8_t last_received_media_payload_type_; bool rtx_; - // TODO(changbin): Remove rtx_payload_type_ once interop with old clients that - // only understand one RTX PT is no longer needed. - int rtx_payload_type_; // Mapping rtx_payload_type_map_[rtx] = associated. std::map rtx_payload_type_map_; - // When true, use rtx_payload_type_map_ when restoring RTX packets to get the - // correct payload type. - bool use_rtx_payload_mapping_on_restore_; uint32_t ssrc_rtx_; + // Only warn once per payload type, if an RTX packet is received but + // no associated payload type found in |rtx_payload_type_map_|. + std::set payload_types_with_suppressed_warnings_ GUARDED_BY(crit_sect_); }; } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/include/rtp_receiver.h b/include/webrtc/modules/rtp_rtcp/include/rtp_receiver.h index 9db1c63..54a99c9 100644 --- a/include/webrtc/modules/rtp_rtcp/include/rtp_receiver.h +++ b/include/webrtc/modules/rtp_rtcp/include/rtp_receiver.h @@ -16,7 +16,9 @@ namespace webrtc { +struct CodecInst; class RTPPayloadRegistry; +class VideoCodec; class TelephoneEventHandler { public: @@ -56,12 +58,9 @@ class RtpReceiver { // Registers a receive payload in the payload registry and notifies the media // receiver strategy. - virtual int32_t RegisterReceivePayload( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - const int8_t payload_type, - const uint32_t frequency, - const size_t channels, - const uint32_t rate) = 0; + virtual int32_t RegisterReceivePayload(const CodecInst& audio_codec) = 0; + // Registers a receive payload in the payload registry. + virtual int32_t RegisterReceivePayload(const VideoCodec& video_codec) = 0; // De-registers |payload_type| from the payload registry. virtual int32_t DeRegisterReceivePayload(const int8_t payload_type) = 0; diff --git a/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h b/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h index 6658988..186e135 100644 --- a/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h +++ b/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h @@ -17,17 +17,23 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/deprecation.h" +#include "webrtc/base/optional.h" #include "webrtc/modules/include/module.h" +#include "webrtc/modules/rtp_rtcp/include/flexfec_sender.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/video_coding/include/video_coding_defines.h" namespace webrtc { + // Forward declarations. +class OverheadObserver; +class RateLimiter; class ReceiveStatistics; class RemoteBitrateEstimator; +class RtcEventLog; class RtpReceiver; class Transport; -class RtcEventLog; +class VideoBitrateAllocationObserver; RTPExtensionType StringToRtpExtensionType(const std::string& extension); @@ -40,617 +46,437 @@ class RtpRtcp : public Module { struct Configuration { Configuration(); - /* id - Unique identifier of this RTP/RTCP module object - * audio - True for a audio version of the RTP/RTCP module - * object false will create a video version - * clock - The clock to use to read time. If NULL object - * will be using the system clock. - * incoming_data - Callback object that will receive the incoming - * data. May not be NULL; default callback will do - * nothing. - * incoming_messages - Callback object that will receive the incoming - * RTP messages. May not be NULL; default callback - * will do nothing. - * outgoing_transport - Transport object that will be called when packets - * are ready to be sent out on the network - * intra_frame_callback - Called when the receiver request a intra frame. - * bandwidth_callback - Called when we receive a changed estimate from - * the receiver of out stream. - * remote_bitrate_estimator - Estimates the bandwidth available for a set of - * streams from the same client. - * paced_sender - Spread any bursts of packets into smaller - * bursts to minimize packet loss. - */ - bool audio; - bool receiver_only; - Clock* clock; + // True for a audio version of the RTP/RTCP module object false will create + // a video version. + bool audio = false; + bool receiver_only = false; + + // The clock to use to read time. If nullptr then system clock will be used. + Clock* clock = nullptr; + ReceiveStatistics* receive_statistics; - Transport* outgoing_transport; - RtcpIntraFrameObserver* intra_frame_callback; - RtcpBandwidthObserver* bandwidth_callback; - TransportFeedbackObserver* transport_feedback_callback; - RtcpRttStats* rtt_stats; - RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer; - RemoteBitrateEstimator* remote_bitrate_estimator; - RtpPacketSender* paced_sender; - TransportSequenceNumberAllocator* transport_sequence_number_allocator; - BitrateStatisticsObserver* send_bitrate_observer; - FrameCountObserver* send_frame_count_observer; - SendSideDelayObserver* send_side_delay_observer; - RtcEventLog* event_log; - SendPacketObserver* send_packet_observer; + + // Transport object that will be called when packets are ready to be sent + // out on the network. + Transport* outgoing_transport = nullptr; + + // Called when the receiver request a intra frame. + RtcpIntraFrameObserver* intra_frame_callback = nullptr; + + // Called when we receive a changed estimate from the receiver of out + // stream. + RtcpBandwidthObserver* bandwidth_callback = nullptr; + + TransportFeedbackObserver* transport_feedback_callback = nullptr; + VideoBitrateAllocationObserver* bitrate_allocation_observer = nullptr; + RtcpRttStats* rtt_stats = nullptr; + RtcpPacketTypeCounterObserver* rtcp_packet_type_counter_observer = nullptr; + + // Estimates the bandwidth available for a set of streams from the same + // client. + RemoteBitrateEstimator* remote_bitrate_estimator = nullptr; + + // Spread any bursts of packets into smaller bursts to minimize packet loss. + RtpPacketSender* paced_sender = nullptr; + + // Generate FlexFEC packets. + // TODO(brandtr): Remove when FlexfecSender is wired up to PacedSender. + FlexfecSender* flexfec_sender = nullptr; + + TransportSequenceNumberAllocator* transport_sequence_number_allocator = + nullptr; + BitrateStatisticsObserver* send_bitrate_observer = nullptr; + FrameCountObserver* send_frame_count_observer = nullptr; + SendSideDelayObserver* send_side_delay_observer = nullptr; + RtcEventLog* event_log = nullptr; + SendPacketObserver* send_packet_observer = nullptr; + RateLimiter* retransmission_rate_limiter = nullptr; + OverheadObserver* overhead_observer = nullptr; + + private: RTC_DISALLOW_COPY_AND_ASSIGN(Configuration); }; - /* - * Create a RTP/RTCP module object using the system clock. - * - * configuration - Configuration of the RTP/RTCP module. - */ + // Create a RTP/RTCP module object using the system clock. + // |configuration| - Configuration of the RTP/RTCP module. static RtpRtcp* CreateRtpRtcp(const RtpRtcp::Configuration& configuration); - /************************************************************************** - * - * Receiver functions - * - ***************************************************************************/ - - virtual int32_t IncomingRtcpPacket(const uint8_t* incoming_packet, - size_t incoming_packet_length) = 0; - - virtual void SetRemoteSSRC(uint32_t ssrc) = 0; - - /************************************************************************** - * - * Sender - * - ***************************************************************************/ - - /* - * set MTU - * - * size - Max transfer unit in bytes, default is 1500 - * - * return -1 on failure else 0 - */ - virtual int32_t SetMaxTransferUnit(uint16_t size) = 0; - - /* - * set transtport overhead - * default is IPv4 and UDP with no encryption - * - * TCP - true for TCP false UDP - * IPv6 - true for IP version 6 false for version 4 - * authenticationOverhead - number of bytes to leave for an - * authentication header - * - * return -1 on failure else 0 - */ - virtual int32_t SetTransportOverhead( - bool TCP, - bool IPV6, - uint8_t authenticationOverhead = 0) = 0; - - /* - * Get max payload length - * - * A combination of the configuration MaxTransferUnit and - * TransportOverhead. - * Does not account FEC/ULP/RED overhead if FEC is enabled. - * Does not account for RTP headers - */ - virtual uint16_t MaxPayloadLength() const = 0; - - /* - * Get max data payload length - * - * A combination of the configuration MaxTransferUnit, headers and - * TransportOverhead. - * Takes into account FEC/ULP/RED overhead if FEC is enabled. - * Takes into account RTP headers - */ - virtual uint16_t MaxDataPayloadLength() const = 0; - - /* - * set codec name and payload type - * - * return -1 on failure else 0 - */ - virtual int32_t RegisterSendPayload( - const CodecInst& voiceCodec) = 0; - - /* - * set codec name and payload type - * - * return -1 on failure else 0 - */ - virtual int32_t RegisterSendPayload( - const VideoCodec& videoCodec) = 0; - - virtual void RegisterVideoSendPayload(int payload_type, - const char* payload_name) = 0; - - /* - * Unregister a send payload - * - * payloadType - payload type of codec - * - * return -1 on failure else 0 - */ - virtual int32_t DeRegisterSendPayload(int8_t payloadType) = 0; - - /* - * (De)register RTP header extension type and id. - * - * return -1 on failure else 0 - */ - virtual int32_t RegisterSendRtpHeaderExtension(RTPExtensionType type, - uint8_t id) = 0; - - virtual int32_t DeregisterSendRtpHeaderExtension(RTPExtensionType type) = 0; - - /* - * get start timestamp - */ - virtual uint32_t StartTimestamp() const = 0; - - /* - * configure start timestamp, default is a random number - * - * timestamp - start timestamp - */ - virtual void SetStartTimestamp(uint32_t timestamp) = 0; - - /* - * Get SequenceNumber - */ - virtual uint16_t SequenceNumber() const = 0; - - /* - * Set SequenceNumber, default is a random number - */ - virtual void SetSequenceNumber(uint16_t seq) = 0; - - virtual void SetRtpState(const RtpState& rtp_state) = 0; - virtual void SetRtxState(const RtpState& rtp_state) = 0; - virtual RtpState GetRtpState() const = 0; - virtual RtpState GetRtxState() const = 0; - - /* - * Get SSRC - */ - virtual uint32_t SSRC() const = 0; - - /* - * configure SSRC, default is a random number - */ - virtual void SetSSRC(uint32_t ssrc) = 0; - - /* - * Set CSRC - * - * csrcs - vector of CSRCs - */ - virtual void SetCsrcs(const std::vector& csrcs) = 0; - - /* - * Turn on/off sending RTX (RFC 4588). The modes can be set as a combination - * of values of the enumerator RtxMode. - */ - virtual void SetRtxSendStatus(int modes) = 0; - - /* - * Get status of sending RTX (RFC 4588). The returned value can be - * a combination of values of the enumerator RtxMode. - */ - virtual int RtxSendStatus() const = 0; - - // Sets the SSRC to use when sending RTX packets. This doesn't enable RTX, - // only the SSRC is set. - virtual void SetRtxSsrc(uint32_t ssrc) = 0; - - // Sets the payload type to use when sending RTX packets. Note that this - // doesn't enable RTX, only the payload type is set. - virtual void SetRtxSendPayloadType(int payload_type, - int associated_payload_type) = 0; - - /* - * sends kRtcpByeCode when going from true to false - * - * sending - on/off - * - * return -1 on failure else 0 - */ - virtual int32_t SetSendingStatus(bool sending) = 0; - - /* - * get send status - */ - virtual bool Sending() const = 0; - - /* - * Starts/Stops media packets, on by default - * - * sending - on/off - */ - virtual void SetSendingMediaStatus(bool sending) = 0; - - /* - * get send status - */ - virtual bool SendingMedia() const = 0; - - /* - * get sent bitrate in Kbit/s - */ - virtual void BitrateSent(uint32_t* totalRate, - uint32_t* videoRate, - uint32_t* fecRate, - uint32_t* nackRate) const = 0; - - /* - * Used by the codec module to deliver a video or audio frame for - * packetization. - * - * frameType - type of frame to send - * payloadType - payload type of frame to send - * timestamp - timestamp of frame to send - * payloadData - payload buffer of frame to send - * payloadSize - size of payload buffer to send - * fragmentation - fragmentation offset data for fragmented frames such - * as layers or RED - * - * return -1 on failure else 0 - */ - virtual int32_t SendOutgoingData( - FrameType frameType, - int8_t payloadType, - uint32_t timeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - size_t payloadSize, - const RTPFragmentationHeader* fragmentation = NULL, - const RTPVideoHeader* rtpVideoHdr = NULL) = 0; - - virtual bool TimeToSendPacket(uint32_t ssrc, - uint16_t sequence_number, - int64_t capture_time_ms, - bool retransmission) = 0; - - virtual size_t TimeToSendPadding(size_t bytes) = 0; - - // Called on generation of new statistics after an RTP send. - virtual void RegisterSendChannelRtpStatisticsCallback( - StreamDataCountersCallback* callback) = 0; - virtual StreamDataCountersCallback* - GetSendChannelRtpStatisticsCallback() const = 0; - - /************************************************************************** - * - * RTCP - * - ***************************************************************************/ - - /* - * Get RTCP status - */ - virtual RtcpMode RTCP() const = 0; - - /* - * configure RTCP status i.e on(compound or non- compound)/off - * - * method - RTCP method to use - */ - virtual void SetRTCPStatus(RtcpMode method) = 0; - - /* - * Set RTCP CName (i.e unique identifier) - * - * return -1 on failure else 0 - */ - virtual int32_t SetCNAME(const char* c_name) = 0; - - /* - * Get remote CName - * - * return -1 on failure else 0 - */ - virtual int32_t RemoteCNAME(uint32_t remoteSSRC, - char cName[RTCP_CNAME_SIZE]) const = 0; - - /* - * Get remote NTP - * - * return -1 on failure else 0 - */ - virtual int32_t RemoteNTP( - uint32_t *ReceivedNTPsecs, - uint32_t *ReceivedNTPfrac, - uint32_t *RTCPArrivalTimeSecs, - uint32_t *RTCPArrivalTimeFrac, - uint32_t *rtcp_timestamp) const = 0; - - /* - * AddMixedCNAME - * - * return -1 on failure else 0 - */ - virtual int32_t AddMixedCNAME(uint32_t SSRC, const char* c_name) = 0; - - /* - * RemoveMixedCNAME - * - * return -1 on failure else 0 - */ - virtual int32_t RemoveMixedCNAME(uint32_t SSRC) = 0; - - /* - * Get RoundTripTime - * - * return -1 on failure else 0 - */ - virtual int32_t RTT(uint32_t remoteSSRC, - int64_t* RTT, - int64_t* avgRTT, - int64_t* minRTT, - int64_t* maxRTT) const = 0; - - /* - * Force a send of a RTCP packet - * periodic SR and RR are triggered via the process function - * - * return -1 on failure else 0 - */ - virtual int32_t SendRTCP(RTCPPacketType rtcpPacketType) = 0; - - /* - * Force a send of a RTCP packet with more than one packet type. - * periodic SR and RR are triggered via the process function - * - * return -1 on failure else 0 - */ - virtual int32_t SendCompoundRTCP( - const std::set& rtcpPacketTypes) = 0; - - /* - * Good state of RTP receiver inform sender - */ - virtual int32_t SendRTCPReferencePictureSelection( - const uint64_t pictureID) = 0; - - /* - * Send a RTCP Slice Loss Indication (SLI) - * 6 least significant bits of pictureID - */ - virtual int32_t SendRTCPSliceLossIndication(uint8_t pictureID) = 0; - - /* - * Statistics of the amount of data sent - * - * return -1 on failure else 0 - */ - virtual int32_t DataCountersRTP( - size_t* bytesSent, - uint32_t* packetsSent) const = 0; - - /* - * Get send statistics for the RTP and RTX stream. - */ - virtual void GetSendStreamDataCounters( - StreamDataCounters* rtp_counters, - StreamDataCounters* rtx_counters) const = 0; - - /* - * Get packet loss statistics for the RTP stream. - */ - virtual void GetRtpPacketLossStats( - bool outgoing, - uint32_t ssrc, - struct RtpPacketLossStats* loss_stats) const = 0; - - /* - * Get received RTCP sender info - * - * return -1 on failure else 0 - */ - virtual int32_t RemoteRTCPStat(RTCPSenderInfo* senderInfo) = 0; - - /* - * Get received RTCP report block - * - * return -1 on failure else 0 - */ - virtual int32_t RemoteRTCPStat( - std::vector* receiveBlocks) const = 0; - - /* - * (APP) Application specific data - * - * return -1 on failure else 0 - */ - virtual int32_t SetRTCPApplicationSpecificData(uint8_t subType, - uint32_t name, - const uint8_t* data, - uint16_t length) = 0; - /* - * (XR) VOIP metric - * - * return -1 on failure else 0 - */ - virtual int32_t SetRTCPVoIPMetrics( - const RTCPVoIPMetric* VoIPMetric) = 0; - - /* - * (XR) Receiver Reference Time Report - */ - virtual void SetRtcpXrRrtrStatus(bool enable) = 0; - - virtual bool RtcpXrRrtrStatus() const = 0; - - /* - * (REMB) Receiver Estimated Max Bitrate - */ - virtual bool REMB() const = 0; - - virtual void SetREMBStatus(bool enable) = 0; - - virtual void SetREMBData(uint32_t bitrate, - const std::vector& ssrcs) = 0; - - /* - * (TMMBR) Temporary Max Media Bit Rate - */ - virtual bool TMMBR() const = 0; - - virtual void SetTMMBRStatus(bool enable) = 0; - - /* - * (NACK) - */ - - /* - * TODO(holmer): Propagate this API to VideoEngine. - * Returns the currently configured selective retransmission settings. - */ - virtual int SelectiveRetransmissions() const = 0; - - /* - * TODO(holmer): Propagate this API to VideoEngine. - * Sets the selective retransmission settings, which will decide which - * packets will be retransmitted if NACKed. Settings are constructed by - * combining the constants in enum RetransmissionMode with bitwise OR. - * All packets are retransmitted if kRetransmitAllPackets is set, while no - * packets are retransmitted if kRetransmitOff is set. - * By default all packets except FEC packets are retransmitted. For VP8 - * with temporal scalability only base layer packets are retransmitted. - * - * Returns -1 on failure, otherwise 0. - */ - virtual int SetSelectiveRetransmissions(uint8_t settings) = 0; - - /* - * Send a Negative acknowledgement packet - * - * return -1 on failure else 0 - */ - // TODO(philipel): Deprecate this and start using SendNack instead, - // mostly because we want a function that actually send - // NACK for the specified packets. - virtual int32_t SendNACK(const uint16_t* nackList, uint16_t size) = 0; - - /* - * Send NACK for the packets specified. - * - * Note: This assumes the caller keeps track of timing and doesn't rely on - * the RTP module to do this. - */ - virtual void SendNack(const std::vector& sequence_numbers) = 0; - - /* - * Store the sent packets, needed to answer to a Negative acknowledgement - * requests - */ - virtual void SetStorePacketsStatus(bool enable, uint16_t numberToStore) = 0; - - // Returns true if the module is configured to store packets. - virtual bool StorePackets() const = 0; - - // Called on receipt of RTCP report block from remote side. - virtual void RegisterRtcpStatisticsCallback( - RtcpStatisticsCallback* callback) = 0; - virtual RtcpStatisticsCallback* - GetRtcpStatisticsCallback() = 0; - // BWE feedback packets. - virtual bool SendFeedbackPacket(const rtcp::TransportFeedback& packet) = 0; - - /************************************************************************** - * - * Audio - * - ***************************************************************************/ - - /* - * set audio packet size, used to determine when it's time to send a DTMF - * packet in silence (CNG) - * - * return -1 on failure else 0 - */ - virtual int32_t SetAudioPacketSize(uint16_t packetSizeSamples) = 0; - - /* - * Send a TelephoneEvent tone using RFC 2833 (4733) - * - * return -1 on failure else 0 - */ - virtual int32_t SendTelephoneEventOutband(uint8_t key, - uint16_t time_ms, - uint8_t level) = 0; - - /* - * Set payload type for Redundant Audio Data RFC 2198 - * - * return -1 on failure else 0 - */ - virtual int32_t SetSendREDPayloadType(int8_t payloadType) = 0; - - /* - * Get payload type for Redundant Audio Data RFC 2198 - * - * return -1 on failure else 0 - */ - virtual int32_t SendREDPayloadType(int8_t* payload_type) const = 0; - /* - * Store the audio level in dBov for header-extension-for-audio-level- - * indication. - * This API shall be called before transmision of an RTP packet to ensure - * that the |level| part of the extended RTP header is updated. - * - * return -1 on failure else 0. - */ - virtual int32_t SetAudioLevel(uint8_t level_dBov) = 0; - - /************************************************************************** - * - * Video - * - ***************************************************************************/ - - /* - * Set the target send bitrate - */ - virtual void SetTargetSendBitrate(uint32_t bitrate_bps) = 0; - - /* - * Turn on/off generic FEC - */ - virtual void SetGenericFECStatus(bool enable, - uint8_t payload_type_red, - uint8_t payload_type_fec) = 0; - - /* - * Get generic FEC setting - */ - virtual void GenericFECStatus(bool* enable, - uint8_t* payload_type_red, - uint8_t* payload_type_fec) = 0; - - virtual int32_t SetFecParameters( - const FecProtectionParams* delta_params, - const FecProtectionParams* key_params) = 0; - - /* - * Set method for requestion a new key frame - * - * return -1 on failure else 0 - */ - virtual int32_t SetKeyFrameRequestMethod(KeyFrameRequestMethod method) = 0; - - /* - * send a request for a keyframe - * - * return -1 on failure else 0 - */ - virtual int32_t RequestKeyFrame() = 0; + // ************************************************************************** + // Receiver functions + // ************************************************************************** + + virtual int32_t IncomingRtcpPacket(const uint8_t* incoming_packet, + size_t incoming_packet_length) = 0; + + virtual void SetRemoteSSRC(uint32_t ssrc) = 0; + + // ************************************************************************** + // Sender + // ************************************************************************** + + // TODO(nisse): Deprecated. Kept temporarily, as an alias for the + // new function which has slighly different semantics. Delete as + // soon as known applications are updated. + virtual int32_t SetMaxTransferUnit(uint16_t size) { + SetMaxRtpPacketSize(size); + return 0; + } + + // Sets the maximum size of an RTP packet, including RTP headers. + virtual void SetMaxRtpPacketSize(size_t size) = 0; + + // Returns max payload length. + // Does not account for RTP headers and FEC/ULP/RED overhead (when FEC is + // enabled). + virtual size_t MaxPayloadSize() const = 0; + + // Returns max RTP packet size. Takes into account RTP headers and + // FEC/ULP/RED overhead (when FEC is enabled). + virtual size_t MaxRtpPacketSize() const = 0; + + // Sets codec name and payload type. Returns -1 on failure else 0. + virtual int32_t RegisterSendPayload(const CodecInst& voice_codec) = 0; + + // Sets codec name and payload type. Return -1 on failure else 0. + virtual int32_t RegisterSendPayload(const VideoCodec& video_codec) = 0; + + virtual void RegisterVideoSendPayload(int payload_type, + const char* payload_name) = 0; + + // Unregisters a send payload. + // |payload_type| - payload type of codec + // Returns -1 on failure else 0. + virtual int32_t DeRegisterSendPayload(int8_t payload_type) = 0; + + // (De)registers RTP header extension type and id. + // Returns -1 on failure else 0. + virtual int32_t RegisterSendRtpHeaderExtension(RTPExtensionType type, + uint8_t id) = 0; + + virtual int32_t DeregisterSendRtpHeaderExtension(RTPExtensionType type) = 0; + + virtual bool HasBweExtensions() const = 0; + + // Returns start timestamp. + virtual uint32_t StartTimestamp() const = 0; + + // Sets start timestamp. Start timestamp is set to a random value if this + // function is never called. + virtual void SetStartTimestamp(uint32_t timestamp) = 0; + + // Returns SequenceNumber. + virtual uint16_t SequenceNumber() const = 0; + + // Sets SequenceNumber, default is a random number. + virtual void SetSequenceNumber(uint16_t seq) = 0; + + virtual void SetRtpState(const RtpState& rtp_state) = 0; + virtual void SetRtxState(const RtpState& rtp_state) = 0; + virtual RtpState GetRtpState() const = 0; + virtual RtpState GetRtxState() const = 0; + + // Returns SSRC. + virtual uint32_t SSRC() const = 0; + + // Sets SSRC, default is a random number. + virtual void SetSSRC(uint32_t ssrc) = 0; + + // Sets CSRC. + // |csrcs| - vector of CSRCs + virtual void SetCsrcs(const std::vector& csrcs) = 0; + + // Turns on/off sending RTX (RFC 4588). The modes can be set as a combination + // of values of the enumerator RtxMode. + virtual void SetRtxSendStatus(int modes) = 0; + + // Returns status of sending RTX (RFC 4588). The returned value can be + // a combination of values of the enumerator RtxMode. + virtual int RtxSendStatus() const = 0; + + // Sets the SSRC to use when sending RTX packets. This doesn't enable RTX, + // only the SSRC is set. + virtual void SetRtxSsrc(uint32_t ssrc) = 0; + + // Sets the payload type to use when sending RTX packets. Note that this + // doesn't enable RTX, only the payload type is set. + virtual void SetRtxSendPayloadType(int payload_type, + int associated_payload_type) = 0; + + // Returns the FlexFEC SSRC, if there is one. + virtual rtc::Optional FlexfecSsrc() const = 0; + + // Sets sending status. Sends kRtcpByeCode when going from true to false. + // Returns -1 on failure else 0. + virtual int32_t SetSendingStatus(bool sending) = 0; + + // Returns current sending status. + virtual bool Sending() const = 0; + + // Starts/Stops media packets. On by default. + virtual void SetSendingMediaStatus(bool sending) = 0; + + // Returns current media sending status. + virtual bool SendingMedia() const = 0; + + // Returns current bitrate in Kbit/s. + virtual void BitrateSent(uint32_t* total_rate, + uint32_t* video_rate, + uint32_t* fec_rate, + uint32_t* nack_rate) const = 0; + + // Used by the codec module to deliver a video or audio frame for + // packetization. + // |frame_type| - type of frame to send + // |payload_type| - payload type of frame to send + // |timestamp| - timestamp of frame to send + // |payload_data| - payload buffer of frame to send + // |payload_size| - size of payload buffer to send + // |fragmentation| - fragmentation offset data for fragmented frames such + // as layers or RED + // |transport_frame_id_out| - set to RTP timestamp. + // Returns true on success. + virtual bool SendOutgoingData(FrameType frame_type, + int8_t payload_type, + uint32_t timestamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_header, + uint32_t* transport_frame_id_out) = 0; + + virtual bool TimeToSendPacket(uint32_t ssrc, + uint16_t sequence_number, + int64_t capture_time_ms, + bool retransmission, + const PacedPacketInfo& pacing_info) = 0; + + virtual size_t TimeToSendPadding(size_t bytes, + const PacedPacketInfo& pacing_info) = 0; + + // Called on generation of new statistics after an RTP send. + virtual void RegisterSendChannelRtpStatisticsCallback( + StreamDataCountersCallback* callback) = 0; + virtual StreamDataCountersCallback* GetSendChannelRtpStatisticsCallback() + const = 0; + + // ************************************************************************** + // RTCP + // ************************************************************************** + + // Returns RTCP status. + virtual RtcpMode RTCP() const = 0; + + // Sets RTCP status i.e on(compound or non-compound)/off. + // |method| - RTCP method to use. + virtual void SetRTCPStatus(RtcpMode method) = 0; + + // Sets RTCP CName (i.e unique identifier). + // Returns -1 on failure else 0. + virtual int32_t SetCNAME(const char* cname) = 0; + + // Returns remote CName. + // Returns -1 on failure else 0. + virtual int32_t RemoteCNAME(uint32_t remote_ssrc, + char cname[RTCP_CNAME_SIZE]) const = 0; + + // Returns remote NTP. + // Returns -1 on failure else 0. + virtual int32_t RemoteNTP(uint32_t* received_ntp_secs, + uint32_t* received_ntp_frac, + uint32_t* rtcp_arrival_time_secs, + uint32_t* rtcp_arrival_time_frac, + uint32_t* rtcp_timestamp) const = 0; + + // Returns -1 on failure else 0. + virtual int32_t AddMixedCNAME(uint32_t ssrc, const char* cname) = 0; + + // Returns -1 on failure else 0. + virtual int32_t RemoveMixedCNAME(uint32_t ssrc) = 0; + + // Returns current RTT (round-trip time) estimate. + // Returns -1 on failure else 0. + virtual int32_t RTT(uint32_t remote_ssrc, + int64_t* rtt, + int64_t* avg_rtt, + int64_t* min_rtt, + int64_t* max_rtt) const = 0; + + // Forces a send of a RTCP packet. Periodic SR and RR are triggered via the + // process function. + // Returns -1 on failure else 0. + virtual int32_t SendRTCP(RTCPPacketType rtcp_packet_type) = 0; + + // Forces a send of a RTCP packet with more than one packet type. + // periodic SR and RR are triggered via the process function + // Returns -1 on failure else 0. + virtual int32_t SendCompoundRTCP( + const std::set& rtcp_packet_types) = 0; + + // Notifies the sender about good state of the RTP receiver. + virtual int32_t SendRTCPReferencePictureSelection(uint64_t picture_id) = 0; + + // Send a RTCP Slice Loss Indication (SLI). + // |picture_id| - 6 least significant bits of picture_id. + virtual int32_t SendRTCPSliceLossIndication(uint8_t picture_id) = 0; + + // Returns statistics of the amount of data sent. + // Returns -1 on failure else 0. + virtual int32_t DataCountersRTP(size_t* bytes_sent, + uint32_t* packets_sent) const = 0; + + // Returns send statistics for the RTP and RTX stream. + virtual void GetSendStreamDataCounters( + StreamDataCounters* rtp_counters, + StreamDataCounters* rtx_counters) const = 0; + + // Returns packet loss statistics for the RTP stream. + virtual void GetRtpPacketLossStats( + bool outgoing, + uint32_t ssrc, + struct RtpPacketLossStats* loss_stats) const = 0; + + // Returns received RTCP sender info. + // Returns -1 on failure else 0. + virtual int32_t RemoteRTCPStat(RTCPSenderInfo* sender_info) = 0; + + // Returns received RTCP report block. + // Returns -1 on failure else 0. + virtual int32_t RemoteRTCPStat( + std::vector* receive_blocks) const = 0; + + // (APP) Sets application specific data. + // Returns -1 on failure else 0. + virtual int32_t SetRTCPApplicationSpecificData(uint8_t sub_type, + uint32_t name, + const uint8_t* data, + uint16_t length) = 0; + // (XR) Sets VOIP metric. + // Returns -1 on failure else 0. + virtual int32_t SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) = 0; + + // (XR) Sets Receiver Reference Time Report (RTTR) status. + virtual void SetRtcpXrRrtrStatus(bool enable) = 0; + + // Returns current Receiver Reference Time Report (RTTR) status. + virtual bool RtcpXrRrtrStatus() const = 0; + + // (REMB) Receiver Estimated Max Bitrate. + virtual bool REMB() const = 0; + + virtual void SetREMBStatus(bool enable) = 0; + + virtual void SetREMBData(uint32_t bitrate, + const std::vector& ssrcs) = 0; + + // (TMMBR) Temporary Max Media Bit Rate + virtual bool TMMBR() const = 0; + + virtual void SetTMMBRStatus(bool enable) = 0; + + // (NACK) + + // TODO(holmer): Propagate this API to VideoEngine. + // Returns the currently configured selective retransmission settings. + virtual int SelectiveRetransmissions() const = 0; + + // TODO(holmer): Propagate this API to VideoEngine. + // Sets the selective retransmission settings, which will decide which + // packets will be retransmitted if NACKed. Settings are constructed by + // combining the constants in enum RetransmissionMode with bitwise OR. + // All packets are retransmitted if kRetransmitAllPackets is set, while no + // packets are retransmitted if kRetransmitOff is set. + // By default all packets except FEC packets are retransmitted. For VP8 + // with temporal scalability only base layer packets are retransmitted. + // Returns -1 on failure, otherwise 0. + virtual int SetSelectiveRetransmissions(uint8_t settings) = 0; + + // Sends a Negative acknowledgement packet. + // Returns -1 on failure else 0. + // TODO(philipel): Deprecate this and start using SendNack instead, mostly + // because we want a function that actually send NACK for the specified + // packets. + virtual int32_t SendNACK(const uint16_t* nack_list, uint16_t size) = 0; + + // Sends NACK for the packets specified. + // Note: This assumes the caller keeps track of timing and doesn't rely on + // the RTP module to do this. + virtual void SendNack(const std::vector& sequence_numbers) = 0; + + // Store the sent packets, needed to answer to a Negative acknowledgment + // requests. + virtual void SetStorePacketsStatus(bool enable, uint16_t numberToStore) = 0; + + // Returns true if the module is configured to store packets. + virtual bool StorePackets() const = 0; + + // Called on receipt of RTCP report block from remote side. + virtual void RegisterRtcpStatisticsCallback( + RtcpStatisticsCallback* callback) = 0; + virtual RtcpStatisticsCallback* GetRtcpStatisticsCallback() = 0; + // BWE feedback packets. + virtual bool SendFeedbackPacket(const rtcp::TransportFeedback& packet) = 0; + + virtual void SetVideoBitrateAllocation(const BitrateAllocation& bitrate) = 0; + + // ************************************************************************** + // Audio + // ************************************************************************** + + // This function is deprecated. It was previously used to determine when it + // was time to send a DTMF packet in silence (CNG). + // Returns -1 on failure else 0. + RTC_DEPRECATED virtual int32_t SetAudioPacketSize( + uint16_t packet_size_samples) = 0; + + // Sends a TelephoneEvent tone using RFC 2833 (4733). + // Returns -1 on failure else 0. + virtual int32_t SendTelephoneEventOutband(uint8_t key, + uint16_t time_ms, + uint8_t level) = 0; + + // Store the audio level in dBov for header-extension-for-audio-level- + // indication. + // This API shall be called before transmision of an RTP packet to ensure + // that the |level| part of the extended RTP header is updated. + // return -1 on failure else 0. + virtual int32_t SetAudioLevel(uint8_t level_dbov) = 0; + + // ************************************************************************** + // Video + // ************************************************************************** + + // Set RED and ULPFEC payload types. A payload type of -1 means that the + // corresponding feature is turned off. Note that we DO NOT support enabling + // ULPFEC without enabling RED. However, we DO support enabling RED without + // enabling ULPFEC. This is due to an RED/RTX workaround, where the receiver + // assumes that RTX packets carry RED if RED has been configured in the SDP, + // regardless of what RTX payload type mapping was negotiated in the SDP. + // TODO(brandtr): Update this comment when we have removed the RED/RTX + // send-side workaround, i.e., when we do not support enabling RED without + // enabling ULPFEC. + virtual void SetUlpfecConfig(int red_payload_type, + int ulpfec_payload_type) = 0; + + // Set FEC rates, max frames before FEC is sent, and type of FEC masks. + // Returns false on failure. + virtual bool SetFecParameters(const FecProtectionParams& delta_params, + const FecProtectionParams& key_params) = 0; + + // Deprecated version of member function above. + RTC_DEPRECATED + int32_t SetFecParameters(const FecProtectionParams* delta_params, + const FecProtectionParams* key_params); + + // Set method for requestion a new key frame. + // Returns -1 on failure else 0. + virtual int32_t SetKeyFrameRequestMethod(KeyFrameRequestMethod method) = 0; + + // Sends a request for a keyframe. + // Returns -1 on failure else 0. + virtual int32_t RequestKeyFrame() = 0; }; + } // namespace webrtc + #endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_H_ diff --git a/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 282483b..a489018 100644 --- a/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/include/webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -13,7 +13,9 @@ #include #include +#include +#include "webrtc/common_types.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/clock.h" #include "webrtc/typedefs.h" @@ -21,7 +23,6 @@ #define RTCP_CNAME_SIZE 256 // RFC 3550 page 44, including null termination #define IP_PACKET_SIZE 1500 // we assume ethernet #define MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS 10 -#define TIMEOUT_SEI_MESSAGES_MS 30000 // in milliseconds namespace webrtc { namespace rtcp { @@ -29,6 +30,10 @@ class TransportFeedback; } const int kVideoPayloadTypeFrequency = 90000; +// TODO(solenberg): RTP time stamp rate for RTCP is fixed at 8k, this is legacy +// and should be fixed. +// See: https://bugs.chromium.org/p/webrtc/issues/detail?id=6458 +const int kBogusRtpRateForAudioRtcp = 8000; // Minimum RTP header size in bytes. const uint8_t kRtpHeaderSize = 12; @@ -40,7 +45,9 @@ struct AudioPayload { }; struct VideoPayload { - RtpVideoCodecTypes videoCodecType; + RtpVideoCodecTypes videoCodecType; + // The H264 profile only matters if videoCodecType == kRtpVideoH264. + H264::Profile h264_profile; }; union PayloadUnion { @@ -67,6 +74,8 @@ enum RTPExtensionType { kRtpExtensionAbsoluteSendTime, kRtpExtensionVideoRotation, kRtpExtensionTransportSequenceNumber, + kRtpExtensionPlayoutDelay, + kRtpExtensionNumberOfExtensions, }; enum RTCPAppSubTypes { kAppSubtypeBwe = 0x00 }; @@ -93,6 +102,7 @@ enum RTCPPacketType : uint32_t { kRtcpXrReceiverReferenceTime = 0x40000, kRtcpXrDlrrReportBlock = 0x80000, kRtcpTransportFeedback = 0x100000, + kRtcpXrTargetBitrate = 0x200000 }; enum KeyFrameRequestMethod { kKeyFrameReqPliRtcp, kKeyFrameReqFirRtcp }; @@ -158,13 +168,6 @@ struct RTCPReportBlock { uint32_t delaySinceLastSR; }; -struct RtcpReceiveTimeInfo { - // Fields as described by RFC 3611 4.5. - uint32_t sourceSSRC; - uint32_t lastRR; - uint32_t delaySinceLastRR; -}; - typedef std::list ReportBlockList; struct RtpState { @@ -187,9 +190,9 @@ class RtpData { public: virtual ~RtpData() {} - virtual int32_t OnReceivedPayloadData(const uint8_t* payloadData, - const size_t payloadSize, - const WebRtcRTPHeader* rtpHeader) = 0; + virtual int32_t OnReceivedPayloadData(const uint8_t* payload_data, + size_t payload_size, + const WebRtcRTPHeader* rtp_header) = 0; virtual bool OnRecoveredPacket(const uint8_t* packet, size_t packet_length) = 0; @@ -204,15 +207,15 @@ class RtpFeedback { * channels - number of channels in codec (1 = mono, 2 = stereo) */ virtual int32_t OnInitializeDecoder( - const int8_t payloadType, - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int frequency, - const size_t channels, - const uint32_t rate) = 0; + int8_t payload_type, + const char payload_name[RTP_PAYLOAD_NAME_SIZE], + int frequency, + size_t channels, + uint32_t rate) = 0; - virtual void OnIncomingSSRCChanged(const uint32_t ssrc) = 0; + virtual void OnIncomingSSRCChanged(uint32_t ssrc) = 0; - virtual void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) = 0; + virtual void OnIncomingCSRCChanged(uint32_t csrc, bool added) = 0; }; class RtcpIntraFrameObserver { @@ -225,8 +228,6 @@ class RtcpIntraFrameObserver { virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) = 0; - virtual void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) = 0; - virtual ~RtcpIntraFrameObserver() {} }; @@ -245,32 +246,51 @@ class RtcpBandwidthObserver { struct PacketInfo { PacketInfo(int64_t arrival_time_ms, uint16_t sequence_number) - : PacketInfo(-1, arrival_time_ms, -1, sequence_number, 0, false) {} + : PacketInfo(-1, + arrival_time_ms, + -1, + sequence_number, + 0, + PacedPacketInfo()) {} PacketInfo(int64_t arrival_time_ms, int64_t send_time_ms, uint16_t sequence_number, size_t payload_size, - bool was_paced) + const PacedPacketInfo& pacing_info) : PacketInfo(-1, arrival_time_ms, send_time_ms, sequence_number, payload_size, - was_paced) {} + pacing_info) {} PacketInfo(int64_t creation_time_ms, int64_t arrival_time_ms, int64_t send_time_ms, uint16_t sequence_number, size_t payload_size, - bool was_paced) + const PacedPacketInfo& pacing_info) : creation_time_ms(creation_time_ms), arrival_time_ms(arrival_time_ms), send_time_ms(send_time_ms), sequence_number(sequence_number), payload_size(payload_size), - was_paced(was_paced) {} + pacing_info(pacing_info) {} + + static constexpr int kNotAProbe = -1; + + // NOTE! The variable |creation_time_ms| is not used when testing equality. + // This is due to |creation_time_ms| only being used by SendTimeHistory + // for book-keeping, and is of no interest outside that class. + // TODO(philipel): Remove |creation_time_ms| from PacketInfo when cleaning up + // SendTimeHistory. + bool operator==(const PacketInfo& rhs) const { + return arrival_time_ms == rhs.arrival_time_ms && + send_time_ms == rhs.send_time_ms && + sequence_number == rhs.sequence_number && + payload_size == rhs.payload_size && pacing_info == rhs.pacing_info; + } // Time corresponding to when this object was created. int64_t creation_time_ms; @@ -285,8 +305,8 @@ struct PacketInfo { uint16_t sequence_number; // Size of the packet excluding RTP headers. size_t payload_size; - // True if the packet was paced out by the pacer. - bool was_paced; + // Pacing information about this packet. + PacedPacketInfo pacing_info; }; class TransportFeedbackObserver { @@ -294,13 +314,14 @@ class TransportFeedbackObserver { TransportFeedbackObserver() {} virtual ~TransportFeedbackObserver() {} - // Note: Transport-wide sequence number as sequence number. Arrival time - // must be set to 0. + // Note: Transport-wide sequence number as sequence number. virtual void AddPacket(uint16_t sequence_number, size_t length, - bool was_paced) = 0; + const PacedPacketInfo& pacing_info) = 0; virtual void OnTransportFeedback(const rtcp::TransportFeedback& feedback) = 0; + + virtual std::vector GetTransportFeedbackVector() const = 0; }; class RtcpRttStats { @@ -317,16 +338,16 @@ class NullRtpFeedback : public RtpFeedback { public: virtual ~NullRtpFeedback() {} - int32_t OnInitializeDecoder(const int8_t payloadType, + int32_t OnInitializeDecoder(int8_t payload_type, const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int frequency, - const size_t channels, - const uint32_t rate) override { + int frequency, + size_t channels, + uint32_t rate) override { return 0; } - void OnIncomingSSRCChanged(const uint32_t ssrc) override {} - void OnIncomingCSRCChanged(const uint32_t CSRC, const bool added) override {} + void OnIncomingSSRCChanged(uint32_t ssrc) override {} + void OnIncomingCSRCChanged(uint32_t csrc, bool added) override {} }; // Null object version of RtpData. @@ -334,9 +355,9 @@ class NullRtpData : public RtpData { public: virtual ~NullRtpData() {} - int32_t OnReceivedPayloadData(const uint8_t* payloadData, - const size_t payloadSize, - const WebRtcRTPHeader* rtpHeader) override { + int32_t OnReceivedPayloadData(const uint8_t* payload_data, + size_t payload_size, + const WebRtcRTPHeader* rtp_header) override { return 0; } diff --git a/include/webrtc/modules/rtp_rtcp/include/fec_receiver.h b/include/webrtc/modules/rtp_rtcp/include/ulpfec_receiver.h similarity index 59% rename from include/webrtc/modules/rtp_rtcp/include/fec_receiver.h rename to include/webrtc/modules/rtp_rtcp/include/ulpfec_receiver.h index 65e85ad..af416f9 100644 --- a/include/webrtc/modules/rtp_rtcp/include/fec_receiver.h +++ b/include/webrtc/modules/rtp_rtcp/include/ulpfec_receiver.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ -#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_ULPFEC_RECEIVER_H_ +#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_ULPFEC_RECEIVER_H_ #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" @@ -20,27 +20,37 @@ struct FecPacketCounter { FecPacketCounter() : num_packets(0), num_fec_packets(0), - num_recovered_packets(0) {} + num_recovered_packets(0), + first_packet_time_ms(-1) {} size_t num_packets; // Number of received packets. size_t num_fec_packets; // Number of received FEC packets. size_t num_recovered_packets; // Number of recovered media packets using FEC. + int64_t first_packet_time_ms; // Time when first packet is received. }; -class FecReceiver { +class UlpfecReceiver { public: - static FecReceiver* Create(RtpData* callback); + static UlpfecReceiver* Create(RtpData* callback); - virtual ~FecReceiver() {} + virtual ~UlpfecReceiver() {} + // Takes a RED packet, strips the RED header, and adds the resulting + // "virtual" RTP packet(s) into the internal buffer. + // + // TODO(brandtr): Set |ulpfec_payload_type| during constructor call, + // rather than as a parameter here. virtual int32_t AddReceivedRedPacket(const RTPHeader& rtp_header, const uint8_t* incoming_rtp_packet, size_t packet_length, uint8_t ulpfec_payload_type) = 0; + // Sends the received packets to the FEC and returns all packets + // (both original media and recovered) through the callback. virtual int32_t ProcessReceivedFec() = 0; + // Returns a counter describing the added and recovered packets. virtual FecPacketCounter GetPacketCounter() const = 0; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_FEC_RECEIVER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_INCLUDE_ULPFEC_RECEIVER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h b/include/webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h new file mode 100644 index 0000000..fcc637b --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RECOVERED_PACKET_RECEIVER_H_ +#define WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RECOVERED_PACKET_RECEIVER_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRecoveredPacketReceiver : public RecoveredPacketReceiver { + public: + MOCK_METHOD2(OnRecoveredPacket, bool(const uint8_t* packet, size_t length)); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RECOVERED_PACKET_RECEIVER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h b/include/webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h new file mode 100644 index 0000000..5f2fae9 --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTCP_RTT_STATS_H_ +#define WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTCP_RTT_STATS_H_ + +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockRtcpRttStats : public RtcpRttStats { + public: + MOCK_METHOD1(OnRttUpdate, void(int64_t rtt)); + MOCK_CONST_METHOD0(LastProcessedRtt, int64_t()); +}; +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_MOCKS_MOCK_RTCP_RTT_STATS_H_ diff --git a/include/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/include/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index bf5e936..cc7058a 100644 --- a/include/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/include/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -15,21 +15,21 @@ #include #include -#include "testing/gmock/include/gmock/gmock.h" - +#include "webrtc/base/optional.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" +#include "webrtc/test/gmock.h" namespace webrtc { class MockRtpData : public RtpData { public: MOCK_METHOD3(OnReceivedPayloadData, - int32_t(const uint8_t* payloadData, - const size_t payloadSize, - const WebRtcRTPHeader* rtpHeader)); + int32_t(const uint8_t* payload_data, + size_t payload_size, + const WebRtcRTPHeader* rtp_header)); MOCK_METHOD2(OnRecoveredPacket, bool(const uint8_t* packet, size_t packet_length)); @@ -37,224 +37,174 @@ class MockRtpData : public RtpData { class MockRtpRtcp : public RtpRtcp { public: - MOCK_METHOD1(RegisterDefaultModule, - int32_t(RtpRtcp* module)); - MOCK_METHOD0(DeRegisterDefaultModule, - int32_t()); - MOCK_METHOD0(DefaultModuleRegistered, - bool()); - MOCK_METHOD0(NumberChildModules, - uint32_t()); - MOCK_METHOD1(RegisterSyncModule, - int32_t(RtpRtcp* module)); - MOCK_METHOD0(DeRegisterSyncModule, - int32_t()); + MOCK_METHOD1(RegisterDefaultModule, int32_t(RtpRtcp* module)); + MOCK_METHOD0(DeRegisterDefaultModule, int32_t()); + MOCK_METHOD0(DefaultModuleRegistered, bool()); + MOCK_METHOD0(NumberChildModules, uint32_t()); + MOCK_METHOD1(RegisterSyncModule, int32_t(RtpRtcp* module)); + MOCK_METHOD0(DeRegisterSyncModule, int32_t()); MOCK_METHOD2(IncomingRtcpPacket, - int32_t(const uint8_t* incomingPacket, size_t packetLength)); - MOCK_METHOD1(SetRemoteSSRC, void(const uint32_t ssrc)); + int32_t(const uint8_t* incoming_packet, size_t packet_length)); + MOCK_METHOD1(SetRemoteSSRC, void(uint32_t ssrc)); MOCK_METHOD4(IncomingAudioNTP, - int32_t(const uint32_t audioReceivedNTPsecs, - const uint32_t audioReceivedNTPfrac, - const uint32_t audioRTCPArrivalTimeSecs, - const uint32_t audioRTCPArrivalTimeFrac)); - MOCK_METHOD0(InitSender, - int32_t()); - MOCK_METHOD1(RegisterSendTransport, - int32_t(Transport* outgoingTransport)); - MOCK_METHOD1(SetMaxTransferUnit, - int32_t(const uint16_t size)); - MOCK_METHOD3(SetTransportOverhead, - int32_t(const bool TCP, const bool IPV6, - const uint8_t authenticationOverhead)); - MOCK_CONST_METHOD0(MaxPayloadLength, - uint16_t()); - MOCK_CONST_METHOD0(MaxDataPayloadLength, - uint16_t()); - MOCK_METHOD1(RegisterSendPayload, - int32_t(const CodecInst& voiceCodec)); - MOCK_METHOD1(RegisterSendPayload, - int32_t(const VideoCodec& videoCodec)); + int32_t(uint32_t audio_received_ntp_secs, + uint32_t audio_received_ntp_frac, + uint32_t audio_rtcp_arrival_time_secs, + uint32_t audio_rtcp_arrival_time_frac)); + MOCK_METHOD0(InitSender, int32_t()); + MOCK_METHOD1(RegisterSendTransport, int32_t(Transport* outgoing_transport)); + MOCK_METHOD1(SetMaxRtpPacketSize, void(size_t size)); + MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet)); + MOCK_CONST_METHOD0(MaxPayloadSize, size_t()); + MOCK_CONST_METHOD0(MaxRtpPacketSize, size_t()); + MOCK_METHOD1(RegisterSendPayload, int32_t(const CodecInst& voice_codec)); + MOCK_METHOD1(RegisterSendPayload, int32_t(const VideoCodec& video_codec)); MOCK_METHOD2(RegisterVideoSendPayload, void(int payload_type, const char* payload_name)); - MOCK_METHOD1(DeRegisterSendPayload, - int32_t(const int8_t payloadType)); + MOCK_METHOD1(DeRegisterSendPayload, int32_t(int8_t payload_type)); MOCK_METHOD2(RegisterSendRtpHeaderExtension, - int32_t(const RTPExtensionType type, const uint8_t id)); + int32_t(RTPExtensionType type, uint8_t id)); MOCK_METHOD1(DeregisterSendRtpHeaderExtension, - int32_t(const RTPExtensionType type)); - MOCK_CONST_METHOD0(StartTimestamp, - uint32_t()); - MOCK_METHOD1(SetStartTimestamp, void(const uint32_t timestamp)); + int32_t(RTPExtensionType type)); + MOCK_CONST_METHOD0(HasBweExtensions, bool()); + MOCK_CONST_METHOD0(StartTimestamp, uint32_t()); + MOCK_METHOD1(SetStartTimestamp, void(uint32_t timestamp)); MOCK_CONST_METHOD0(SequenceNumber, uint16_t()); - MOCK_METHOD1(SetSequenceNumber, void(const uint16_t seq)); + MOCK_METHOD1(SetSequenceNumber, void(uint16_t seq)); MOCK_METHOD1(SetRtpState, void(const RtpState& rtp_state)); MOCK_METHOD1(SetRtxState, void(const RtpState& rtp_state)); MOCK_CONST_METHOD0(GetRtpState, RtpState()); MOCK_CONST_METHOD0(GetRtxState, RtpState()); - MOCK_CONST_METHOD0(SSRC, - uint32_t()); - MOCK_METHOD1(SetSSRC, - void(const uint32_t ssrc)); - MOCK_CONST_METHOD1(CSRCs, - int32_t(uint32_t arrOfCSRC[kRtpCsrcSize])); + MOCK_CONST_METHOD0(SSRC, uint32_t()); + MOCK_METHOD1(SetSSRC, void(uint32_t ssrc)); + MOCK_CONST_METHOD1(CSRCs, int32_t(uint32_t csrcs[kRtpCsrcSize])); MOCK_METHOD1(SetCsrcs, void(const std::vector& csrcs)); - MOCK_METHOD1(SetCSRCStatus, - int32_t(const bool include)); + MOCK_METHOD1(SetCSRCStatus, int32_t(bool include)); MOCK_METHOD1(SetRtxSendStatus, void(int modes)); MOCK_CONST_METHOD0(RtxSendStatus, int()); - MOCK_METHOD1(SetRtxSsrc, - void(uint32_t)); + MOCK_METHOD1(SetRtxSsrc, void(uint32_t)); MOCK_METHOD2(SetRtxSendPayloadType, void(int, int)); + MOCK_CONST_METHOD0(FlexfecSsrc, rtc::Optional()); MOCK_CONST_METHOD0(RtxSendPayloadType, std::pair()); - MOCK_METHOD1(SetSendingStatus, - int32_t(const bool sending)); - MOCK_CONST_METHOD0(Sending, - bool()); - MOCK_METHOD1(SetSendingMediaStatus, void(const bool sending)); - MOCK_CONST_METHOD0(SendingMedia, - bool()); + MOCK_METHOD1(SetSendingStatus, int32_t(bool sending)); + MOCK_CONST_METHOD0(Sending, bool()); + MOCK_METHOD1(SetSendingMediaStatus, void(bool sending)); + MOCK_CONST_METHOD0(SendingMedia, bool()); MOCK_CONST_METHOD4(BitrateSent, - void(uint32_t* totalRate, - uint32_t* videoRate, - uint32_t* fecRate, - uint32_t* nackRate)); + void(uint32_t* total_rate, + uint32_t* video_rate, + uint32_t* fec_rate, + uint32_t* nack_rate)); MOCK_METHOD1(RegisterVideoBitrateObserver, void(BitrateStatisticsObserver*)); MOCK_CONST_METHOD0(GetVideoBitrateObserver, BitrateStatisticsObserver*(void)); MOCK_CONST_METHOD1(EstimatedReceiveBandwidth, - int(uint32_t* available_bandwidth)); - MOCK_METHOD8(SendOutgoingData, - int32_t(const FrameType frameType, - const int8_t payloadType, - const uint32_t timeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const size_t payloadSize, - const RTPFragmentationHeader* fragmentation, - const RTPVideoHeader* rtpVideoHdr)); - MOCK_METHOD4(TimeToSendPacket, - bool(uint32_t ssrc, uint16_t sequence_number, int64_t capture_time_ms, - bool retransmission)); - MOCK_METHOD1(TimeToSendPadding, - size_t(size_t bytes)); + int(uint32_t* available_bandwidth)); + MOCK_METHOD9(SendOutgoingData, + bool(FrameType frame_type, + int8_t payload_type, + uint32_t timestamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_header, + uint32_t* frame_id_out)); + MOCK_METHOD5(TimeToSendPacket, + bool(uint32_t ssrc, + uint16_t sequence_number, + int64_t capture_time_ms, + bool retransmission, + const PacedPacketInfo& pacing_info)); + MOCK_METHOD2(TimeToSendPadding, + size_t(size_t bytes, const PacedPacketInfo& pacing_info)); MOCK_METHOD2(RegisterRtcpObservers, - void(RtcpIntraFrameObserver* intraFrameCallback, - RtcpBandwidthObserver* bandwidthCallback)); + void(RtcpIntraFrameObserver* intra_frame_callback, + RtcpBandwidthObserver* bandwidth_callback)); MOCK_CONST_METHOD0(RTCP, RtcpMode()); - MOCK_METHOD1(SetRTCPStatus, void(const RtcpMode method)); - MOCK_METHOD1(SetCNAME, - int32_t(const char cName[RTCP_CNAME_SIZE])); + MOCK_METHOD1(SetRTCPStatus, void(RtcpMode method)); + MOCK_METHOD1(SetCNAME, int32_t(const char cname[RTCP_CNAME_SIZE])); MOCK_CONST_METHOD2(RemoteCNAME, - int32_t(const uint32_t remoteSSRC, - char cName[RTCP_CNAME_SIZE])); + int32_t(uint32_t remote_ssrc, + char cname[RTCP_CNAME_SIZE])); MOCK_CONST_METHOD5(RemoteNTP, - int32_t(uint32_t *ReceivedNTPsecs, - uint32_t *ReceivedNTPfrac, - uint32_t *RTCPArrivalTimeSecs, - uint32_t *RTCPArrivalTimeFrac, - uint32_t *rtcp_timestamp)); + int32_t(uint32_t* received_ntp_secs, + uint32_t* received_ntp_frac, + uint32_t* rtcp_arrival_time_secs, + uint32_t* rtcp_arrival_time_frac, + uint32_t* rtcp_timestamp)); MOCK_METHOD2(AddMixedCNAME, - int32_t(const uint32_t SSRC, - const char cName[RTCP_CNAME_SIZE])); - MOCK_METHOD1(RemoveMixedCNAME, - int32_t(const uint32_t SSRC)); + int32_t(uint32_t ssrc, const char cname[RTCP_CNAME_SIZE])); + MOCK_METHOD1(RemoveMixedCNAME, int32_t(uint32_t ssrc)); MOCK_CONST_METHOD5(RTT, - int32_t(const uint32_t remoteSSRC, - int64_t* RTT, - int64_t* avgRTT, - int64_t* minRTT, - int64_t* maxRTT)); - MOCK_METHOD1(SendRTCP, int32_t(RTCPPacketType packetType)); + int32_t(uint32_t remote_ssrc, + int64_t* rtt, + int64_t* avg_rtt, + int64_t* min_rtt, + int64_t* max_rtt)); + MOCK_METHOD1(SendRTCP, int32_t(RTCPPacketType packet_type)); MOCK_METHOD1(SendCompoundRTCP, - int32_t(const std::set& packetTypes)); - MOCK_METHOD1(SendRTCPReferencePictureSelection, - int32_t(const uint64_t pictureID)); - MOCK_METHOD1(SendRTCPSliceLossIndication, - int32_t(const uint8_t pictureID)); + int32_t(const std::set& packet_types)); + MOCK_METHOD1(SendRTCPReferencePictureSelection, int32_t(uint64_t picture_id)); + MOCK_METHOD1(SendRTCPSliceLossIndication, int32_t(uint8_t picture_id)); MOCK_CONST_METHOD2(DataCountersRTP, - int32_t(size_t *bytesSent, uint32_t *packetsSent)); + int32_t(size_t* bytes_sent, uint32_t* packets_sent)); MOCK_CONST_METHOD2(GetSendStreamDataCounters, - void(StreamDataCounters*, StreamDataCounters*)); + void(StreamDataCounters*, StreamDataCounters*)); MOCK_CONST_METHOD3(GetRtpPacketLossStats, - void(bool, uint32_t, struct RtpPacketLossStats*)); - MOCK_METHOD1(RemoteRTCPStat, - int32_t(RTCPSenderInfo* senderInfo)); + void(bool, uint32_t, struct RtpPacketLossStats*)); + MOCK_METHOD1(RemoteRTCPStat, int32_t(RTCPSenderInfo* sender_info)); MOCK_CONST_METHOD1(RemoteRTCPStat, - int32_t(std::vector* receiveBlocks)); + int32_t(std::vector* receive_blocks)); MOCK_METHOD4(SetRTCPApplicationSpecificData, - int32_t(const uint8_t subType, - const uint32_t name, + int32_t(uint8_t sub_type, + uint32_t name, const uint8_t* data, - const uint16_t length)); - MOCK_METHOD1(SetRTCPVoIPMetrics, - int32_t(const RTCPVoIPMetric* VoIPMetric)); - MOCK_METHOD1(SetRtcpXrRrtrStatus, - void(bool enable)); - MOCK_CONST_METHOD0(RtcpXrRrtrStatus, - bool()); - MOCK_CONST_METHOD0(REMB, - bool()); - MOCK_METHOD1(SetREMBStatus, void(const bool enable)); + uint16_t length)); + MOCK_METHOD1(SetRTCPVoIPMetrics, int32_t(const RTCPVoIPMetric* voip_metric)); + MOCK_METHOD1(SetRtcpXrRrtrStatus, void(bool enable)); + MOCK_CONST_METHOD0(RtcpXrRrtrStatus, bool()); + MOCK_CONST_METHOD0(REMB, bool()); + MOCK_METHOD1(SetREMBStatus, void(bool enable)); MOCK_METHOD2(SetREMBData, - void(const uint32_t bitrate, - const std::vector& ssrcs)); - MOCK_CONST_METHOD0(TMMBR, - bool()); - MOCK_METHOD1(SetTMMBRStatus, void(const bool enable)); - MOCK_METHOD1(OnBandwidthEstimateUpdate, - void(uint16_t bandWidthKbit)); - MOCK_CONST_METHOD0(SelectiveRetransmissions, - int()); - MOCK_METHOD1(SetSelectiveRetransmissions, - int(uint8_t settings)); - MOCK_METHOD2(SendNACK, - int32_t(const uint16_t* nackList, const uint16_t size)); + void(uint32_t bitrate, const std::vector& ssrcs)); + MOCK_CONST_METHOD0(TMMBR, bool()); + MOCK_METHOD1(SetTMMBRStatus, void(bool enable)); + MOCK_METHOD1(OnBandwidthEstimateUpdate, void(uint16_t bandwidth_kbit)); + MOCK_CONST_METHOD0(SelectiveRetransmissions, int()); + MOCK_METHOD1(SetSelectiveRetransmissions, int(uint8_t settings)); + MOCK_METHOD2(SendNACK, int32_t(const uint16_t* nack_list, uint16_t size)); MOCK_METHOD1(SendNack, void(const std::vector& sequence_numbers)); MOCK_METHOD2(SetStorePacketsStatus, - void(const bool enable, const uint16_t numberToStore)); + void(bool enable, uint16_t number_to_store)); MOCK_CONST_METHOD0(StorePackets, bool()); MOCK_METHOD1(RegisterRtcpStatisticsCallback, void(RtcpStatisticsCallback*)); MOCK_METHOD0(GetRtcpStatisticsCallback, RtcpStatisticsCallback*()); MOCK_METHOD1(SendFeedbackPacket, bool(const rtcp::TransportFeedback& packet)); - MOCK_METHOD1(SetAudioPacketSize, - int32_t(const uint16_t packetSizeSamples)); + MOCK_METHOD1(SetAudioPacketSize, int32_t(uint16_t packet_size_samples)); MOCK_METHOD3(SendTelephoneEventOutband, - int32_t(const uint8_t key, const uint16_t time_ms, const uint8_t level)); - MOCK_METHOD1(SetSendREDPayloadType, - int32_t(const int8_t payloadType)); - MOCK_CONST_METHOD1(SendREDPayloadType, int32_t(int8_t* payloadType)); + int32_t(uint8_t key, uint16_t time_ms, uint8_t level)); + MOCK_METHOD1(SetSendREDPayloadType, int32_t(int8_t payload_type)); + MOCK_CONST_METHOD1(SendREDPayloadType, int32_t(int8_t* payload_type)); MOCK_METHOD2(SetRTPAudioLevelIndicationStatus, - int32_t(const bool enable, const uint8_t ID)); - MOCK_METHOD1(SetAudioLevel, - int32_t(const uint8_t level_dBov)); - MOCK_METHOD1(SetTargetSendBitrate, - void(uint32_t bitrate_bps)); - MOCK_METHOD3(SetGenericFECStatus, - void(const bool enable, - const uint8_t payload_type_red, - const uint8_t payload_type_fec)); - MOCK_METHOD3(GenericFECStatus, - void(bool* enable, - uint8_t* payloadTypeRED, - uint8_t* payloadTypeFEC)); + int32_t(bool enable, uint8_t id)); + MOCK_METHOD1(SetAudioLevel, int32_t(uint8_t level_dbov)); + MOCK_METHOD1(SetTargetSendBitrate, void(uint32_t bitrate_bps)); + MOCK_METHOD2(SetUlpfecConfig, + void(int red_payload_type, int fec_payload_type)); MOCK_METHOD2(SetFecParameters, - int32_t(const FecProtectionParams* delta_params, - const FecProtectionParams* key_params)); - MOCK_METHOD1(SetKeyFrameRequestMethod, - int32_t(const KeyFrameRequestMethod method)); - MOCK_METHOD0(RequestKeyFrame, - int32_t()); - MOCK_METHOD0(TimeUntilNextProcess, - int64_t()); - MOCK_METHOD0(Process, - void()); - MOCK_METHOD1(RegisterSendFrameCountObserver, - void(FrameCountObserver*)); - MOCK_CONST_METHOD0(GetSendFrameCountObserver, - FrameCountObserver*(void)); + bool(const FecProtectionParams& delta_params, + const FecProtectionParams& key_params)); + MOCK_METHOD1(SetKeyFrameRequestMethod, int32_t(KeyFrameRequestMethod method)); + MOCK_METHOD0(RequestKeyFrame, int32_t()); + MOCK_METHOD0(TimeUntilNextProcess, int64_t()); + MOCK_METHOD0(Process, void()); + MOCK_METHOD1(RegisterSendFrameCountObserver, void(FrameCountObserver*)); + MOCK_CONST_METHOD0(GetSendFrameCountObserver, FrameCountObserver*(void)); MOCK_METHOD1(RegisterSendChannelRtpStatisticsCallback, - void(StreamDataCountersCallback*)); + void(StreamDataCountersCallback*)); MOCK_CONST_METHOD0(GetSendChannelRtpStatisticsCallback, - StreamDataCountersCallback*(void)); + StreamDataCountersCallback*(void)); + MOCK_METHOD1(SetVideoBitrateAllocation, void(const BitrateAllocation&)); // Members. unsigned int remote_ssrc_; }; diff --git a/include/webrtc/modules/rtp_rtcp/source/bitrate.h b/include/webrtc/modules/rtp_rtcp/source/bitrate.h deleted file mode 100644 index 7aaaead..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/bitrate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_ - -#include - -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/common_types.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class Clock; - -class Bitrate { - public: - class Observer; - Bitrate(Clock* clock, Observer* observer); - virtual ~Bitrate(); - - // Calculates rates. - void Process(); - - // Update with a packet. - void Update(const size_t bytes); - - // Packet rate last second, updated roughly every 100 ms. - uint32_t PacketRate() const; - - // Bitrate last second, updated roughly every 100 ms. - uint32_t BitrateLast() const; - - // Bitrate last second, updated now. - uint32_t BitrateNow() const; - - int64_t time_last_rate_update() const; - - class Observer { - public: - Observer() {} - virtual ~Observer() {} - - virtual void BitrateUpdated(const BitrateStatistics& stats) = 0; - }; - - protected: - Clock* clock_; - - private: - rtc::CriticalSection crit_; - uint32_t packet_rate_; - uint32_t bitrate_; - uint8_t bitrate_next_idx_; - int64_t packet_rate_array_[10]; - int64_t bitrate_array_[10]; - int64_t bitrate_diff_ms_[10]; - int64_t time_last_rate_update_; - size_t bytes_count_; - uint32_t packet_count_; - Observer* const observer_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/dtmf_queue.h b/include/webrtc/modules/rtp_rtcp/source/dtmf_queue.h index c0e616f..af546dc 100644 --- a/include/webrtc/modules/rtp_rtcp/source/dtmf_queue.h +++ b/include/webrtc/modules/rtp_rtcp/source/dtmf_queue.h @@ -11,27 +11,30 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_DTMF_QUEUE_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_DTMF_QUEUE_H_ +#include + #include "webrtc/base/criticalsection.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" -#include "webrtc/typedefs.h" namespace webrtc { -class DTMFqueue { +class DtmfQueue { public: - DTMFqueue(); - virtual ~DTMFqueue(); + struct Event { + uint16_t duration_ms = 0; + uint8_t payload_type = 0; + uint8_t key = 0; + uint8_t level = 0; + }; + + DtmfQueue(); + ~DtmfQueue(); - int32_t AddDTMF(uint8_t dtmf_key, uint16_t len, uint8_t level); - int8_t NextDTMF(uint8_t* dtmf_key, uint16_t* len, uint8_t* level); - bool PendingDTMF(); - void ResetDTMF(); + bool AddDtmf(const Event& event); + bool NextDtmf(Event* event); + bool PendingDtmf() const; private: rtc::CriticalSection dtmf_critsect_; - uint8_t next_empty_index_; - uint8_t dtmf_key_[DTMF_OUTBAND_MAX]; - uint16_t dtmf_length[DTMF_OUTBAND_MAX]; - uint8_t dtmf_level_[DTMF_OUTBAND_MAX]; + std::list queue_; }; } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/fec_test_helper.h b/include/webrtc/modules/rtp_rtcp/source/fec_test_helper.h index 6af7f9c..50594ec 100644 --- a/include/webrtc/modules/rtp_rtcp/source/fec_test_helper.h +++ b/include/webrtc/modules/rtp_rtcp/source/fec_test_helper.h @@ -11,50 +11,124 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ +#include + +#include "webrtc/base/basictypes.h" +#include "webrtc/base/random.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" namespace webrtc { namespace test { -struct RawRtpPacket : public ForwardErrorCorrection::Packet { +namespace fec { + +struct AugmentedPacket : public ForwardErrorCorrection::Packet { WebRtcRTPHeader header; }; -} // namespace test -const uint8_t kFecPayloadType = 96; -const uint8_t kRedPayloadType = 97; -const uint8_t kVp8PayloadType = 120; +// TODO(brandtr): Consider merging MediaPacketGenerator and +// AugmentedPacketGenerator into a single class, since their functionality is +// similar. -class FrameGenerator { +// This class generates media packets corresponding to a single frame. +class MediaPacketGenerator { public: - FrameGenerator(); + MediaPacketGenerator(uint32_t min_packet_size, + uint32_t max_packet_size, + uint32_t ssrc, + Random* random) + : min_packet_size_(min_packet_size), + max_packet_size_(max_packet_size), + ssrc_(ssrc), + random_(random) {} - void NewFrame(int num_packets); + // Construct the media packets, up to |num_media_packets| packets. + ForwardErrorCorrection::PacketList ConstructMediaPackets( + int num_media_packets, + uint16_t start_seq_num); + ForwardErrorCorrection::PacketList ConstructMediaPackets( + int num_media_packets); - uint16_t NextSeqNum(); + uint16_t GetFecSeqNum(); - test::RawRtpPacket* NextPacket(int offset, size_t length); + private: + uint32_t min_packet_size_; + uint32_t max_packet_size_; + uint32_t ssrc_; + Random* random_; - // Creates a new RtpPacket with the RED header added to the packet. - test::RawRtpPacket* BuildMediaRedPacket(const test::RawRtpPacket* packet); + ForwardErrorCorrection::PacketList media_packets_; + uint16_t fec_seq_num_; +}; - // Creates a new RtpPacket with FEC payload and red header. Does this by - // creating a new fake media RtpPacket, clears the marker bit and adds a RED - // header. Finally replaces the payload with the content of |packet->data|. - test::RawRtpPacket* BuildFecRedPacket( - const ForwardErrorCorrection::Packet* packet); +// This class generates media packets with a certain structure of the payload. +class AugmentedPacketGenerator { + public: + explicit AugmentedPacketGenerator(uint32_t ssrc); - void SetRedHeader(ForwardErrorCorrection::Packet* red_packet, - uint8_t payload_type, - size_t header_length) const; + // Prepare for generating a new set of packets, corresponding to a frame. + void NewFrame(size_t num_packets); - private: - static void BuildRtpHeader(uint8_t* data, const RTPHeader* header); + // Increment and return the newly incremented sequence number. + uint16_t NextPacketSeqNum(); - int num_packets_; + // Return the next packet in the current frame. + std::unique_ptr NextPacket(size_t offset, size_t length); + + protected: + // Given |header|, writes the appropriate RTP header fields in |data|. + static void WriteRtpHeader(const RTPHeader& header, uint8_t* data); + + // Number of packets left to generate, in the current frame. + size_t num_packets_; + + private: + uint32_t ssrc_; uint16_t seq_num_; uint32_t timestamp_; }; + +// This class generates media and FlexFEC packets for a single frame. +class FlexfecPacketGenerator : public AugmentedPacketGenerator { + public: + FlexfecPacketGenerator(uint32_t media_ssrc, uint32_t flexfec_ssrc); + + // Creates a new AugmentedPacket (with RTP headers) from a + // FlexFEC packet (without RTP headers). + std::unique_ptr BuildFlexfecPacket( + const ForwardErrorCorrection::Packet& packet); + + private: + uint32_t flexfec_ssrc_; + uint16_t flexfec_seq_num_; + uint32_t flexfec_timestamp_; +}; + +// This class generates media and ULPFEC packets (both encapsulated in RED) +// for a single frame. +class UlpfecPacketGenerator : public AugmentedPacketGenerator { + public: + explicit UlpfecPacketGenerator(uint32_t ssrc); + + // Creates a new AugmentedPacket with the RED header added to the packet. + static std::unique_ptr BuildMediaRedPacket( + const AugmentedPacket& packet); + + // Creates a new AugmentedPacket with FEC payload and RED header. Does this by + // creating a new fake media AugmentedPacket, clears the marker bit and adds a + // RED header. Finally replaces the payload with the content of + // |packet->data|. + std::unique_ptr BuildUlpfecRedPacket( + const ForwardErrorCorrection::Packet& packet); + + private: + static void SetRedHeader(uint8_t payload_type, + size_t header_length, + AugmentedPacket* red_packet); +}; + +} // namespace fec +} // namespace test } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_TEST_HELPER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/flexfec_header_reader_writer.h b/include/webrtc/modules/rtp_rtcp/source/flexfec_header_reader_writer.h new file mode 100644 index 0000000..13f7477 --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/flexfec_header_reader_writer.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FLEXFEC_HEADER_READER_WRITER_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_FLEXFEC_HEADER_READER_WRITER_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" + +namespace webrtc { + +// FlexFEC header, minimum 20 bytes. +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 |R|F|P|X| CC |M| PT recovery | length recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | TS recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | SSRCCount | reserved | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// 12 | SSRC_i | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 16 | SN base_i |k| Mask [0-14] | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 20 |k| Mask [15-45] (optional) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 24 |k| | +// +-+ Mask [46-108] (optional) | +// 28 | | +// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +// : ... next in SSRC_i ... : +// +// +// FlexFEC header in 'inflexible' mode (F = 1), 20 bytes. +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 |0|1|P|X| CC |M| PT recovery | length recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 4 | TS recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 8 | SSRCCount | reserved | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 12 | SSRC_i | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 16 | SN base_i | M (columns) | N (rows) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +class FlexfecHeaderReader : public FecHeaderReader { + public: + FlexfecHeaderReader(); + ~FlexfecHeaderReader() override; + + bool ReadFecHeader( + ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const override; +}; + +class FlexfecHeaderWriter : public FecHeaderWriter { + public: + FlexfecHeaderWriter(); + ~FlexfecHeaderWriter() override; + + size_t MinPacketMaskSize(const uint8_t* packet_mask, + size_t packet_mask_size) const override; + + size_t FecHeaderSize(size_t packet_mask_row_size) const override; + + void FinalizeFecHeader( + uint32_t media_ssrc, + uint16_t seq_num_base, + const uint8_t* packet_mask, + size_t packet_mask_size, + ForwardErrorCorrection::Packet* fec_packet) const override; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FLEXFEC_HEADER_READER_WRITER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/forward_error_correction.h b/include/webrtc/modules/rtp_rtcp/source/forward_error_correction.h index cbeb97e..f45473c 100644 --- a/include/webrtc/modules/rtp_rtcp/source/forward_error_correction.h +++ b/include/webrtc/modules/rtp_rtcp/source/forward_error_correction.h @@ -11,18 +11,23 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ +#include + #include +#include #include +#include "webrtc/base/basictypes.h" +#include "webrtc/base/constructormagic.h" #include "webrtc/base/refcount.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/typedefs.h" +#include "webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h" namespace webrtc { -// Forward declaration. -class FecPacket; +class FecHeaderReader; +class FecHeaderWriter; // Performs codec-independent forward error correction (FEC), based on RFC 5109. // Option exists to enable unequal protection (UEP) across packets. @@ -30,17 +35,14 @@ class FecPacket; // (referred to as uneven level protection (ULP) in RFC 5109). class ForwardErrorCorrection { public: - // Maximum number of media packets we can protect - static const unsigned int kMaxMediaPackets = 48u; - // TODO(holmer): As a next step all these struct-like packet classes should be // refactored into proper classes, and their members should be made private. // This will require parts of the functionality in forward_error_correction.cc // and receiver_fec.cc to be refactored into the packet classes. class Packet { public: - Packet() : length(0), data(), ref_count_(0) {} - virtual ~Packet() {} + Packet(); + virtual ~Packet(); // Add a reference. virtual int32_t AddRef(); @@ -49,7 +51,7 @@ class ForwardErrorCorrection { // reaches zero. virtual int32_t Release(); - size_t length; // Length of packet in bytes. + size_t length; // Length of packet in bytes. uint8_t data[IP_PACKET_SIZE]; // Packet data. private: @@ -59,26 +61,19 @@ class ForwardErrorCorrection { // TODO(holmer): Refactor into a proper class. class SortablePacket { public: - // True if first is <= than second. - static bool LessThan(const SortablePacket* first, - const SortablePacket* second); + // Functor which returns true if the sequence number of |first| + // is < the sequence number of |second|. + struct LessThan { + template + bool operator() (const S& first, const T& second); + }; uint16_t seq_num; }; - // The received list parameter of #DecodeFEC() must reference structs of this - // type. The last_media_pkt_in_frame is not required to be used for correct - // recovery, but will reduce delay by allowing #DecodeFEC() to pre-emptively - // determine frame completion. If set, we assume a FEC stream, and the - // following assumptions must hold:\n + // The received list parameter of DecodeFec() references structs of this type. // - // 1. The media packets in a frame have contiguous sequence numbers, i.e. the - // frame's FEC packets have sequence numbers either lower than the first - // media packet or higher than the last media packet.\n - // 2. All FEC packets have a sequence number base equal to the first media - // packet in the corresponding frame.\n - // - // The ssrc member is needed to ensure we can restore the SSRC field of + // The ssrc member is needed to ensure that we can restore the SSRC field of // recovered packets. In most situations this could be retrieved from other // media packets, but in the case of an FEC packet protecting a single // missing media packet, we have no other means of obtaining it. @@ -95,7 +90,7 @@ class ForwardErrorCorrection { rtc::scoped_refptr pkt; // Pointer to the packet storage. }; - // The recovered list parameter of #DecodeFEC() will reference structs of + // The recovered list parameter of DecodeFec() references structs of // this type. // TODO(holmer): Refactor into a proper class. class RecoveredPacket : public SortablePacket { @@ -108,204 +103,313 @@ class ForwardErrorCorrection { // through the received packet list. bool returned; // True when the packet already has been returned to the // caller through the callback. - uint8_t length_recovery[2]; // Two bytes used for recovering the packet - // length with XOR operations. rtc::scoped_refptr pkt; // Pointer to the packet storage. }; - typedef std::list PacketList; - typedef std::list ReceivedPacketList; - typedef std::list RecoveredPacketList; - - ForwardErrorCorrection(); - - virtual ~ForwardErrorCorrection(); - - /** - * Generates a list of FEC packets from supplied media packets. - * - * \param[in] mediaPacketList List of media packets to protect, of type - * #Packet. All packets must belong to the - * same frame and the list must not be empty. - * \param[in] protectionFactor FEC protection overhead in the [0, 255] - * domain. To obtain 100% overhead, or an - * equal number of FEC packets as media - * packets, use 255. - * \param[in] numImportantPackets The number of "important" packets in the - * frame. These packets may receive greater - * protection than the remaining packets. The - * important packets must be located at the - * start of the media packet list. For codecs - * with data partitioning, the important - * packets may correspond to first partition - * packets. - * \param[in] useUnequalProtection Parameter to enable/disable unequal - * protection (UEP) across packets. Enabling - * UEP will allocate more protection to the - * numImportantPackets from the start of the - * mediaPacketList. - * \param[in] fec_mask_type The type of packet mask used in the FEC. - * Random or bursty type may be selected. The - * bursty type is only defined up to 12 media - * packets. If the number of media packets is - * above 12, the packets masks from the - * random table will be selected. - * \param[out] fecPacketList List of FEC packets, of type #Packet. Must - * be empty on entry. The memory available - * through the list will be valid until the - * next call to GenerateFEC(). - * - * \return 0 on success, -1 on failure. - */ - int32_t GenerateFEC(const PacketList& media_packet_list, - uint8_t protection_factor, int num_important_packets, - bool use_unequal_protection, FecMaskType fec_mask_type, - PacketList* fec_packet_list); - - /** - * Decodes a list of media and FEC packets. It will parse the input received - * packet list, storing FEC packets internally and inserting media packets to - * the output recovered packet list. The recovered list will be sorted by - * ascending sequence number and have duplicates removed. The function - * should be called as new packets arrive, with the recovered list being - * progressively assembled with each call. The received packet list will be - * empty at output.\n - * - * The user will allocate packets submitted through the received list. The - * function will handle allocation of recovered packets and optionally - * deleting of all packet memory. The user may delete the recovered list - * packets, in which case they must remove deleted packets from the - * recovered list.\n - * - * \param[in] receivedPacketList List of new received packets, of type - * #ReceivedPacket, belonging to a single - * frame. At output the list will be empty, - * with packets either stored internally, - * or accessible through the recovered list. - * \param[out] recoveredPacketList List of recovered media packets, of type - * #RecoveredPacket, belonging to a single - * frame. The memory available through the - * list will be valid until the next call to - * DecodeFEC(). - * - * \return 0 on success, -1 on failure. - */ - int32_t DecodeFEC(ReceivedPacketList* received_packet_list, - RecoveredPacketList* recovered_packet_list); - - // Get the number of FEC packets, given the number of media packets and the - // protection factor. - int GetNumberOfFecPackets(int num_media_packets, int protection_factor); - - // Gets the size in bytes of the FEC/ULP headers, which must be accounted for - // as packet overhead. - // \return Packet overhead in bytes. - static size_t PacketOverhead(); - - // Reset internal states from last frame and clear the recovered_packet_list. + // Used to link media packets to their protecting FEC packets. + // + // TODO(holmer): Refactor into a proper class. + class ProtectedPacket : public ForwardErrorCorrection::SortablePacket { + public: + ProtectedPacket(); + ~ProtectedPacket(); + + rtc::scoped_refptr pkt; + }; + + using ProtectedPacketList = std::list>; + + // Used for internal storage of received FEC packets in a list. + // + // TODO(holmer): Refactor into a proper class. + class ReceivedFecPacket : public ForwardErrorCorrection::SortablePacket { + public: + ReceivedFecPacket(); + ~ReceivedFecPacket(); + + // List of media packets that this FEC packet protects. + ProtectedPacketList protected_packets; + // RTP header fields. + uint32_t ssrc; + // FEC header fields. + size_t fec_header_size; + uint32_t protected_ssrc; + uint16_t seq_num_base; + size_t packet_mask_offset; // Relative start of FEC header. + size_t packet_mask_size; + size_t protection_length; + // Raw data. + rtc::scoped_refptr pkt; + }; + + using PacketList = std::list>; + using ReceivedPacketList = std::list>; + using RecoveredPacketList = std::list>; + using ReceivedFecPacketList = std::list>; + + ~ForwardErrorCorrection(); + + // Creates a ForwardErrorCorrection tailored for a specific FEC scheme. + static std::unique_ptr CreateUlpfec(); + static std::unique_ptr CreateFlexfec(); + + // Generates a list of FEC packets from supplied media packets. + // + // Input: media_packets List of media packets to protect, of type + // Packet. All packets must belong to the + // same frame and the list must not be empty. + // Input: protection_factor FEC protection overhead in the [0, 255] + // domain. To obtain 100% overhead, or an + // equal number of FEC packets as + // media packets, use 255. + // Input: num_important_packets The number of "important" packets in the + // frame. These packets may receive greater + // protection than the remaining packets. + // The important packets must be located at the + // start of the media packet list. For codecs + // with data partitioning, the important + // packets may correspond to first partition + // packets. + // Input: use_unequal_protection Parameter to enable/disable unequal + // protection (UEP) across packets. Enabling + // UEP will allocate more protection to the + // num_important_packets from the start of the + // media_packets. + // Input: fec_mask_type The type of packet mask used in the FEC. + // Random or bursty type may be selected. The + // bursty type is only defined up to 12 media + // packets. If the number of media packets is + // above 12, the packet masks from the random + // table will be selected. + // Output: fec_packets List of pointers to generated FEC packets, + // of type Packet. Must be empty on entry. + // The memory available through the list will + // be valid until the next call to + // EncodeFec(). + // + // Returns 0 on success, -1 on failure. + // + int EncodeFec(const PacketList& media_packets, + uint8_t protection_factor, + int num_important_packets, + bool use_unequal_protection, + FecMaskType fec_mask_type, + std::list* fec_packets); + + // Decodes a list of received media and FEC packets. It will parse the + // |received_packets|, storing FEC packets internally, and move + // media packets to |recovered_packets|. The recovered list will be + // sorted by ascending sequence number and have duplicates removed. + // The function should be called as new packets arrive, and + // |recovered_packets| will be progressively assembled with each call. + // When the function returns, |received_packets| will be empty. + // + // The caller will allocate packets submitted through |received_packets|. + // The function will handle allocation of recovered packets. + // + // Input: received_packets List of new received packets, of type + // ReceivedPacket, belonging to a single + // frame. At output the list will be empty, + // with packets either stored internally, + // or accessible through the recovered list. + // Output: recovered_packets List of recovered media packets, of type + // RecoveredPacket, belonging to a single + // frame. The memory available through the + // list will be valid until the next call to + // DecodeFec(). + // + // Returns 0 on success, -1 on failure. + // + int DecodeFec(ReceivedPacketList* received_packets, + RecoveredPacketList* recovered_packets); + + // Get the number of generated FEC packets, given the number of media packets + // and the protection factor. + static int NumFecPackets(int num_media_packets, int protection_factor); + + // Gets the maximum size of the FEC headers in bytes, which must be + // accounted for as packet overhead. + size_t MaxPacketOverhead() const; + + // Reset internal states from last frame and clear |recovered_packets|. // Frees all memory allocated by this class. - void ResetState(RecoveredPacketList* recovered_packet_list); + void ResetState(RecoveredPacketList* recovered_packets); - private: - typedef std::list FecPacketList; + // TODO(brandtr): Remove these functions when the Packet classes + // have been refactored. + static uint16_t ParseSequenceNumber(uint8_t* packet); + static uint32_t ParseSsrc(uint8_t* packet); - void GenerateFecUlpHeaders(const PacketList& media_packet_list, - uint8_t* packet_mask, bool l_bit, - int num_fec_packets); + protected: + ForwardErrorCorrection(std::unique_ptr fec_header_reader, + std::unique_ptr fec_header_writer); + private: // Analyzes |media_packets| for holes in the sequence and inserts zero columns // into the |packet_mask| where those holes are found. Zero columns means that // those packets will have no protection. // Returns the number of bits used for one row of the new packet mask. // Requires that |packet_mask| has at least 6 * |num_fec_packets| bytes // allocated. - int InsertZerosInBitMasks(const PacketList& media_packets, - uint8_t* packet_mask, int num_mask_bytes, - int num_fec_packets); - - // Inserts |num_zeros| zero columns into |new_mask| at position - // |new_bit_index|. If the current byte of |new_mask| can't fit all zeros, the - // byte will be filled with zeros from |new_bit_index|, but the next byte will - // be untouched. - static void InsertZeroColumns(int num_zeros, uint8_t* new_mask, - int new_mask_bytes, int num_fec_packets, - int new_bit_index); - - // Copies the left most bit column from the byte pointed to by - // |old_bit_index| in |old_mask| to the right most column of the byte pointed - // to by |new_bit_index| in |new_mask|. |old_mask_bytes| and |new_mask_bytes| - // represent the number of bytes used per row for each mask. |num_fec_packets| - // represent the number of rows of the masks. - // The copied bit is shifted out from |old_mask| and is shifted one step to - // the left in |new_mask|. |new_mask| will contain "xxxx xxn0" after this - // operation, where x are previously inserted bits and n is the new bit. - static void CopyColumn(uint8_t* new_mask, int new_mask_bytes, - uint8_t* old_mask, int old_mask_bytes, - int num_fec_packets, int new_bit_index, - int old_bit_index); - - void GenerateFecBitStrings(const PacketList& media_packet_list, - uint8_t* packet_mask, int num_fec_packets, - bool l_bit); - - // Insert received packets into FEC or recovered list. - void InsertPackets(ReceivedPacketList* received_packet_list, - RecoveredPacketList* recovered_packet_list); - - // Insert media packet into recovered packet list. We delete duplicates. - void InsertMediaPacket(ReceivedPacket* rx_packet, - RecoveredPacketList* recovered_packet_list); + int InsertZerosInPacketMasks(const PacketList& media_packets, + size_t num_fec_packets); + + // Writes FEC payloads and some recovery fields in the FEC headers. + void GenerateFecPayloads(const PacketList& media_packets, + size_t num_fec_packets); + + // Writes the FEC header fields that are not written by GenerateFecPayloads. + // This includes writing the packet masks. + void FinalizeFecHeaders(size_t num_fec_packets, + uint32_t media_ssrc, + uint16_t seq_num_base); + + // Inserts the |received_packets| into the internal received FEC packet list + // or into |recovered_packets|. + void InsertPackets(ReceivedPacketList* received_packets, + RecoveredPacketList* recovered_packets); + + // Inserts the |received_packet| into |recovered_packets|. Deletes duplicates. + void InsertMediaPacket(RecoveredPacketList* recovered_packets, + ReceivedPacket* received_packet); // Assigns pointers to the recovered packet from all FEC packets which cover // it. // Note: This reduces the complexity when we want to try to recover a packet // since we don't have to find the intersection between recovered packets and // packets covered by the FEC packet. - void UpdateCoveringFECPackets(RecoveredPacket* packet); + void UpdateCoveringFecPackets(const RecoveredPacket& packet); - // Insert packet into FEC list. We delete duplicates. - void InsertFECPacket(ReceivedPacket* rx_packet, - const RecoveredPacketList* recovered_packet_list); + // Insert |received_packet| into internal FEC list. Deletes duplicates. + void InsertFecPacket(const RecoveredPacketList& recovered_packets, + ReceivedPacket* received_packet); - // Assigns pointers to already recovered packets covered by this FEC packet. + // Assigns pointers to already recovered packets covered by |fec_packet|. static void AssignRecoveredPackets( - FecPacket* fec_packet, const RecoveredPacketList* recovered_packets); + const RecoveredPacketList& recovered_packets, + ReceivedFecPacket* fec_packet); + + // Attempt to recover missing packets, using the internally stored + // received FEC packets. + void AttemptRecovery(RecoveredPacketList* recovered_packets); + + // Initializes headers and payload before the XOR operation + // that recovers a packet. + static bool StartPacketRecovery(const ReceivedFecPacket& fec_packet, + RecoveredPacket* recovered_packet); + + // Performs XOR between the first 8 bytes of |src| and |dst| and stores + // the result in |dst|. The 3rd and 4th bytes are used for storing + // the length recovery field. + static void XorHeaders(const Packet& src, Packet* dst); + + // Performs XOR between the payloads of |src| and |dst| and stores the result + // in |dst|. The parameter |dst_offset| determines at what byte the + // XOR operation starts in |dst|. In total, |payload_length| bytes are XORed. + static void XorPayloads(const Packet& src, + size_t payload_length, + size_t dst_offset, + Packet* dst); + + // Finalizes recovery of packet by setting RTP header fields. + // This is not specific to the FEC scheme used. + static bool FinishPacketRecovery(const ReceivedFecPacket& fec_packet, + RecoveredPacket* recovered_packet); + + // Recover a missing packet. + static bool RecoverPacket(const ReceivedFecPacket& fec_packet, + RecoveredPacket* recovered_packet); - // Insert into recovered list in correct position. - void InsertRecoveredPacket(RecoveredPacket* rec_packet_to_insert, - RecoveredPacketList* recovered_packet_list); + // Get the number of missing media packets which are covered by |fec_packet|. + // An FEC packet can recover at most one packet, and if zero packets are + // missing the FEC packet can be discarded. This function returns 2 when two + // or more packets are missing. + static int NumCoveredPacketsMissing(const ReceivedFecPacket& fec_packet); - // Attempt to recover missing packets. - void AttemptRecover(RecoveredPacketList* recovered_packet_list); + // Discards old packets in |recovered_packets|, which are no longer relevant + // for recovering lost packets. + void DiscardOldRecoveredPackets(RecoveredPacketList* recovered_packets); - // Initializes the packet recovery using the FEC packet. - static bool InitRecovery(const FecPacket* fec_packet, - RecoveredPacket* recovered); + std::unique_ptr fec_header_reader_; + std::unique_ptr fec_header_writer_; - // Performs XOR between |src_packet| and |dst_packet| and stores the result - // in |dst_packet|. - static void XorPackets(const Packet* src_packet, RecoveredPacket* dst_packet); + std::vector generated_fec_packets_; + ReceivedFecPacketList received_fec_packets_; + + // Arrays used to avoid dynamically allocating memory when generating + // the packet masks. + // (There are never more than |kUlpfecMaxMediaPackets| FEC packets generated.) + uint8_t packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize]; + uint8_t tmp_packet_masks_[kUlpfecMaxMediaPackets * kUlpfecMaxPacketMaskSize]; + size_t packet_mask_size_; +}; - // Finish up the recovery of a packet. - static bool FinishRecovery(RecoveredPacket* recovered); +// Classes derived from FecHeader{Reader,Writer} encapsulate the +// specifics of reading and writing FEC header for, e.g., ULPFEC +// and FlexFEC. +class FecHeaderReader { + public: + virtual ~FecHeaderReader(); - // Recover a missing packet. - bool RecoverPacket(const FecPacket* fec_packet, - RecoveredPacket* rec_packet_to_insert); + // The maximum number of media packets that can be covered by one FEC packet. + size_t MaxMediaPackets() const; - // Get the number of missing media packets which are covered by this - // FEC packet. An FEC packet can recover at most one packet, and if zero - // packets are missing the FEC packet can be discarded. - // This function returns 2 when two or more packets are missing. - static int NumCoveredPacketsMissing(const FecPacket* fec_packet); + // The maximum number of FEC packets that is supported, per call + // to ForwardErrorCorrection::EncodeFec(). + size_t MaxFecPackets() const; - static void DiscardFECPacket(FecPacket* fec_packet); - static void DiscardOldPackets(RecoveredPacketList* recovered_packet_list); - static uint16_t ParseSequenceNumber(uint8_t* packet); + // Parses FEC header and stores information in ReceivedFecPacket members. + virtual bool ReadFecHeader( + ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const = 0; - std::vector generated_fec_packets_; - FecPacketList fec_packet_list_; - bool fec_packet_received_; + protected: + FecHeaderReader(size_t max_media_packets, size_t max_fec_packets); + + const size_t max_media_packets_; + const size_t max_fec_packets_; +}; + +class FecHeaderWriter { + public: + virtual ~FecHeaderWriter(); + + // The maximum number of media packets that can be covered by one FEC packet. + size_t MaxMediaPackets() const; + + // The maximum number of FEC packets that is supported, per call + // to ForwardErrorCorrection::EncodeFec(). + size_t MaxFecPackets() const; + + // The maximum overhead (in bytes) per packet, due to FEC headers. + size_t MaxPacketOverhead() const; + + // Calculates the minimum packet mask size needed (in bytes), + // given the discrete options of the ULPFEC masks and the bits + // set in the current packet mask. + virtual size_t MinPacketMaskSize(const uint8_t* packet_mask, + size_t packet_mask_size) const = 0; + + // The header size (in bytes), given the packet mask size. + virtual size_t FecHeaderSize(size_t packet_mask_size) const = 0; + + // Writes FEC header. + virtual void FinalizeFecHeader( + uint32_t media_ssrc, + uint16_t seq_num_base, + const uint8_t* packet_mask, + size_t packet_mask_size, + ForwardErrorCorrection::Packet* fec_packet) const = 0; + + protected: + FecHeaderWriter(size_t max_media_packets, + size_t max_fec_packets, + size_t max_packet_overhead); + + const size_t max_media_packets_; + const size_t max_fec_packets_; + const size_t max_packet_overhead_; }; + } // namespace webrtc + #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h b/include/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h index f82e46d..c61aea8 100644 --- a/include/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h +++ b/include/webrtc/modules/rtp_rtcp/source/forward_error_correction_internal.h @@ -11,15 +11,22 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_INTERNAL_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_INTERNAL_H_ -#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { -// Packet mask size in bytes (L bit is set). -static const int kMaskSizeLBitSet = 6; -// Packet mask size in bytes (L bit is cleared). -static const int kMaskSizeLBitClear = 2; +// Maximum number of media packets that can be protected +// by these packet masks. +constexpr size_t kUlpfecMaxMediaPackets = 48; + +// Packet mask size in bytes (given L bit). +constexpr size_t kUlpfecPacketMaskSizeLBitClear = 2; +constexpr size_t kUlpfecPacketMaskSizeLBitSet = 6; + +// Convenience constants. +constexpr size_t kUlpfecMinPacketMaskSize = kUlpfecPacketMaskSizeLBitClear; +constexpr size_t kUlpfecMaxPacketMaskSize = kUlpfecPacketMaskSizeLBitSet; namespace internal { @@ -65,6 +72,37 @@ void GeneratePacketMasks(int num_media_packets, int num_fec_packets, const PacketMaskTable& mask_table, uint8_t* packet_mask); +// Returns the required packet mask size, given the number of sequence numbers +// that will be covered. +size_t PacketMaskSize(size_t num_sequence_numbers); + +// Inserts |num_zeros| zero columns into |new_mask| at position +// |new_bit_index|. If the current byte of |new_mask| can't fit all zeros, the +// byte will be filled with zeros from |new_bit_index|, but the next byte will +// be untouched. +void InsertZeroColumns(int num_zeros, + uint8_t* new_mask, + int new_mask_bytes, + int num_fec_packets, + int new_bit_index); + +// Copies the left most bit column from the byte pointed to by +// |old_bit_index| in |old_mask| to the right most column of the byte pointed +// to by |new_bit_index| in |new_mask|. |old_mask_bytes| and |new_mask_bytes| +// represent the number of bytes used per row for each mask. |num_fec_packets| +// represent the number of rows of the masks. +// The copied bit is shifted out from |old_mask| and is shifted one step to +// the left in |new_mask|. |new_mask| will contain "xxxx xxn0" after this +// operation, where x are previously inserted bits and n is the new bit. +void CopyColumn(uint8_t* new_mask, + int new_mask_bytes, + uint8_t* old_mask, + int old_mask_bytes, + int num_fec_packets, + int new_bit_index, + int old_bit_index); + } // namespace internal } // namespace webrtc + #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_INTERNAL_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h b/include/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h deleted file mode 100644 index 28276af..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/h264_bitstream_parser.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ - -#include -#include - -namespace rtc { -class BitBuffer; -} - -namespace webrtc { - -// Stateful H264 bitstream parser (due to SPS/PPS). Used to parse out QP values -// from the bitstream. -// TODO(pbos): Unify with RTP SPS parsing and only use one H264 parser. -// TODO(pbos): If/when this gets used on the receiver side CHECKs must be -// removed and gracefully abort as we have no control over receive-side -// bitstreams. -class H264BitstreamParser { - public: - // Parse an additional chunk of H264 bitstream. - void ParseBitstream(const uint8_t* bitstream, size_t length); - - // Get the last extracted QP value from the parsed bitstream. - bool GetLastSliceQp(int* qp) const; - - private: - // Captured in SPS and used when parsing slice NALUs. - struct SpsState { - SpsState(); - - uint32_t delta_pic_order_always_zero_flag = 0; - uint32_t separate_colour_plane_flag = 0; - uint32_t frame_mbs_only_flag = 0; - uint32_t log2_max_frame_num_minus4 = 0; - uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0; - uint32_t pic_order_cnt_type = 0; - }; - - struct PpsState { - PpsState(); - - bool bottom_field_pic_order_in_frame_present_flag = false; - bool weighted_pred_flag = false; - uint32_t weighted_bipred_idc = false; - uint32_t redundant_pic_cnt_present_flag = 0; - int pic_init_qp_minus26 = 0; - }; - - void ParseSlice(const uint8_t* slice, size_t length); - bool ParseSpsNalu(const uint8_t* sps_nalu, size_t length); - bool ParsePpsNalu(const uint8_t* pps_nalu, size_t length); - bool ParseNonParameterSetNalu(const uint8_t* source, - size_t source_length, - uint8_t nalu_type); - - // SPS/PPS state, updated when parsing new SPS/PPS, used to parse slices. - bool sps_parsed_ = false; - SpsState sps_; - bool pps_parsed_ = false; - PpsState pps_; - - // Last parsed slice QP. - bool last_slice_qp_delta_parsed_ = false; - int32_t last_slice_qp_delta_ = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_BITSTREAM_PARSER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/h264_sps_parser.h b/include/webrtc/modules/rtp_rtcp/source/h264_sps_parser.h deleted file mode 100644 index c05ee67..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/h264_sps_parser.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_SPS_PARSER_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_SPS_PARSER_H_ - -#include "webrtc/base/common.h" - -namespace webrtc { - -// A class for parsing out sequence parameter set (SPS) data from an H264 NALU. -// Currently, only resolution is read without being ignored. -class H264SpsParser { - public: - H264SpsParser(const uint8_t* sps, size_t byte_length); - // Parses the SPS to completion. Returns true if the SPS was parsed correctly. - bool Parse(); - uint16_t width() { return width_; } - uint16_t height() { return height_; } - - private: - const uint8_t* const sps_; - const size_t byte_length_; - - uint16_t width_; - uint16_t height_; -}; - -} // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_H264_SPS_PARSER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h b/include/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h deleted file mode 100644 index 011829c..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/mock/mock_rtp_payload_strategy.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ - -#include "testing/gmock/include/gmock/gmock.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h" - -namespace webrtc { - -class MockRTPPayloadStrategy : public RTPPayloadStrategy { - public: - MOCK_CONST_METHOD0(CodecsMustBeUnique, - bool()); - MOCK_CONST_METHOD4(PayloadIsCompatible, - bool(const RtpUtility::Payload& payload, - const uint32_t frequency, - const size_t channels, - const uint32_t rate)); - MOCK_CONST_METHOD2(UpdatePayloadRate, - void(RtpUtility::Payload* payload, const uint32_t rate)); - MOCK_CONST_METHOD1(GetPayloadTypeFrequency, - int(const RtpUtility::Payload& payload)); - MOCK_CONST_METHOD5( - CreatePayloadType, - RtpUtility::Payload*(const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int8_t payloadType, - const uint32_t frequency, - const size_t channels, - const uint32_t rate)); -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_MOCK_MOCK_RTP_PAYLOAD_STRATEGY_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h b/include/webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h new file mode 100644 index 0000000..013d1c1 --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_PLAYOUT_DELAY_ORACLE_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_PLAYOUT_DELAY_ORACLE_H_ + +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/base/thread_annotations.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" + +namespace webrtc { + +// This class tracks the application requests to limit minimum and maximum +// playout delay and makes a decision on whether the current RTP frame +// should include the playout out delay extension header. +// +// Playout delay can be defined in terms of capture and render time as follows: +// +// Render time = Capture time in receiver time + playout delay +// +// The application specifies a minimum and maximum limit for the playout delay +// which are both communicated to the receiver and the receiver can adapt +// the playout delay within this range based on observed network jitter. +class PlayoutDelayOracle { + public: + PlayoutDelayOracle(); + ~PlayoutDelayOracle(); + + // Returns true if the current frame should include the playout delay + // extension + bool send_playout_delay() const { + rtc::CritScope lock(&crit_sect_); + return send_playout_delay_; + } + + // Returns current playout delay. + PlayoutDelay playout_delay() const { + rtc::CritScope lock(&crit_sect_); + return playout_delay_; + } + + // Updates the application requested playout delay, current ssrc + // and the current sequence number. + void UpdateRequest(uint32_t ssrc, + PlayoutDelay playout_delay, + uint16_t seq_num); + + void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks); + + private: + // The playout delay information is updated from the encoder thread(s). + // The sequence number feedback is updated from the worker thread. + // Guards access to data across multiple threads. + rtc::CriticalSection crit_sect_; + // The current highest sequence number on which playout delay has been sent. + int64_t high_sequence_number_ GUARDED_BY(crit_sect_); + // Indicates whether the playout delay should go on the next frame. + bool send_playout_delay_ GUARDED_BY(crit_sect_); + // Sender ssrc. + uint32_t ssrc_ GUARDED_BY(crit_sect_); + // Sequence number unwrapper. + SequenceNumberUnwrapper unwrapper_ GUARDED_BY(crit_sect_); + // Playout delay values on the next frame if |send_playout_delay_| is set. + PlayoutDelay playout_delay_ GUARDED_BY(crit_sect_); + + RTC_DISALLOW_COPY_AND_ASSIGN(PlayoutDelayOracle); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_PLAYOUT_DELAY_ORACLE_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/producer_fec.h b/include/webrtc/modules/rtp_rtcp/source/producer_fec.h deleted file mode 100644 index dcd71c8..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/producer_fec.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_PRODUCER_FEC_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_PRODUCER_FEC_H_ - -#include -#include - -#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" - -namespace webrtc { - -class RedPacket { - public: - explicit RedPacket(size_t length); - ~RedPacket(); - void CreateHeader(const uint8_t* rtp_header, size_t header_length, - int red_pl_type, int pl_type); - void SetSeqNum(int seq_num); - void AssignPayload(const uint8_t* payload, size_t length); - void ClearMarkerBit(); - uint8_t* data() const; - size_t length() const; - - private: - uint8_t* data_; - size_t length_; - size_t header_length_; -}; - -class ProducerFec { - public: - explicit ProducerFec(ForwardErrorCorrection* fec); - ~ProducerFec(); - - void SetFecParameters(const FecProtectionParams* params, - int max_fec_frames); - - // The caller is expected to delete the memory when done. - RedPacket* BuildRedPacket(const uint8_t* data_buffer, - size_t payload_length, - size_t rtp_header_length, - int red_pl_type); - - int AddRtpPacketAndGenerateFec(const uint8_t* data_buffer, - size_t payload_length, - size_t rtp_header_length); - - bool ExcessOverheadBelowMax(); - - bool MinimumMediaPacketsReached(); - - bool FecAvailable() const; - size_t NumAvailableFecPackets() const; - - // GetFecPackets allocates memory and creates FEC packets, but the caller is - // assumed to delete the memory when done with the packets. - std::vector GetFecPackets(int red_pl_type, - int fec_pl_type, - uint16_t first_seq_num, - size_t rtp_header_length); - - private: - void DeletePackets(); - int Overhead() const; - ForwardErrorCorrection* fec_; - std::list media_packets_fec_; - std::list fec_packets_; - int num_frames_; - int num_first_partition_; - int minimum_media_packets_fec_; - FecProtectionParams params_; - FecProtectionParams new_params_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_PRODUCER_FEC_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h b/include/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h index 3967967..913f3b5 100644 --- a/include/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/include/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -17,7 +17,7 @@ #include #include "webrtc/base/criticalsection.h" -#include "webrtc/modules/rtp_rtcp/source/bitrate.h" +#include "webrtc/base/rate_statistics.h" #include "webrtc/system_wrappers/include/ntp_time.h" namespace webrtc { @@ -44,7 +44,6 @@ class StreamStatisticianImpl : public StreamStatistician { bool retransmitted); void FecPacketReceived(const RTPHeader& header, size_t packet_length); void SetMaxReorderingThreshold(int max_reordering_threshold); - void ProcessBitrate(); virtual void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const; private: @@ -57,9 +56,9 @@ class StreamStatisticianImpl : public StreamStatistician { void NotifyRtpCallback() LOCKS_EXCLUDED(stream_lock_); void NotifyRtcpCallback() LOCKS_EXCLUDED(stream_lock_); - Clock* clock_; + Clock* const clock_; rtc::CriticalSection stream_lock_; - Bitrate incoming_bitrate_; + RateStatistics incoming_bitrate_; uint32_t ssrc_; int max_reordering_threshold_; // In number of packets or sequence numbers. @@ -108,10 +107,6 @@ class ReceiveStatisticsImpl : public ReceiveStatistics, StreamStatistician* GetStatistician(uint32_t ssrc) const override; void SetMaxReorderingThreshold(int max_reordering_threshold) override; - // Implement Module. - void Process() override; - int64_t TimeUntilNextProcess() override; - void RegisterRtcpStatisticsCallback( RtcpStatisticsCallback* callback) override; @@ -127,9 +122,8 @@ class ReceiveStatisticsImpl : public ReceiveStatistics, typedef std::map StatisticianImplMap; - Clock* clock_; + Clock* const clock_; rtc::CriticalSection receive_statistics_lock_; - int64_t last_rate_update_ms_; StatisticianImplMap statisticians_; RtcpStatisticsCallback* rtcp_stats_callback_; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h new file mode 100644 index 0000000..72fad6c --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h @@ -0,0 +1,40 @@ +/* +* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. +* +* Use of this source code is governed by a BSD-style license +* that can be found in the LICENSE file in the root of the source +* tree. An additional intellectual property rights grant can be found +* in the file PATENTS. All contributing project authors may +* be found in the AUTHORS file in the root of the source tree. +*/ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_NACK_STATS_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_NACK_STATS_H_ + +#include + +namespace webrtc { + +class RtcpNackStats { + public: + RtcpNackStats(); + + // Updates stats with requested sequence number. + // This function should be called for each NACK request to calculate the + // number of unique NACKed RTP packets. + void ReportRequest(uint16_t sequence_number); + + // Gets the number of NACKed RTP packets. + uint32_t requests() const { return requests_; } + + // Gets the number of unique NACKed RTP packets. + uint32_t unique_requests() const { return unique_requests_; } + + private: + uint16_t max_sequence_number_; + uint32_t requests_; + uint32_t unique_requests_; +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_NACK_STATS_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet.h index 27ec57a..86ed11d 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet.h @@ -8,12 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. * */ - #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ +#include "webrtc/base/basictypes.h" #include "webrtc/base/buffer.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { @@ -21,16 +20,16 @@ namespace rtcp { // // Example: // ReportBlock report_block; -// report_block.To(234); -// report_block.WithFractionLost(10); +// report_block.SetMediaSsrc(234); +// report_block.SetFractionLost(10); // // ReceiverReport rr; -// rr.From(123); -// rr.WithReportBlock(report_block); +// rr.SetSenderSsrc(123); +// rr.AddReportBlock(report_block); // // Fir fir; -// fir.From(123); -// fir.WithRequestTo(234, 56); +// fir.SetSenderSsrc(123); +// fir.AddRequestTo(234, 56); // // size_t length = 0; // Builds an intra frame request // uint8_t packet[kPacketSize]; // with sequence number 56. @@ -46,27 +45,24 @@ namespace rtcp { class RtcpPacket { public: - virtual ~RtcpPacket() {} - // Callback used to signal that an RTCP packet is ready. Note that this may // not contain all data in this RtcpPacket; if a packet cannot fit in // max_length bytes, it will be fragmented and multiple calls to this // callback will be made. class PacketReadyCallback { public: + virtual void OnPacketReady(uint8_t* data, size_t length) = 0; + + protected: PacketReadyCallback() {} virtual ~PacketReadyCallback() {} - - virtual void OnPacketReady(uint8_t* data, size_t length) = 0; }; - // Convenience method mostly used for test. Max length of IP_PACKET_SIZE is - // used, will cause assertion error if fragmentation occurs. - rtc::Buffer Build() const; + virtual ~RtcpPacket() {} - // Returns true if call to Create succeeded. A buffer of size - // IP_PACKET_SIZE will be allocated and reused between calls to callback. - bool Build(PacketReadyCallback* callback) const; + // Convenience method mostly used for test. Creates packet without + // fragmentation using BlockLength() to allocate big enough buffer. + rtc::Buffer Build() const; // Returns true if call to Create succeeded. Provided buffer reference // will be used for all calls to callback. @@ -86,21 +82,21 @@ class RtcpPacket { PacketReadyCallback* callback) const = 0; protected: + // Size of the rtcp common header. + static constexpr size_t kHeaderLength = 4; RtcpPacket() {} static void CreateHeader(uint8_t count_or_format, uint8_t packet_type, - size_t block_length, // Size in 32bit words - 1. + size_t block_length, // Payload size in 32bit words. uint8_t* buffer, size_t* pos); bool OnBufferFull(uint8_t* packet, size_t* index, - RtcpPacket::PacketReadyCallback* callback) const; - + PacketReadyCallback* callback) const; + // Size of the rtcp packet as written in header. size_t HeaderLength() const; - - static const size_t kHeaderLength = 4; }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h index f5a885c..42a16c7 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h @@ -12,32 +12,25 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_APP_H_ #include "webrtc/base/buffer.h" -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; class App : public RtcpPacket { public: - static const uint8_t kPacketType = 204; - // 28 bytes for UDP header - // 12 bytes for RTCP app header - static const size_t kMaxDataSize = IP_PACKET_SIZE - 12 - 28; + static constexpr uint8_t kPacketType = 204; App() : sub_type_(0), ssrc_(0), name_(0) {} - - virtual ~App() {} + ~App() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void From(uint32_t ssrc) { ssrc_ = ssrc; } - void WithSubType(uint8_t subtype); - void WithName(uint32_t name) { name_ = name; } - void WithData(const uint8_t* data, size_t data_length); + void SetSsrc(uint32_t ssrc) { ssrc_ = ssrc; } + void SetSubType(uint8_t subtype); + void SetName(uint32_t name) { name_ = name; } + void SetData(const uint8_t* data, size_t data_length); uint8_t sub_type() const { return sub_type_; } uint32_t ssrc() const { return ssrc_; } @@ -52,14 +45,16 @@ class App : public RtcpPacket { RtcpPacket::PacketReadyCallback* callback) const override; private: - size_t BlockLength() const override { return 12 + data_.size(); } + static constexpr size_t kAppBaseLength = 8; // Ssrc and Name. + static constexpr size_t kMaxDataSize = 0xffff * 4 - kAppBaseLength; + size_t BlockLength() const override { + return kHeaderLength + kAppBaseLength + data_.size(); + } uint8_t sub_type_; uint32_t ssrc_; uint32_t name_; rtc::Buffer data_; - - RTC_DISALLOW_COPY_AND_ASSIGN(App); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h index ad28cb3..c3f1cab 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h @@ -15,7 +15,6 @@ #include #include -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" namespace webrtc { @@ -24,7 +23,7 @@ class CommonHeader; class Bye : public RtcpPacket { public: - static const uint8_t kPacketType = 203; + static constexpr uint8_t kPacketType = 203; Bye(); ~Bye() override {} @@ -32,9 +31,9 @@ class Bye : public RtcpPacket { // Parse assumes header is already parsed and validated. bool Parse(const CommonHeader& packet); - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } - bool WithCsrc(uint32_t csrc); - void WithReason(const std::string& reason); + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } + bool SetCsrcs(std::vector csrcs); + void SetReason(std::string reason); uint32_t sender_ssrc() const { return sender_ssrc_; } const std::vector& csrcs() const { return csrcs_; } @@ -54,8 +53,6 @@ class Bye : public RtcpPacket { uint32_t sender_ssrc_; std::vector csrcs_; std::string reason_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Bye); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h index a48c339..c5f5c23 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h @@ -32,7 +32,6 @@ struct ReceiveTimeInfo { class Dlrr { public: static const uint8_t kBlockType = 5; - static const size_t kMaxNumberOfDlrrItems = 100; Dlrr() {} Dlrr(const Dlrr& other) = default; @@ -40,6 +39,9 @@ class Dlrr { Dlrr& operator=(const Dlrr& other) = default; + // Dlrr without items treated same as no dlrr block. + explicit operator bool() const { return !sub_blocks_.empty(); } + // Second parameter is value read from block header, // i.e. size of block in 32bits excluding block header itself. bool Parse(const uint8_t* buffer, uint16_t block_length_32bits); @@ -49,9 +51,10 @@ class Dlrr { // Consumes BlockLength() bytes. void Create(uint8_t* buffer) const; - // Max 100 DLRR Items can be added per DLRR report block. - bool WithDlrrItem(const ReceiveTimeInfo& time_info); - bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr); + void ClearItems() { sub_blocks_.clear(); } + void AddDlrrItem(const ReceiveTimeInfo& time_info) { + sub_blocks_.push_back(time_info); + } const std::vector& sub_blocks() const { return sub_blocks_; } diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h index 34eb57f..2e56e33 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h @@ -13,32 +13,27 @@ #include -#include "webrtc/base/checks.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; class ExtendedJitterReport : public RtcpPacket { public: - static const uint8_t kPacketType = 195; + static constexpr uint8_t kPacketType = 195; + static constexpr size_t kMaxNumberOfJitterValues = 0x1f; - ExtendedJitterReport() : RtcpPacket() {} - - virtual ~ExtendedJitterReport() {} + ExtendedJitterReport() {} + ~ExtendedJitterReport() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - bool WithJitter(uint32_t jitter); + bool SetJitterValues(std::vector jitter_values); - size_t jitters_count() const { return inter_arrival_jitters_.size(); } - uint32_t jitter(size_t index) const { - RTC_DCHECK_LT(index, jitters_count()); - return inter_arrival_jitters_[index]; + const std::vector& jitter_values() { + return inter_arrival_jitters_; } protected: @@ -48,15 +43,13 @@ class ExtendedJitterReport : public RtcpPacket { RtcpPacket::PacketReadyCallback* callback) const override; private: - static const int kMaxNumberOfJitters = 0x1f; + static constexpr size_t kJitterSizeBytes = 4; size_t BlockLength() const override { - return kHeaderLength + 4 * inter_arrival_jitters_.size(); + return kHeaderLength + kJitterSizeBytes * inter_arrival_jitters_.size(); } std::vector inter_arrival_jitters_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ExtendedJitterReport); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h index d7e715b..21fadd8 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h @@ -13,40 +13,43 @@ #include -#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR). class ExtendedReports : public RtcpPacket { public: - static const uint8_t kPacketType = 207; + static constexpr uint8_t kPacketType = 207; ExtendedReports(); ~ExtendedReports() override; // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } - // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr. - bool WithRrtr(const Rrtr& rrtr); - bool WithDlrr(const Dlrr& dlrr); - bool WithVoipMetric(const VoipMetric& voip_metric); + void SetRrtr(const Rrtr& rrtr); + void AddDlrrItem(const ReceiveTimeInfo& time_info); + void SetVoipMetric(const VoipMetric& voip_metric); + void SetTargetBitrate(const TargetBitrate& target_bitrate); uint32_t sender_ssrc() const { return sender_ssrc_; } - const std::vector& rrtrs() const { return rrtr_blocks_; } - const std::vector& dlrrs() const { return dlrr_blocks_; } - const std::vector& voip_metrics() const { - return voip_metric_blocks_; + const rtc::Optional& rrtr() const { return rrtr_block_; } + const Dlrr& dlrr() const { return dlrr_block_; } + const rtc::Optional& voip_metric() const { + return voip_metric_block_; + } + const rtc::Optional& target_bitrate() { + return target_bitrate_; } protected: @@ -56,32 +59,30 @@ class ExtendedReports : public RtcpPacket { RtcpPacket::PacketReadyCallback* callback) const override; private: - static const size_t kMaxNumberOfRrtrBlocks = 50; - static const size_t kMaxNumberOfDlrrBlocks = 50; - static const size_t kMaxNumberOfVoipMetricBlocks = 50; - static const size_t kXrBaseLength = 4; + static constexpr size_t kXrBaseLength = 4; size_t BlockLength() const override { return kHeaderLength + kXrBaseLength + RrtrLength() + DlrrLength() + - VoipMetricLength(); + VoipMetricLength() + TargetBitrateLength(); } - size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); } - size_t DlrrLength() const; + size_t RrtrLength() const { return rrtr_block_ ? Rrtr::kLength : 0; } + size_t DlrrLength() const { return dlrr_block_.BlockLength(); } size_t VoipMetricLength() const { - return VoipMetric::kLength * voip_metric_blocks_.size(); + return voip_metric_block_ ? VoipMetric::kLength : 0; } + size_t TargetBitrateLength() const; void ParseRrtrBlock(const uint8_t* block, uint16_t block_length); void ParseDlrrBlock(const uint8_t* block, uint16_t block_length); void ParseVoipMetricBlock(const uint8_t* block, uint16_t block_length); + void ParseTargetBitrateBlock(const uint8_t* block, uint16_t block_length); uint32_t sender_ssrc_; - std::vector rrtr_blocks_; - std::vector dlrr_blocks_; - std::vector voip_metric_blocks_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ExtendedReports); + rtc::Optional rrtr_block_; + Dlrr dlrr_block_; // Dlrr without items treated same as no dlrr block. + rtc::Optional voip_metric_block_; + rtc::Optional target_bitrate_; }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h index 992ce6d..59f3b61 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h @@ -15,14 +15,14 @@ #include "webrtc/base/basictypes.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; // Full intra request (FIR) (RFC 5104). class Fir : public Psfb { public: - static const uint8_t kFeedbackMessageType = 4; + static constexpr uint8_t kFeedbackMessageType = 4; struct Request { Request() : ssrc(0), seq_nr(0) {} Request(uint32_t ssrc, uint8_t seq_nr) : ssrc(ssrc), seq_nr(seq_nr) {} @@ -34,11 +34,10 @@ class Fir : public Psfb { ~Fir() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithRequestTo(uint32_t ssrc, uint8_t seq_num) { - items_.push_back(Request(ssrc, seq_num)); + void AddRequestTo(uint32_t ssrc, uint8_t seq_num) { + items_.emplace_back(ssrc, seq_num); } const std::vector& requests() const { return items_; } @@ -49,12 +48,12 @@ class Fir : public Psfb { RtcpPacket::PacketReadyCallback* callback) const override; private: - static const size_t kFciLength = 8; + static constexpr size_t kFciLength = 8; size_t BlockLength() const override { return kHeaderLength + kCommonFeedbackLength + kFciLength * items_.size(); } // SSRC of media source is not used in FIR packet. Shadow base functions. - void To(uint32_t ssrc); + void SetMediaSsrc(uint32_t ssrc); uint32_t media_ssrc() const; std::vector items_; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h index b6acae5..65a6593 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h @@ -14,25 +14,22 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; class Nack : public Rtpfb { public: - const uint8_t kFeedbackMessageType = 1; - Nack() {} - - virtual ~Nack() {} + static constexpr uint8_t kFeedbackMessageType = 1; + Nack(); + ~Nack() override; // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithList(const uint16_t* nack_list, size_t length); + void SetPacketIds(const uint16_t* nack_list, size_t length); const std::vector& packet_ids() const { return packet_ids_; } protected: @@ -44,19 +41,17 @@ class Nack : public Rtpfb { size_t BlockLength() const override; private: - const size_t kNackItemLength = 4; + static constexpr size_t kNackItemLength = 4; struct PackedNack { uint16_t first_pid; uint16_t bitmask; }; - void Pack(); // Fills packed_ using packed_ids_. (used in WithList). + void Pack(); // Fills packed_ using packed_ids_. (used in SetPacketIds). void Unpack(); // Fills packet_ids_ using packed_. (used in Parse). std::vector packed_; std::vector packet_ids_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Nack); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h index 64caf1b..1cfde4f 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h @@ -11,7 +11,6 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_PLI_H_ #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" namespace webrtc { @@ -20,7 +19,7 @@ class CommonHeader; // Picture loss indication (PLI) (RFC 4585). class Pli : public Psfb { public: - static const uint8_t kFeedbackMessageType = 1; + static constexpr uint8_t kFeedbackMessageType = 1; Pli() {} ~Pli() override {} @@ -37,8 +36,6 @@ class Pli : public Psfb { size_t BlockLength() const override { return kHeaderLength + kCommonFeedbackLength; } - - RTC_DISALLOW_COPY_AND_ASSIGN(Pli); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h index dddcdec..762dc61 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h @@ -22,19 +22,19 @@ namespace rtcp { // RFC 4585, Section 6.3. class Psfb : public RtcpPacket { public: - static const uint8_t kPacketType = 206; + static constexpr uint8_t kPacketType = 206; Psfb() : sender_ssrc_(0), media_ssrc_(0) {} - virtual ~Psfb() {} + ~Psfb() override {} - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } - void To(uint32_t ssrc) { media_ssrc_ = ssrc; } + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void SetMediaSsrc(uint32_t ssrc) { media_ssrc_ = ssrc; } uint32_t sender_ssrc() const { return sender_ssrc_; } uint32_t media_ssrc() const { return media_ssrc_; } protected: - static const size_t kCommonFeedbackLength = 8; + static constexpr size_t kCommonFeedbackLength = 8; void ParseCommonFeedback(const uint8_t* payload); void CreateCommonFeedback(uint8_t* payload) const; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h index 8568e73..eb45e14 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h @@ -12,23 +12,22 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RAPID_RESYNC_REQUEST_H_ #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; + // draft-perkins-avt-rapid-rtp-sync-03 class RapidResyncRequest : public Rtpfb { public: - static const uint8_t kFeedbackMessageType = 5; + static constexpr uint8_t kFeedbackMessageType = 5; RapidResyncRequest() {} ~RapidResyncRequest() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& header); protected: bool Create(uint8_t* packet, @@ -40,8 +39,6 @@ class RapidResyncRequest : public Rtpfb { size_t BlockLength() const override { return kHeaderLength + kCommonFeedbackLength; } - - RTC_DISALLOW_COPY_AND_ASSIGN(RapidResyncRequest); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h index 0630adb..09aa0fe 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h @@ -14,7 +14,6 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" @@ -24,16 +23,15 @@ class CommonHeader; class ReceiverReport : public RtcpPacket { public: - static const uint8_t kPacketType = 201; + static constexpr uint8_t kPacketType = 201; ReceiverReport() : sender_ssrc_(0) {} - ~ReceiverReport() override {} // Parse assumes header is already parsed and validated. bool Parse(const CommonHeader& packet); - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } - bool WithReportBlock(const ReportBlock& block); + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } + bool AddReportBlock(const ReportBlock& block); uint32_t sender_ssrc() const { return sender_ssrc_; } const std::vector& report_blocks() const { @@ -57,8 +55,6 @@ class ReceiverReport : public RtcpPacket { uint32_t sender_ssrc_; std::vector report_blocks_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ReceiverReport); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h index 9f10921..fdcce10 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h @@ -14,7 +14,6 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" namespace webrtc { @@ -25,6 +24,7 @@ class CommonHeader; class Remb : public Psfb { public: static constexpr uint8_t kFeedbackMessageType = 15; + static constexpr size_t kMaxNumberOfSsrcs = 0xff; Remb() : bitrate_bps_(0) {} ~Remb() override {} @@ -32,9 +32,8 @@ class Remb : public Psfb { // Parse assumes header is already parsed and validated. bool Parse(const CommonHeader& packet); - bool AppliesTo(uint32_t ssrc); - bool AppliesToMany(const std::vector& ssrcs); - void WithBitrateBps(uint64_t bitrate_bps) { bitrate_bps_ = bitrate_bps; } + bool SetSsrcs(std::vector ssrcs); + void SetBitrateBps(uint64_t bitrate_bps) { bitrate_bps_ = bitrate_bps; } uint64_t bitrate_bps() const { return bitrate_bps_; } const std::vector& ssrcs() const { return ssrcs_; } @@ -50,17 +49,14 @@ class Remb : public Psfb { } private: - static constexpr size_t kMaxNumberOfSsrcs = 0xff; static constexpr uint32_t kUniqueIdentifier = 0x52454D42; // 'R' 'E' 'M' 'B'. // Media ssrc is unused, shadow base class setter and getter. - void To(uint32_t); + void SetMediaSsrc(uint32_t); uint32_t media_ssrc() const; uint64_t bitrate_bps_; std::vector ssrcs_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Remb); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h index ef99e17..bdc3cbc 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h @@ -30,17 +30,17 @@ class ReportBlock { // Consumes ReportBlock::kLength bytes. void Create(uint8_t* buffer) const; - void To(uint32_t ssrc) { source_ssrc_ = ssrc; } - void WithFractionLost(uint8_t fraction_lost) { + void SetMediaSsrc(uint32_t ssrc) { source_ssrc_ = ssrc; } + void SetFractionLost(uint8_t fraction_lost) { fraction_lost_ = fraction_lost; } - bool WithCumulativeLost(uint32_t cumulative_lost); - void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) { + bool SetCumulativeLost(uint32_t cumulative_lost); + void SetExtHighestSeqNum(uint32_t ext_highest_seq_num) { extended_high_seq_num_ = ext_highest_seq_num; } - void WithJitter(uint32_t jitter) { jitter_ = jitter; } - void WithLastSr(uint32_t last_sr) { last_sr_ = last_sr; } - void WithDelayLastSr(uint32_t delay_last_sr) { + void SetJitter(uint32_t jitter) { jitter_ = jitter; } + void SetLastSr(uint32_t last_sr) { last_sr_ = last_sr; } + void SetDelayLastSr(uint32_t delay_last_sr) { delay_since_last_sr_ = delay_last_sr; } diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h index 7d4895b..d65023d 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h @@ -12,26 +12,25 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_RPSI_H_ #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; + // Reference picture selection indication (RPSI) (RFC 4585). // Assumes native bit string stores PictureId (VP8, VP9). class Rpsi : public Psfb { public: - static const uint8_t kFeedbackMessageType = 3; + static constexpr uint8_t kFeedbackMessageType = 3; Rpsi(); ~Rpsi() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithPayloadType(uint8_t payload); - void WithPictureId(uint64_t picture_id); + void SetPayloadType(uint8_t payload); + void SetPictureId(uint64_t picture_id); uint8_t payload_type() const { return payload_type_; } uint64_t picture_id() const { return picture_id_; } @@ -49,8 +48,6 @@ class Rpsi : public Psfb { uint8_t payload_type_; uint64_t picture_id_; size_t block_length_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h index 3354f61..f123aaf 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h @@ -36,7 +36,7 @@ class Rrtr { // Consumes Rrtr::kLength bytes. void Create(uint8_t* buffer) const; - void WithNtp(const NtpTime& ntp) { ntp_ = ntp; } + void SetNtp(NtpTime ntp) { ntp_ = ntp; } NtpTime ntp() const { return ntp_; } diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h index 801aa08..b34e4a0 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h @@ -22,19 +22,19 @@ namespace rtcp { // RFC4585, Section 6.2 class Rtpfb : public RtcpPacket { public: - static const uint8_t kPacketType = 205; + static constexpr uint8_t kPacketType = 205; Rtpfb() : sender_ssrc_(0), media_ssrc_(0) {} - virtual ~Rtpfb() {} + ~Rtpfb() override {} - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } - void To(uint32_t ssrc) { media_ssrc_ = ssrc; } + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void SetMediaSsrc(uint32_t ssrc) { media_ssrc_ = ssrc; } uint32_t sender_ssrc() const { return sender_ssrc_; } uint32_t media_ssrc() const { return media_ssrc_; } protected: - static const size_t kCommonFeedbackLength = 8; + static constexpr size_t kCommonFeedbackLength = 8; void ParseCommonFeedback(const uint8_t* payload); void CreateCommonFeedback(uint8_t* payload) const; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h index 19d5b42..31366ad 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h @@ -15,7 +15,6 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" namespace webrtc { @@ -28,7 +27,7 @@ class Sdes : public RtcpPacket { uint32_t ssrc; std::string cname; }; - static const uint8_t kPacketType = 202; + static constexpr uint8_t kPacketType = 202; Sdes(); ~Sdes() override; @@ -36,7 +35,7 @@ class Sdes : public RtcpPacket { // Parse assumes header is already parsed and validated. bool Parse(const CommonHeader& packet); - bool WithCName(uint32_t ssrc, const std::string& cname); + bool AddCName(uint32_t ssrc, std::string cname); const std::vector& chunks() const { return chunks_; } @@ -53,8 +52,6 @@ class Sdes : public RtcpPacket { std::vector chunks_; size_t block_length_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Sdes); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h index a544017..c62e505 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h @@ -13,7 +13,6 @@ #include -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "webrtc/system_wrappers/include/ntp_time.h" @@ -24,7 +23,7 @@ class CommonHeader; class SenderReport : public RtcpPacket { public: - static const uint8_t kPacketType = 200; + static constexpr uint8_t kPacketType = 200; SenderReport(); ~SenderReport() override {} @@ -32,18 +31,18 @@ class SenderReport : public RtcpPacket { // Parse assumes header is already parsed and validated. bool Parse(const CommonHeader& packet); - void From(uint32_t ssrc) { sender_ssrc_ = ssrc; } - void WithNtp(NtpTime ntp) { ntp_ = ntp; } - void WithRtpTimestamp(uint32_t rtp_timestamp) { + void SetSenderSsrc(uint32_t ssrc) { sender_ssrc_ = ssrc; } + void SetNtp(NtpTime ntp) { ntp_ = ntp; } + void SetRtpTimestamp(uint32_t rtp_timestamp) { rtp_timestamp_ = rtp_timestamp; } - void WithPacketCount(uint32_t packet_count) { + void SetPacketCount(uint32_t packet_count) { sender_packet_count_ = packet_count; } - void WithOctetCount(uint32_t octet_count) { + void SetOctetCount(uint32_t octet_count) { sender_octet_count_ = octet_count; } - bool WithReportBlock(const ReportBlock& block); + bool AddReportBlock(const ReportBlock& block); void ClearReportBlocks() { report_blocks_.clear(); } uint32_t sender_ssrc() const { return sender_ssrc_; } @@ -77,8 +76,6 @@ class SenderReport : public RtcpPacket { uint32_t sender_packet_count_; uint32_t sender_octet_count_; std::vector report_blocks_; - - RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h index 7b6b24f..8d42baf 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h @@ -8,27 +8,25 @@ * be found in the AUTHORS file in the root of the source tree. * */ - #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SLI_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_SLI_H_ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/psfb.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; // Slice loss indication (SLI) (RFC 4585). class Sli : public Psfb { public: - static const uint8_t kFeedbackMessageType = 2; + static constexpr uint8_t kFeedbackMessageType = 2; class Macroblocks { public: - static const size_t kLength = 4; + static constexpr size_t kLength = 4; Macroblocks() : item_(0) {} Macroblocks(uint8_t picture_id, uint16_t first, uint16_t number); ~Macroblocks() {} @@ -45,17 +43,18 @@ class Sli : public Psfb { }; Sli() {} - virtual ~Sli() {} + ~Sli() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithPictureId(uint8_t picture_id, - uint16_t first_macroblock = 0, - uint16_t number_macroblocks = 0x1fff) { - items_.push_back( - Macroblocks(picture_id, first_macroblock, number_macroblocks)); + void AddPictureId(uint8_t picture_id) { + items_.emplace_back(picture_id, 0, 0x1fff); + } + void AddPictureId(uint8_t picture_id, + uint16_t first_macroblock, + uint16_t number_macroblocks) { + items_.emplace_back(picture_id, first_macroblock, number_macroblocks); } const std::vector& macroblocks() const { return items_; } @@ -73,8 +72,6 @@ class Sli : public Psfb { } std::vector items_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Sli); }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h new file mode 100644 index 0000000..013c222 --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/target_bitrate.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TARGET_BITRATE_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TARGET_BITRATE_H_ + +#include + +#include "webrtc/base/basictypes.h" + +namespace webrtc { +namespace rtcp { + +class TargetBitrate { + public: + // TODO(sprang): This block type is just a place holder. We need to get an + // id assigned by IANA. + static constexpr uint8_t kBlockType = 42; + static const size_t kBitrateItemSizeBytes; + + struct BitrateItem { + BitrateItem(); + BitrateItem(uint8_t spatial_layer, + uint8_t temporal_layer, + uint32_t target_bitrate_kbps); + + uint8_t spatial_layer; + uint8_t temporal_layer; + uint32_t target_bitrate_kbps; + }; + + TargetBitrate(); + ~TargetBitrate(); + + void AddTargetBitrate(uint8_t spatial_layer, + uint8_t temporal_layer, + uint32_t target_bitrate_kbps); + + const std::vector& GetTargetBitrates() const; + + bool Parse(const uint8_t* block, uint16_t block_length); + + void Create(uint8_t* buffer) const; + + size_t BlockLength() const; + + private: + std::vector bitrates_; +}; + +} // namespace rtcp +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TARGET_BITRATE_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h index d082f2f..c77bb76 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h @@ -23,17 +23,17 @@ class TmmbItem { static const size_t kLength = 8; TmmbItem() : ssrc_(0), bitrate_bps_(0), packet_overhead_(0) {} - TmmbItem(uint32_t ssrc, uint32_t bitrate_bps, uint16_t overhead); + TmmbItem(uint32_t ssrc, uint64_t bitrate_bps, uint16_t overhead); - void Parse(const uint8_t* buffer); + bool Parse(const uint8_t* buffer); void Create(uint8_t* buffer) const; void set_ssrc(uint32_t ssrc) { ssrc_ = ssrc; } - void set_bitrate_bps(uint32_t bitrate_bps) { bitrate_bps_ = bitrate_bps; } + void set_bitrate_bps(uint64_t bitrate_bps) { bitrate_bps_ = bitrate_bps; } void set_packet_overhead(uint16_t overhead); uint32_t ssrc() const { return ssrc_; } - uint32_t bitrate_bps() const { return bitrate_bps_; } + uint64_t bitrate_bps() const { return bitrate_bps_; } uint16_t packet_overhead() const { return packet_overhead_; } private: @@ -41,7 +41,7 @@ class TmmbItem { uint32_t ssrc_; // Maximum total media bit rate that the media receiver is // currently prepared to accept for this media stream. - uint32_t bitrate_bps_; + uint64_t bitrate_bps_; // Per-packet overhead that the media receiver has observed // for this media stream at its chosen reference protocol layer. uint16_t packet_overhead_; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h index c84d0df..a02aad6 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h @@ -14,30 +14,26 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; + // Temporary Maximum Media Stream Bit Rate Notification (TMMBN). // RFC 5104, Section 4.2.2. class Tmmbn : public Rtpfb { public: - static const uint8_t kFeedbackMessageType = 4; + static constexpr uint8_t kFeedbackMessageType = 4; Tmmbn() {} ~Tmmbn() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) { - WithTmmbr(TmmbItem(ssrc, bitrate_kbps * 1000, overhead)); - } - void WithTmmbr(const TmmbItem& item); + void AddTmmbr(const TmmbItem& item); const std::vector& items() const { return items_; } @@ -54,12 +50,10 @@ class Tmmbn : public Rtpfb { } // Media ssrc is unused, shadow base class setter and getter. - void To(uint32_t ssrc); + void SetMediaSsrc(uint32_t ssrc); uint32_t media_ssrc() const; std::vector items_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbn); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h index 15bfc58..2915c9d 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h @@ -14,27 +14,26 @@ #include #include "webrtc/base/basictypes.h" -#include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" namespace webrtc { namespace rtcp { +class CommonHeader; + // Temporary Maximum Media Stream Bit Rate Request (TMMBR). // RFC 5104, Section 4.2.1. class Tmmbr : public Rtpfb { public: - static const uint8_t kFeedbackMessageType = 3; + static constexpr uint8_t kFeedbackMessageType = 3; Tmmbr() {} ~Tmmbr() override {} // Parse assumes header is already parsed and validated. - bool Parse(const RTCPUtility::RtcpCommonHeader& header, - const uint8_t* payload); // Size of the payload is in the header. + bool Parse(const CommonHeader& packet); - void WithTmmbr(const TmmbItem& item); + void AddTmmbr(const TmmbItem& item); const std::vector& requests() const { return items_; } @@ -50,13 +49,10 @@ class Tmmbr : public Rtpfb { TmmbItem::kLength * items_.size(); } - // Media ssrc is unused, shadow base class setter and getter. - void To(uint32_t ssrc); - uint32_t media_ssrc() const; + // Media ssrc is unused, shadow base class setter. + void SetMediaSsrc(uint32_t ssrc); std::vector items_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbr); }; } // namespace rtcp } // namespace webrtc diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h index 7a74d7f..fa6ef04 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h @@ -11,31 +11,48 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TRANSPORT_FEEDBACK_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_TRANSPORT_FEEDBACK_H_ -#include #include #include -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rtpfb.h" namespace webrtc { namespace rtcp { +class CommonHeader; -class PacketStatusChunk; - -class TransportFeedback : public RtcpPacket { +class TransportFeedback : public Rtpfb { public: + class ReceivedPacket { + public: + ReceivedPacket(uint16_t sequence_number, int16_t delta_ticks) + : sequence_number_(sequence_number), delta_ticks_(delta_ticks) {} + ReceivedPacket(const ReceivedPacket&) = default; + ReceivedPacket& operator=(const ReceivedPacket&) = default; + + uint16_t sequence_number() const { return sequence_number_; } + int16_t delta_ticks() const { return delta_ticks_; } + int32_t delta_us() const { return delta_ticks_ * kDeltaScaleFactor; } + + private: + uint16_t sequence_number_; + int16_t delta_ticks_; + }; + // TODO(sprang): IANA reg? + static constexpr uint8_t kFeedbackMessageType = 15; + // Convert to multiples of 0.25ms. + static constexpr int kDeltaScaleFactor = 250; + // Maximum number of packets (including missing) TransportFeedback can report. + static constexpr size_t kMaxReportedPackets = 0xffff; + TransportFeedback(); - virtual ~TransportFeedback(); + ~TransportFeedback() override; - void WithPacketSenderSsrc(uint32_t ssrc); - void WithMediaSourceSsrc(uint32_t ssrc); - void WithBase(uint16_t base_sequence, // Seq# of first packet in this msg. - int64_t ref_timestamp_us); // Reference timestamp for this msg. - void WithFeedbackSequenceNumber(uint8_t feedback_sequence); + void SetBase(uint16_t base_sequence, // Seq# of first packet in this msg. + int64_t ref_timestamp_us); // Reference timestamp for this msg. + void SetFeedbackSequenceNumber(uint8_t feedback_sequence); // NOTE: This method requires increasing sequence numbers (excepting wraps). - bool WithReceivedPacket(uint16_t sequence_number, int64_t timestamp_us); + bool AddReceivedPacket(uint16_t sequence_number, int64_t timestamp_us); + const std::vector& GetReceivedPackets() const; enum class StatusSymbol { kNotReceived, @@ -53,14 +70,12 @@ class TransportFeedback : public RtcpPacket { // is relative the base time. std::vector GetReceiveDeltasUs() const; - uint32_t GetPacketSenderSsrc() const; - uint32_t GetMediaSourceSsrc() const; - static const int kDeltaScaleFactor = 250; // Convert to multiples of 0.25ms. - static const uint8_t kFeedbackMessageType = 15; // TODO(sprang): IANA reg? - static const uint8_t kPayloadType = 205; // RTPFB, see RFC4585. - + bool Parse(const CommonHeader& packet); static std::unique_ptr ParseFrom(const uint8_t* buffer, size_t length); + // Pre and postcondition for all public methods. Should always return true. + // This function is for tests. + bool IsConsistent() const; protected: bool Create(uint8_t* packet, @@ -71,34 +86,28 @@ class TransportFeedback : public RtcpPacket { size_t BlockLength() const override; private: - static PacketStatusChunk* ParseChunk(const uint8_t* buffer, size_t max_size); - - int64_t Unwrap(uint16_t sequence_number); - bool AddSymbol(StatusSymbol symbol, int64_t seq); - bool Encode(StatusSymbol symbol); - bool HandleRleCandidate(StatusSymbol symbol, - int current_capacity, - int delta_size); - void EmitRemaining(); - void EmitVectorChunk(); - void EmitRunLengthChunk(); - - uint32_t packet_sender_ssrc_; - uint32_t media_source_ssrc_; - int32_t base_seq_; - int64_t base_time_; - uint8_t feedback_seq_; - std::vector status_chunks_; - std::vector receive_deltas_; + // Size in bytes of a delta time in rtcp packet. + // Valid values are 0 (packet wasn't received), 1 or 2. + using DeltaSize = uint8_t; + // Keeps DeltaSizes that can be encoded into single chunk if it is last chunk. + class LastChunk; + + // Reset packet to consistent empty state. + void Clear(); - int64_t last_seq_; - int64_t last_timestamp_; - std::deque symbol_vec_; - uint16_t first_symbol_cardinality_; - bool vec_needs_two_bit_symbols_; - uint32_t size_bytes_; + bool AddDeltaSize(DeltaSize delta_size); + + uint16_t base_seq_no_; + uint16_t num_seq_no_; + int32_t base_time_ticks_; + uint8_t feedback_seq_; - RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedback); + int64_t last_timestamp_us_; + std::vector packets_; + // All but last encoded packet chunks. + std::vector encoded_chunks_; + const std::unique_ptr last_chunk_; + size_t size_bytes_; }; } // namespace rtcp diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h index 9e3e419..62c26fe 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h @@ -35,8 +35,8 @@ class VoipMetric { // Consumes VoipMetric::kLength bytes. void Create(uint8_t* buffer) const; - void To(uint32_t ssrc) { ssrc_ = ssrc; } - void WithVoipMetric(const RTCPVoIPMetric& voip_metric) { + void SetMediaSsrc(uint32_t ssrc) { ssrc_ = ssrc; } + void SetVoipMetric(const RTCPVoIPMetric& voip_metric) { voip_metric_ = voip_metric; } diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h index 28c28cb..c64e95d 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver.h @@ -13,308 +13,261 @@ #include #include +#include #include #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" +#include "webrtc/system_wrappers/include/ntp_time.h" #include "webrtc/typedefs.h" namespace webrtc { -class ModuleRtpRtcpImpl; - -class RTCPReceiver : public TMMBRHelp -{ -public: - RTCPReceiver(Clock* clock, - bool receiver_only, - RtcpPacketTypeCounterObserver* packet_type_counter_observer, - RtcpBandwidthObserver* rtcp_bandwidth_observer, - RtcpIntraFrameObserver* rtcp_intra_frame_observer, - TransportFeedbackObserver* transport_feedback_observer, - ModuleRtpRtcpImpl* owner); - virtual ~RTCPReceiver(); - - int64_t LastReceived(); - int64_t LastReceivedReceiverReport() const; - - void SetSsrcs(uint32_t main_ssrc, - const std::set& registered_ssrcs); - void SetRemoteSSRC(uint32_t ssrc); - uint32_t RemoteSSRC() const; - - int32_t IncomingRTCPPacket( - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation, - RTCPUtility::RTCPParserV2 *rtcpParser); - - void TriggerCallbacksFromRTCPPacket( - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation); - - // get received cname - int32_t CNAME(uint32_t remoteSSRC, char cName[RTCP_CNAME_SIZE]) const; - - // get received NTP - bool NTP(uint32_t* ReceivedNTPsecs, - uint32_t* ReceivedNTPfrac, - uint32_t* RTCPArrivalTimeSecs, - uint32_t* RTCPArrivalTimeFrac, - uint32_t* rtcp_timestamp) const; - - bool LastReceivedXrReferenceTimeInfo(RtcpReceiveTimeInfo* info) const; - - // get rtt - int32_t RTT(uint32_t remoteSSRC, - int64_t* RTT, - int64_t* avgRTT, - int64_t* minRTT, - int64_t* maxRTT) const; - - int32_t SenderInfoReceived(RTCPSenderInfo* senderInfo) const; - - void SetRtcpXrRrtrStatus(bool enable); - bool GetAndResetXrRrRtt(int64_t* rtt_ms); - - // get statistics - int32_t StatisticsReceived( - std::vector* receiveBlocks) const; - - // Returns true if we haven't received an RTCP RR for several RTCP - // intervals, but only triggers true once. - bool RtcpRrTimeout(int64_t rtcp_interval_ms); - - // Returns true if we haven't received an RTCP RR telling the receive side - // has not received RTP packets for too long, i.e. extended highest sequence - // number hasn't increased for several RTCP intervals. The function only - // returns true once until a new RR is received. - bool RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms); - - // Get TMMBR - int32_t TMMBRReceived(uint32_t size, - uint32_t accNumCandidates, - TMMBRSet* candidateSet) const; - - bool UpdateRTCPReceiveInformationTimers(); - - int32_t BoundingSet(bool* tmmbrOwner, TMMBRSet* boundingSetRec); - - int32_t UpdateTMMBR(); - - void RegisterRtcpStatisticsCallback(RtcpStatisticsCallback* callback); - RtcpStatisticsCallback* GetRtcpStatisticsCallback(); - -protected: - RTCPUtility::RTCPCnameInformation* CreateCnameInformation(uint32_t remoteSSRC); - RTCPUtility::RTCPCnameInformation* GetCnameInformation( - uint32_t remoteSSRC) const; - - RTCPHelp::RTCPReceiveInformation* CreateReceiveInformation( - uint32_t remoteSSRC); - RTCPHelp::RTCPReceiveInformation* GetReceiveInformation(uint32_t remoteSSRC); - - void UpdateReceiveInformation( - RTCPHelp::RTCPReceiveInformation& receiveInformation); - - void HandleSenderReceiverReport( - RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleReportBlock( - const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation, - uint32_t remoteSSRC) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleSDES(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleSDESChunk(RTCPUtility::RTCPParserV2& rtcpParser) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleXrHeader(RTCPUtility::RTCPParserV2& parser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleXrReceiveReferenceTime( - RTCPUtility::RTCPParserV2& parser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleXrDlrrReportBlock( - RTCPUtility::RTCPParserV2& parser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleXrDlrrReportBlockItem( - const RTCPUtility::RTCPPacket& packet, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleXRVOIPMetric( - RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleNACK(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleNACKItem(const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleBYE(RTCPUtility::RTCPParserV2& rtcpParser) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandlePLI(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleSLI(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleSLIItem(const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleRPSI(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandlePsfbApp(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleREMBItem(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleIJ(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleIJItem(const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleTMMBR(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleTMMBRItem(RTCPHelp::RTCPReceiveInformation& receiveInfo, - const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation, - uint32_t senderSSRC) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleTMMBN(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleSR_REQ(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleTMMBNItem(RTCPHelp::RTCPReceiveInformation& receiveInfo, - const RTCPUtility::RTCPPacket& rtcpPacket) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleFIR(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleFIRItem(RTCPHelp::RTCPReceiveInformation* receiveInfo, - const RTCPUtility::RTCPPacket& rtcpPacket, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleAPP(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleAPPItem(RTCPUtility::RTCPParserV2& rtcpParser, - RTCPHelp::RTCPPacketInformation& rtcpPacketInformation) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - void HandleTransportFeedback( - RTCPUtility::RTCPParserV2* rtcp_parser, - RTCPHelp::RTCPPacketInformation* rtcp_packet_information) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); +class VideoBitrateAllocationObserver; +namespace rtcp { +class CommonHeader; +class ReportBlock; +class Rrtr; +class TargetBitrate; +class TmmbItem; +} // namespace rtcp + +class RTCPReceiver { + public: + class ModuleRtpRtcp { + public: + virtual void SetTmmbn(std::vector bounding_set) = 0; + virtual void OnRequestSendReport() = 0; + virtual void OnReceivedNack( + const std::vector& nack_sequence_numbers) = 0; + virtual void OnReceivedRtcpReportBlocks( + const ReportBlockList& report_blocks) = 0; + + protected: + virtual ~ModuleRtpRtcp() = default; + }; + + RTCPReceiver(Clock* clock, + bool receiver_only, + RtcpPacketTypeCounterObserver* packet_type_counter_observer, + RtcpBandwidthObserver* rtcp_bandwidth_observer, + RtcpIntraFrameObserver* rtcp_intra_frame_observer, + TransportFeedbackObserver* transport_feedback_observer, + VideoBitrateAllocationObserver* bitrate_allocation_observer, + ModuleRtpRtcp* owner); + virtual ~RTCPReceiver(); + + bool IncomingPacket(const uint8_t* packet, size_t packet_size); + + int64_t LastReceivedReceiverReport() const; + + void SetSsrcs(uint32_t main_ssrc, const std::set& registered_ssrcs); + void SetRemoteSSRC(uint32_t ssrc); + uint32_t RemoteSSRC() const; + + // Get received cname. + int32_t CNAME(uint32_t remote_ssrc, char cname[RTCP_CNAME_SIZE]) const; + + // Get received NTP. + bool NTP(uint32_t* received_ntp_secs, + uint32_t* received_ntp_frac, + uint32_t* rtcp_arrival_time_secs, + uint32_t* rtcp_arrival_time_frac, + uint32_t* rtcp_timestamp) const; + + bool LastReceivedXrReferenceTimeInfo(rtcp::ReceiveTimeInfo* info) const; + + // Get rtt. + int32_t RTT(uint32_t remote_ssrc, + int64_t* last_rtt_ms, + int64_t* avg_rtt_ms, + int64_t* min_rtt_ms, + int64_t* max_rtt_ms) const; + + int32_t SenderInfoReceived(RTCPSenderInfo* sender_info) const; + + void SetRtcpXrRrtrStatus(bool enable); + bool GetAndResetXrRrRtt(int64_t* rtt_ms); + + // Get statistics. + int32_t StatisticsReceived(std::vector* receiveBlocks) const; + + // Returns true if we haven't received an RTCP RR for several RTCP + // intervals, but only triggers true once. + bool RtcpRrTimeout(int64_t rtcp_interval_ms); + + // Returns true if we haven't received an RTCP RR telling the receive side + // has not received RTP packets for too long, i.e. extended highest sequence + // number hasn't increased for several RTCP intervals. The function only + // returns true once until a new RR is received. + bool RtcpRrSequenceNumberTimeout(int64_t rtcp_interval_ms); + + std::vector TmmbrReceived(); + // Return true if new bandwidth should be set. + bool UpdateTmmbrTimers(); + std::vector BoundingSet(bool* tmmbr_owner); + // Set new bandwidth and notify remote clients about it. + void NotifyTmmbrUpdated(); + + void RegisterRtcpStatisticsCallback(RtcpStatisticsCallback* callback); + RtcpStatisticsCallback* GetRtcpStatisticsCallback(); private: - typedef std::map - ReceivedInfoMap; - // RTCP report block information mapped by remote SSRC. - typedef std::map - ReportBlockInfoMap; - // RTCP report block information map mapped by source SSRC. - typedef std::map ReportBlockMap; - - RTCPHelp::RTCPReportBlockInformation* CreateOrGetReportBlockInformation( - uint32_t remote_ssrc, uint32_t source_ssrc) - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - RTCPHelp::RTCPReportBlockInformation* GetReportBlockInformation( - uint32_t remote_ssrc, uint32_t source_ssrc) const - EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver); - - Clock* const _clock; + struct PacketInformation; + struct TmmbrInformation; + struct ReportBlockWithRtt; + struct LastFirStatus; + // RTCP report blocks mapped by remote SSRC. + using ReportBlockInfoMap = std::map; + // RTCP report blocks map mapped by source SSRC. + using ReportBlockMap = std::map; + + bool ParseCompoundPacket(const uint8_t* packet_begin, + const uint8_t* packet_end, + PacketInformation* packet_information); + + void TriggerCallbacksFromRtcpPacket( + const PacketInformation& packet_information); + + TmmbrInformation* FindOrCreateTmmbrInfo(uint32_t remote_ssrc) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + // Update TmmbrInformation (if present) is alive. + void UpdateTmmbrRemoteIsAlive(uint32_t remote_ssrc) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + TmmbrInformation* GetTmmbrInformation(uint32_t remote_ssrc) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleSenderReport(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleReceiverReport(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleReportBlock(const rtcp::ReportBlock& report_block, + PacketInformation* packet_information, + uint32_t remote_ssrc) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleSdes(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleXr(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleXrReceiveReferenceTime(uint32_t sender_ssrc, + const rtcp::Rrtr& rrtr) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleXrDlrrReportBlock(const rtcp::ReceiveTimeInfo& rti) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleXrTargetBitrate(const rtcp::TargetBitrate& target_bitrate, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleNack(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleBye(const rtcp::CommonHeader& rtcp_block) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandlePli(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleSli(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleRpsi(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandlePsfbApp(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleTmmbr(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleTmmbn(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleSrReq(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleFir(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + void HandleTransportFeedback(const rtcp::CommonHeader& rtcp_block, + PacketInformation* packet_information) + EXCLUSIVE_LOCKS_REQUIRED(rtcp_receiver_lock_); + + Clock* const clock_; const bool receiver_only_; - int64_t _lastReceived; - ModuleRtpRtcpImpl& _rtpRtcp; + ModuleRtpRtcp* const rtp_rtcp_; - rtc::CriticalSection _criticalSectionFeedbacks; - RtcpBandwidthObserver* const _cbRtcpBandwidthObserver; - RtcpIntraFrameObserver* const _cbRtcpIntraFrameObserver; - TransportFeedbackObserver* const _cbTransportFeedbackObserver; + rtc::CriticalSection feedbacks_lock_; + RtcpBandwidthObserver* const rtcp_bandwidth_observer_; + RtcpIntraFrameObserver* const rtcp_intra_frame_observer_; + TransportFeedbackObserver* const transport_feedback_observer_; + VideoBitrateAllocationObserver* const bitrate_allocation_observer_; - rtc::CriticalSection _criticalSectionRTCPReceiver; - uint32_t main_ssrc_ GUARDED_BY(_criticalSectionRTCPReceiver); - uint32_t _remoteSSRC GUARDED_BY(_criticalSectionRTCPReceiver); - std::set registered_ssrcs_ GUARDED_BY(_criticalSectionRTCPReceiver); + rtc::CriticalSection rtcp_receiver_lock_; + uint32_t main_ssrc_ GUARDED_BY(rtcp_receiver_lock_); + uint32_t remote_ssrc_ GUARDED_BY(rtcp_receiver_lock_); + std::set registered_ssrcs_ GUARDED_BY(rtcp_receiver_lock_); - // Received send report - RTCPSenderInfo _remoteSenderInfo; - // when did we receive the last send report - uint32_t _lastReceivedSRNTPsecs; - uint32_t _lastReceivedSRNTPfrac; + // Received sender report. + RTCPSenderInfo remote_sender_info_; + // When did we receive the last send report. + NtpTime last_received_sr_ntp_; // Received XR receive time report. - RtcpReceiveTimeInfo _remoteXRReceiveTimeInfo; + rtcp::ReceiveTimeInfo remote_time_info_; // Time when the report was received. - uint32_t _lastReceivedXRNTPsecs; - uint32_t _lastReceivedXRNTPfrac; + NtpTime last_received_xr_ntp_; // Estimated rtt, zero when there is no valid estimate. - bool xr_rrtr_status_ GUARDED_BY(_criticalSectionRTCPReceiver); + bool xr_rrtr_status_ GUARDED_BY(rtcp_receiver_lock_); int64_t xr_rr_rtt_ms_; - // Received report blocks. - ReportBlockMap _receivedReportBlockMap - GUARDED_BY(_criticalSectionRTCPReceiver); - ReceivedInfoMap _receivedInfoMap; - std::map _receivedCnameMap; + int64_t oldest_tmmbr_info_ms_ GUARDED_BY(rtcp_receiver_lock_); + // Mapped by remote ssrc. + std::map tmmbr_infos_ + GUARDED_BY(rtcp_receiver_lock_); + + ReportBlockMap received_report_blocks_ GUARDED_BY(rtcp_receiver_lock_); + std::map last_fir_ GUARDED_BY(rtcp_receiver_lock_); + std::map received_cnames_ + GUARDED_BY(rtcp_receiver_lock_); // The last time we received an RTCP RR. - int64_t _lastReceivedRrMs; + int64_t last_received_rr_ms_ GUARDED_BY(rtcp_receiver_lock_); // The time we last received an RTCP RR telling we have successfully // delivered RTP packet to the remote side. - int64_t _lastIncreasedSequenceNumberMs; + int64_t last_increased_sequence_number_ms_; - RtcpStatisticsCallback* stats_callback_ GUARDED_BY(_criticalSectionFeedbacks); + RtcpStatisticsCallback* stats_callback_ GUARDED_BY(feedbacks_lock_); RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; RtcpPacketTypeCounter packet_type_counter_; - RTCPUtility::NackStats nack_stats_; + RtcpNackStats nack_stats_; size_t num_skipped_packets_; - int64_t last_skipped_packets_warning_; + int64_t last_skipped_packets_warning_ms_; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h deleted file mode 100644 index 40d1220..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_receiver_help.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ - -#include -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" // RTCPReportBlock -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -namespace rtcp { -class TransportFeedback; -} -namespace RTCPHelp -{ - -class RTCPReportBlockInformation -{ -public: - RTCPReportBlockInformation(); - ~RTCPReportBlockInformation(); - - // Statistics - RTCPReportBlock remoteReceiveBlock; - uint32_t remoteMaxJitter; - - // RTT - int64_t RTT; - int64_t minRTT; - int64_t maxRTT; - int64_t avgRTT; - uint32_t numAverageCalcs; -}; - -class RTCPPacketInformation -{ -public: - RTCPPacketInformation(); - ~RTCPPacketInformation(); - - void AddVoIPMetric(const RTCPVoIPMetric* metric); - - void AddApplicationData(const uint8_t* data, - const uint16_t size); - - void AddNACKPacket(const uint16_t packetID); - void ResetNACKPacketIdArray(); - - void AddReportInfo(const RTCPReportBlockInformation& report_block_info); - - uint32_t rtcpPacketTypeFlags; // RTCPPacketTypeFlags bit field - uint32_t remoteSSRC; - - std::list nackSequenceNumbers; - - uint8_t applicationSubType; - uint32_t applicationName; - uint8_t* applicationData; - uint16_t applicationLength; - - ReportBlockList report_blocks; - int64_t rtt; - - uint32_t interArrivalJitter; - - uint8_t sliPictureId; - uint64_t rpsiPictureId; - uint32_t receiverEstimatedMaxBitrate; - - uint32_t ntp_secs; - uint32_t ntp_frac; - uint32_t rtp_timestamp; - - uint32_t xr_originator_ssrc; - bool xr_dlrr_item; - std::unique_ptr VoIPMetric; - - std::unique_ptr transport_feedback_; - -private: - RTC_DISALLOW_COPY_AND_ASSIGN(RTCPPacketInformation); -}; - -class RTCPReceiveInformation -{ -public: - RTCPReceiveInformation(); - ~RTCPReceiveInformation(); - - void VerifyAndAllocateBoundingSet(const uint32_t minimumSize); - void VerifyAndAllocateTMMBRSet(const uint32_t minimumSize); - - void InsertTMMBRItem(const uint32_t senderSSRC, - const RTCPUtility::RTCPPacketRTPFBTMMBRItem& TMMBRItem, - const int64_t currentTimeMS); - - // get - int32_t GetTMMBRSet(const uint32_t sourceIdx, - const uint32_t targetIdx, - TMMBRSet* candidateSet, - const int64_t currentTimeMS); - - int64_t lastTimeReceived; - - // FIR - int32_t lastFIRSequenceNumber; - int64_t lastFIRRequest; - - // TMMBN - TMMBRSet TmmbnBoundingSet; - - // TMMBR - TMMBRSet TmmbrSet; - - bool readyForDelete; -private: - std::vector _tmmbrSetTimeouts; -}; - -} // end namespace RTCPHelp -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_RECEIVER_HELP_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_sender.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_sender.h index 02719aa..76abf63 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_sender.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtcp_sender.h @@ -18,25 +18,26 @@ #include #include +#include "webrtc/api/call/transport.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/base/optional.h" #include "webrtc/base/random.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h" #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_nack_stats.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" -#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h" -#include "webrtc/transport.h" +#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" #include "webrtc/typedefs.h" namespace webrtc { class ModuleRtpRtcpImpl; -class RTCPReceiver; class RtcEventLog; class NACKStringBuilder { @@ -60,7 +61,6 @@ class RTCPSender { FeedbackState(); uint8_t send_payload_type; - uint32_t frequency_hz; uint32_t packets_sent; size_t media_bytes_sent; uint32_t send_bitrate; @@ -70,7 +70,7 @@ class RTCPSender { uint32_t remote_sr; bool has_last_xr_rr; - RtcpReceiveTimeInfo last_xr_rr; + rtcp::ReceiveTimeInfo last_xr_rr; // Used when generating TMMBR. ModuleRtpRtcpImpl* module; @@ -93,7 +93,7 @@ class RTCPSender { int32_t SetNackStatus(bool enable); - void SetStartTimestamp(uint32_t start_timestamp); + void SetTimestampOffset(uint32_t timestamp_offset); void SetLastRtpTime(uint32_t rtp_timestamp, int64_t capture_time_ms); @@ -113,14 +113,12 @@ class RTCPSender { RTCPPacketType packetType, int32_t nackSize = 0, const uint16_t* nackList = 0, - bool repeat = false, uint64_t pictureID = 0); int32_t SendCompoundRTCP(const FeedbackState& feedback_state, const std::set& packetTypes, int32_t nackSize = 0, const uint16_t* nackList = 0, - bool repeat = false, uint64_t pictureID = 0); bool REMB() const; @@ -133,9 +131,9 @@ class RTCPSender { void SetTMMBRStatus(bool enable); - void SetMaxPayloadLength(size_t max_payload_length); + void SetMaxRtpPacketSize(size_t max_packet_size); - void SetTMMBN(const std::vector* boundingSet); + void SetTmmbn(std::vector bounding_set); int32_t SetApplicationSpecificData(uint8_t subType, uint32_t name, @@ -150,14 +148,14 @@ class RTCPSender { void SetCsrcs(const std::vector& csrcs); void SetTargetBitrate(unsigned int target_bitrate); + void SetVideoBitrateAllocation(const BitrateAllocation& bitrate); bool SendFeedbackPacket(const rtcp::TransportFeedback& packet); private: class RtcpContext; // Determine which RTCP messages should be sent and setup flags. - void PrepareReport(const std::set& packetTypes, - const FeedbackState& feedback_state) + void PrepareReport(const FeedbackState& feedback_state) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); bool AddReportBlock(const FeedbackState& feedback_state, @@ -181,7 +179,8 @@ class RTCPSender { EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); std::unique_ptr BuildAPP(const RtcpContext& context) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - std::unique_ptr BuildVoIPMetric(const RtcpContext& context) + std::unique_ptr BuildExtendedReports( + const RtcpContext& context) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); std::unique_ptr BuildBYE(const RtcpContext& context) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); @@ -193,11 +192,6 @@ class RTCPSender { EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); std::unique_ptr BuildNACK(const RtcpContext& context) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - std::unique_ptr BuildReceiverReferenceTime( - const RtcpContext& context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - std::unique_ptr BuildDlrr(const RtcpContext& context) - EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); private: const bool audio_; @@ -215,7 +209,7 @@ class RTCPSender { int64_t next_time_to_send_rtcp_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t start_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t timestamp_offset_ GUARDED_BY(critical_section_rtcp_sender_); uint32_t last_rtp_timestamp_ GUARDED_BY(critical_section_rtcp_sender_); int64_t last_frame_capture_time_ms_ GUARDED_BY(critical_section_rtcp_sender_); uint32_t ssrc_ GUARDED_BY(critical_section_rtcp_sender_); @@ -240,12 +234,11 @@ class RTCPSender { uint32_t remb_bitrate_ GUARDED_BY(critical_section_rtcp_sender_); std::vector remb_ssrcs_ GUARDED_BY(critical_section_rtcp_sender_); - TMMBRHelp tmmbr_help_ GUARDED_BY(critical_section_rtcp_sender_); std::vector tmmbn_to_send_ GUARDED_BY(critical_section_rtcp_sender_); - uint32_t tmmbr_send_ GUARDED_BY(critical_section_rtcp_sender_); + uint32_t tmmbr_send_bps_ GUARDED_BY(critical_section_rtcp_sender_); uint32_t packet_oh_send_ GUARDED_BY(critical_section_rtcp_sender_); - size_t max_payload_length_; + size_t max_packet_size_ GUARDED_BY(critical_section_rtcp_sender_); // APP uint8_t app_sub_type_ GUARDED_BY(critical_section_rtcp_sender_); @@ -259,30 +252,34 @@ class RTCPSender { GUARDED_BY(critical_section_rtcp_sender_); // XR VoIP metric - RTCPVoIPMetric xr_voip_metric_ GUARDED_BY(critical_section_rtcp_sender_); + rtc::Optional xr_voip_metric_ + GUARDED_BY(critical_section_rtcp_sender_); RtcpPacketTypeCounterObserver* const packet_type_counter_observer_; RtcpPacketTypeCounter packet_type_counter_ GUARDED_BY(critical_section_rtcp_sender_); - RTCPUtility::NackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); + RtcpNackStats nack_stats_ GUARDED_BY(critical_section_rtcp_sender_); + + rtc::Optional video_bitrate_allocation_ + GUARDED_BY(critical_section_rtcp_sender_); - void SetFlag(RTCPPacketType type, bool is_volatile) + void SetFlag(uint32_t type, bool is_volatile) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); void SetFlags(const std::set& types, bool is_volatile) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - bool IsFlagPresent(RTCPPacketType type) const + bool IsFlagPresent(uint32_t type) const EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); - bool ConsumeFlag(RTCPPacketType type, bool forced = false) + bool ConsumeFlag(uint32_t type, bool forced = false) EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); bool AllVolatileFlagsConsumed() const EXCLUSIVE_LOCKS_REQUIRED(critical_section_rtcp_sender_); struct ReportFlag { - ReportFlag(RTCPPacketType type, bool is_volatile) + ReportFlag(uint32_t type, bool is_volatile) : type(type), is_volatile(is_volatile) {} bool operator<(const ReportFlag& flag) const { return type < flag.type; } bool operator==(const ReportFlag& flag) const { return type == flag.type; } - const RTCPPacketType type; + const uint32_t type; const bool is_volatile; }; @@ -290,7 +287,8 @@ class RTCPSender { typedef std::unique_ptr (RTCPSender::*BuilderFunc)( const RtcpContext&); - std::map builders_; + // Map from RTCPPacketType to builder. + std::map builders_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTCPSender); }; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtcp_utility.h b/include/webrtc/modules/rtp_rtcp/source/rtcp_utility.h deleted file mode 100644 index 629de4e..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/rtcp_utility.h +++ /dev/null @@ -1,494 +0,0 @@ -/* -* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. -* -* Use of this source code is governed by a BSD-style license -* that can be found in the LICENSE file in the root of the source -* tree. An additional intellectual property rights grant can be found -* in the file PATENTS. All contributing project authors may -* be found in the AUTHORS file in the root of the source tree. -*/ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ - -#include // size_t, ptrdiff_t - -#include - -#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -namespace rtcp { -class RtcpPacket; -} -namespace RTCPUtility { - -class NackStats { - public: - NackStats(); - ~NackStats(); - - // Updates stats with requested sequence number. - // This function should be called for each NACK request to calculate the - // number of unique NACKed RTP packets. - void ReportRequest(uint16_t sequence_number); - - // Gets the number of NACKed RTP packets. - uint32_t requests() const { return requests_; } - - // Gets the number of unique NACKed RTP packets. - uint32_t unique_requests() const { return unique_requests_; } - - private: - uint16_t max_sequence_number_; - uint32_t requests_; - uint32_t unique_requests_; -}; - -uint32_t MidNtp(uint32_t ntp_sec, uint32_t ntp_frac); - -// CNAME -struct RTCPCnameInformation { - char name[RTCP_CNAME_SIZE]; -}; -struct RTCPPacketRR { - uint32_t SenderSSRC; - uint8_t NumberOfReportBlocks; -}; -struct RTCPPacketSR { - uint32_t SenderSSRC; - uint8_t NumberOfReportBlocks; - - // sender info - uint32_t NTPMostSignificant; - uint32_t NTPLeastSignificant; - uint32_t RTPTimestamp; - uint32_t SenderPacketCount; - uint32_t SenderOctetCount; -}; -struct RTCPPacketReportBlockItem { - // report block - uint32_t SSRC; - uint8_t FractionLost; - uint32_t CumulativeNumOfPacketsLost; - uint32_t ExtendedHighestSequenceNumber; - uint32_t Jitter; - uint32_t LastSR; - uint32_t DelayLastSR; -}; -struct RTCPPacketSDESCName { - // RFC3550 - uint32_t SenderSSRC; - char CName[RTCP_CNAME_SIZE]; -}; - -struct RTCPPacketExtendedJitterReportItem { - // RFC 5450 - uint32_t Jitter; -}; - -struct RTCPPacketBYE { - uint32_t SenderSSRC; -}; -struct RTCPPacketXR { - // RFC 3611 - uint32_t OriginatorSSRC; -}; -struct RTCPPacketXRReceiverReferenceTimeItem { - // RFC 3611 4.4 - uint32_t NTPMostSignificant; - uint32_t NTPLeastSignificant; -}; -struct RTCPPacketXRDLRRReportBlockItem { - // RFC 3611 4.5 - uint32_t SSRC; - uint32_t LastRR; - uint32_t DelayLastRR; -}; -struct RTCPPacketXRVOIPMetricItem { - // RFC 3611 4.7 - uint32_t SSRC; - uint8_t lossRate; - uint8_t discardRate; - uint8_t burstDensity; - uint8_t gapDensity; - uint16_t burstDuration; - uint16_t gapDuration; - uint16_t roundTripDelay; - uint16_t endSystemDelay; - uint8_t signalLevel; - uint8_t noiseLevel; - uint8_t RERL; - uint8_t Gmin; - uint8_t Rfactor; - uint8_t extRfactor; - uint8_t MOSLQ; - uint8_t MOSCQ; - uint8_t RXconfig; - uint16_t JBnominal; - uint16_t JBmax; - uint16_t JBabsMax; -}; - -struct RTCPPacketRTPFBNACK { - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketRTPFBNACKItem { - // RFC4585 - uint16_t PacketID; - uint16_t BitMask; -}; - -struct RTCPPacketRTPFBTMMBR { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketRTPFBTMMBRItem { - // RFC5104 - uint32_t SSRC; - uint32_t MaxTotalMediaBitRate; // In Kbit/s - uint32_t MeasuredOverhead; -}; - -struct RTCPPacketRTPFBTMMBN { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketRTPFBTMMBNItem { - // RFC5104 - uint32_t SSRC; // "Owner" - uint32_t MaxTotalMediaBitRate; - uint32_t MeasuredOverhead; -}; - -struct RTCPPacketPSFBFIR { - uint32_t SenderSSRC; - uint32_t MediaSSRC; // zero! -}; -struct RTCPPacketPSFBFIRItem { - // RFC5104 - uint32_t SSRC; - uint8_t CommandSequenceNumber; -}; - -struct RTCPPacketPSFBPLI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; - -struct RTCPPacketPSFBSLI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketPSFBSLIItem { - // RFC4585 - uint16_t FirstMB; - uint16_t NumberOfMB; - uint8_t PictureId; -}; -struct RTCPPacketPSFBRPSI { - // RFC4585 - uint32_t SenderSSRC; - uint32_t MediaSSRC; - uint8_t PayloadType; - uint16_t NumberOfValidBits; - uint8_t NativeBitString[RTCP_RPSI_DATA_SIZE]; -}; -struct RTCPPacketPSFBAPP { - uint32_t SenderSSRC; - uint32_t MediaSSRC; -}; -struct RTCPPacketPSFBREMBItem { - uint32_t BitRate; - uint8_t NumberOfSSRCs; - uint32_t SSRCs[MAX_NUMBER_OF_REMB_FEEDBACK_SSRCS]; -}; -// generic name APP -struct RTCPPacketAPP { - uint8_t SubType; - uint32_t Name; - uint8_t Data[kRtcpAppCode_DATA_SIZE]; - uint16_t Size; -}; - -union RTCPPacket { - RTCPPacketRR RR; - RTCPPacketSR SR; - RTCPPacketReportBlockItem ReportBlockItem; - - RTCPPacketSDESCName CName; - RTCPPacketBYE BYE; - - RTCPPacketExtendedJitterReportItem ExtendedJitterReportItem; - - RTCPPacketRTPFBNACK NACK; - RTCPPacketRTPFBNACKItem NACKItem; - - RTCPPacketPSFBPLI PLI; - RTCPPacketPSFBSLI SLI; - RTCPPacketPSFBSLIItem SLIItem; - RTCPPacketPSFBRPSI RPSI; - RTCPPacketPSFBAPP PSFBAPP; - RTCPPacketPSFBREMBItem REMBItem; - - RTCPPacketRTPFBTMMBR TMMBR; - RTCPPacketRTPFBTMMBRItem TMMBRItem; - RTCPPacketRTPFBTMMBN TMMBN; - RTCPPacketRTPFBTMMBNItem TMMBNItem; - RTCPPacketPSFBFIR FIR; - RTCPPacketPSFBFIRItem FIRItem; - - RTCPPacketXR XR; - RTCPPacketXRReceiverReferenceTimeItem XRReceiverReferenceTimeItem; - RTCPPacketXRDLRRReportBlockItem XRDLRRReportBlockItem; - RTCPPacketXRVOIPMetricItem XRVOIPMetricItem; - - RTCPPacketAPP APP; -}; - -enum class RTCPPacketTypes { - kInvalid, - - // RFC3550 - kRr, - kSr, - kReportBlockItem, - - kSdes, - kSdesChunk, - kBye, - - // RFC5450 - kExtendedIj, - kExtendedIjItem, - - // RFC4585 - kRtpfbNack, - kRtpfbNackItem, - - kPsfbPli, - kPsfbRpsi, - kPsfbRpsiItem, - kPsfbSli, - kPsfbSliItem, - kPsfbApp, - kPsfbRemb, - kPsfbRembItem, - - // RFC5104 - kRtpfbTmmbr, - kRtpfbTmmbrItem, - kRtpfbTmmbn, - kRtpfbTmmbnItem, - kPsfbFir, - kPsfbFirItem, - - // draft-perkins-avt-rapid-rtp-sync - kRtpfbSrReq, - - // RFC 3611 - kXrHeader, - kXrReceiverReferenceTime, - kXrDlrrReportBlock, - kXrDlrrReportBlockItem, - kXrVoipMetric, - - kApp, - kAppItem, - - // draft-holmer-rmcat-transport-wide-cc-extensions - kTransportFeedback, -}; - -struct RTCPRawPacket { - const uint8_t* _ptrPacketBegin; - const uint8_t* _ptrPacketEnd; -}; - -struct RTCPModRawPacket { - uint8_t* _ptrPacketBegin; - uint8_t* _ptrPacketEnd; -}; - -struct RtcpCommonHeader { - static const uint8_t kHeaderSizeBytes = 4; - RtcpCommonHeader() - : version(2), - count_or_format(0), - packet_type(0), - payload_size_bytes(0), - padding_bytes(0) {} - - uint32_t BlockSize() const { - return kHeaderSizeBytes + payload_size_bytes + padding_bytes; - } - - uint8_t version; - uint8_t count_or_format; - uint8_t packet_type; - uint32_t payload_size_bytes; - uint8_t padding_bytes; -}; - -enum RTCPPT : uint8_t { - PT_IJ = 195, - PT_SR = 200, - PT_RR = 201, - PT_SDES = 202, - PT_BYE = 203, - PT_APP = 204, - PT_RTPFB = 205, - PT_PSFB = 206, - PT_XR = 207 -}; - -// Extended report blocks, RFC 3611. -enum RtcpXrBlockType : uint8_t { - kBtReceiverReferenceTime = 4, - kBtDlrr = 5, - kBtVoipMetric = 7 -}; - -bool RtcpParseCommonHeader(const uint8_t* buffer, - size_t size_bytes, - RtcpCommonHeader* parsed_header); - -class RTCPParserV2 { - public: - RTCPParserV2( - const uint8_t* rtcpData, - size_t rtcpDataLength, - bool rtcpReducedSizeEnable); // Set to true, to allow non-compound RTCP! - ~RTCPParserV2(); - - RTCPPacketTypes PacketType() const; - const RTCPPacket& Packet() const; - rtcp::RtcpPacket* ReleaseRtcpPacket(); - const RTCPRawPacket& RawPacket() const; - ptrdiff_t LengthLeft() const; - - bool IsValid() const; - size_t NumSkippedBlocks() const; - - RTCPPacketTypes Begin(); - RTCPPacketTypes Iterate(); - - private: - enum class ParseState { - State_TopLevel, // Top level packet - State_ReportBlockItem, // SR/RR report block - State_SDESChunk, // SDES chunk - State_BYEItem, // BYE item - State_ExtendedJitterItem, // Extended jitter report item - State_RTPFB_NACKItem, // NACK FCI item - State_RTPFB_TMMBRItem, // TMMBR FCI item - State_RTPFB_TMMBNItem, // TMMBN FCI item - State_PSFB_SLIItem, // SLI FCI item - State_PSFB_RPSIItem, // RPSI FCI item - State_PSFB_FIRItem, // FIR FCI item - State_PSFB_AppItem, // Application specific FCI item - State_PSFB_REMBItem, // Application specific REMB item - State_XRItem, - State_XR_DLLRItem, - State_AppItem - }; - - private: - void IterateTopLevel(); - void IterateReportBlockItem(); - void IterateSDESChunk(); - void IterateBYEItem(); - void IterateExtendedJitterItem(); - void IterateNACKItem(); - void IterateTMMBRItem(); - void IterateTMMBNItem(); - void IterateSLIItem(); - void IterateRPSIItem(); - void IterateFIRItem(); - void IteratePsfbAppItem(); - void IteratePsfbREMBItem(); - void IterateAppItem(); - void IterateXrItem(); - void IterateXrDlrrItem(); - - void Validate(); - void EndCurrentBlock(); - - bool ParseRR(); - bool ParseSR(); - bool ParseReportBlockItem(); - - bool ParseSDES(); - bool ParseSDESChunk(); - bool ParseSDESItem(); - - bool ParseBYE(); - bool ParseBYEItem(); - - bool ParseIJ(); - bool ParseIJItem(); - - bool ParseXr(); - bool ParseXrItem(); - bool ParseXrReceiverReferenceTimeItem(int block_length_4bytes); - bool ParseXrDlrr(int block_length_4bytes); - bool ParseXrDlrrItem(); - bool ParseXrVoipMetricItem(int block_length_4bytes); - bool ParseXrUnsupportedBlockType(int block_length_4bytes); - - bool ParseFBCommon(const RtcpCommonHeader& header); - bool ParseNACKItem(); - bool ParseTMMBRItem(); - bool ParseTMMBNItem(); - bool ParseSLIItem(); - bool ParseRPSIItem(); - bool ParseFIRItem(); - bool ParsePsfbAppItem(); - bool ParsePsfbREMBItem(); - - bool ParseAPP(const RtcpCommonHeader& header); - bool ParseAPPItem(); - - private: - const uint8_t* const _ptrRTCPDataBegin; - const bool _RTCPReducedSizeEnable; - const uint8_t* const _ptrRTCPDataEnd; - - bool _validPacket; - const uint8_t* _ptrRTCPData; - const uint8_t* _ptrRTCPBlockEnd; - - ParseState _state; - uint8_t _numberOfBlocks; - size_t num_skipped_blocks_; - - RTCPPacketTypes _packetType; - RTCPPacket _packet; - std::unique_ptr rtcp_packet_; -}; - -class RTCPPacketIterator { - public: - RTCPPacketIterator(uint8_t* rtcpData, size_t rtcpDataLength); - ~RTCPPacketIterator(); - - const RtcpCommonHeader* Begin(); - const RtcpCommonHeader* Iterate(); - const RtcpCommonHeader* Current(); - - private: - uint8_t* const _ptrBegin; - uint8_t* const _ptrEnd; - - uint8_t* _ptrBlock; - - RtcpCommonHeader _header; -}; -} // namespace RTCPUtility -} // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_UTILITY_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format.h index 3519499..3b6004b 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format.h @@ -18,6 +18,7 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { +class RtpPacketToSend; class RtpPacketizer { public: @@ -33,15 +34,11 @@ class RtpPacketizer { const RTPFragmentationHeader* fragmentation) = 0; // Get the next payload with payload header. - // buffer is a pointer to where the output will be written. - // bytes_to_send is an output variable that will contain number of bytes - // written to buffer. The parameter last_packet is true for the last packet of - // the frame, false otherwise (i.e., call the function again to get the - // next packet). - // Returns true on success or false if there was no payload to packetize. - virtual bool NextPacket(uint8_t* buffer, - size_t* bytes_to_send, - bool* last_packet) = 0; + // Write payload and set marker bit of the |packet|. + // The parameter |last_packet| is true for the last packet of the frame, false + // otherwise (i.e., call the function again to get the next packet). + // Returns true on success, false otherwise. + virtual bool NextPacket(RtpPacketToSend* packet, bool* last_packet) = 0; virtual ProtectionType GetProtectionType() = 0; @@ -50,6 +47,10 @@ class RtpPacketizer { virtual std::string ToString() = 0; }; +// TODO(sprang): Update the depacketizer to return a std::unqie_ptr with a copy +// of the parsed payload, rather than just a pointer into the incoming buffer. +// This way we can move some parsing out from the jitter buffer into here, and +// the jitter buffer can just store that pointer rather than doing a copy there. class RtpDepacketizer { public: struct ParsedPayload { diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h index 88258df..fe7b378 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h @@ -11,9 +11,12 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_ +#include +#include #include #include +#include "webrtc/base/buffer.h" #include "webrtc/base/constructormagic.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" @@ -23,7 +26,8 @@ class RtpPacketizerH264 : public RtpPacketizer { public: // Initialize with payload from encoder. // The payload_data must be exactly one encoded H264 frame. - RtpPacketizerH264(FrameType frame_type, size_t max_payload_len); + RtpPacketizerH264(size_t max_payload_len, + H264PacketizationMode packetization_mode); virtual ~RtpPacketizerH264(); @@ -32,15 +36,11 @@ class RtpPacketizerH264 : public RtpPacketizer { const RTPFragmentationHeader* fragmentation) override; // Get the next payload with H264 payload header. - // buffer is a pointer to where the output will be written. - // bytes_to_send is an output variable that will contain number of bytes - // written to buffer. The parameter last_packet is true for the last packet of - // the frame, false otherwise (i.e., call the function again to get the - // next packet). - // Returns true on success or false if there was no payload to packetize. - bool NextPacket(uint8_t* buffer, - size_t* bytes_to_send, - bool* last_packet) override; + // Write payload and set marker bit of the |packet|. + // The parameter |last_packet| is true for the last packet of the frame, false + // otherwise (i.e., call the function again to get the next packet). + // Returns true on success, false otherwise. + bool NextPacket(RtpPacketToSend* rtp_packet, bool* last_packet) override; ProtectionType GetProtectionType() override; @@ -49,42 +49,52 @@ class RtpPacketizerH264 : public RtpPacketizer { std::string ToString() override; private: - struct Packet { - Packet(size_t offset, - size_t size, - bool first_fragment, - bool last_fragment, - bool aggregated, - uint8_t header) - : offset(offset), - size(size), + // Input fragments (NAL units), with an optionally owned temporary buffer, + // used in case the fragment gets modified. + struct Fragment { + Fragment(const uint8_t* buffer, size_t length); + explicit Fragment(const Fragment& fragment); + const uint8_t* buffer = nullptr; + size_t length = 0; + std::unique_ptr tmp_buffer; + }; + + // A packet unit (H264 packet), to be put into an RTP packet: + // If a NAL unit is too large for an RTP packet, this packet unit will + // represent a FU-A packet of a single fragment of the NAL unit. + // If a NAL unit is small enough to fit within a single RTP packet, this + // packet unit may represent a single NAL unit or a STAP-A packet, of which + // there may be multiple in a single RTP packet (if so, aggregated = true). + struct PacketUnit { + PacketUnit(const Fragment& source_fragment, + bool first_fragment, + bool last_fragment, + bool aggregated, + uint8_t header) + : source_fragment(source_fragment), first_fragment(first_fragment), last_fragment(last_fragment), aggregated(aggregated), header(header) {} - size_t offset; - size_t size; + const Fragment source_fragment; bool first_fragment; bool last_fragment; bool aggregated; uint8_t header; }; - typedef std::queue PacketQueue; void GeneratePackets(); - void PacketizeFuA(size_t fragment_offset, size_t fragment_length); - int PacketizeStapA(size_t fragment_index, - size_t fragment_offset, - size_t fragment_length); - void NextAggregatePacket(uint8_t* buffer, size_t* bytes_to_send); - void NextFragmentPacket(uint8_t* buffer, size_t* bytes_to_send); - - const uint8_t* payload_data_; - size_t payload_size_; + void PacketizeFuA(size_t fragment_index); + size_t PacketizeStapA(size_t fragment_index); + void PacketizeSingleNalu(size_t fragment_index); + void NextAggregatePacket(RtpPacketToSend* rtp_packet); + void NextFragmentPacket(RtpPacketToSend* rtp_packet); + const size_t max_payload_len_; - RTPFragmentationHeader fragmentation_; - PacketQueue packets_; + const H264PacketizationMode packetization_mode_; + std::deque input_fragments_; + std::queue packets_; RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerH264); }; @@ -92,11 +102,22 @@ class RtpPacketizerH264 : public RtpPacketizer { // Depacketizer for H264. class RtpDepacketizerH264 : public RtpDepacketizer { public: - virtual ~RtpDepacketizerH264() {} + RtpDepacketizerH264(); + virtual ~RtpDepacketizerH264(); bool Parse(ParsedPayload* parsed_payload, const uint8_t* payload_data, size_t payload_data_length) override; + + private: + bool ParseFuaNalu(RtpDepacketizer::ParsedPayload* parsed_payload, + const uint8_t* payload_data); + bool ProcessStapAOrSingleNalu(RtpDepacketizer::ParsedPayload* parsed_payload, + const uint8_t* payload_data); + + size_t offset_; + size_t length_; + std::unique_ptr modified_buffer_; }; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H264_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h index e72fe31..118166f 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h @@ -36,15 +36,11 @@ class RtpPacketizerGeneric : public RtpPacketizer { const RTPFragmentationHeader* fragmentation) override; // Get the next payload with generic payload header. - // buffer is a pointer to where the output will be written. - // bytes_to_send is an output variable that will contain number of bytes - // written to buffer. The parameter last_packet is true for the last packet of - // the frame, false otherwise (i.e., call the function again to get the - // next packet). - // Returns true on success or false if there was no payload to packetize. - bool NextPacket(uint8_t* buffer, - size_t* bytes_to_send, - bool* last_packet) override; + // Write payload and set marker bit of the |packet|. + // The parameter |last_packet| is true for the last packet of the frame, false + // otherwise (i.e., call the function again to get the next packet). + // Returns true on success, false otherwise. + bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override; ProtectionType GetProtectionType() override; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h index d62ecba..cddf51f 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h @@ -65,19 +65,11 @@ class RtpPacketizerVp8 : public RtpPacketizer { const RTPFragmentationHeader* fragmentation) override; // Get the next payload with VP8 payload header. - // max_payload_len limits the sum length of payload and VP8 payload header. - // buffer is a pointer to where the output will be written. - // bytes_to_send is an output variable that will contain number of bytes - // written to buffer. Parameter last_packet is true for the last packet of - // the frame, false otherwise (i.e., call the function again to get the - // next packet). - // For the kStrict and kAggregate mode: returns the partition index from which - // the first payload byte in the packet is taken, with the first partition - // having index 0; returns negative on error. - // For the kEqualSize mode: returns 0 on success, return negative on error. - bool NextPacket(uint8_t* buffer, - size_t* bytes_to_send, - bool* last_packet) override; + // Write payload and set marker bit of the |packet|. + // The parameter |last_packet| is true for the last packet of the frame, false + // otherwise (i.e., call the function again to get the next packet). + // Returns true on success, false otherwise. + bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override; ProtectionType GetProtectionType() override; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h index 6684768..c71ba71 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h @@ -21,6 +21,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -41,7 +42,10 @@ class RtpFormatVp8TestHelper { uint8_t* payload_data() const { return payload_data_; } size_t payload_size() const { return payload_size_; } RTPFragmentationHeader* fragmentation() const { return fragmentation_; } - size_t buffer_size() const { return buffer_size_; } + size_t buffer_size() const { + static constexpr size_t kVp8PayloadDescriptorMaxSize = 6; + return payload_size_ + kVp8PayloadDescriptorMaxSize; + } void set_sloppy_partitioning(bool value) { sloppy_partitioning_ = value; } private: @@ -49,19 +53,17 @@ class RtpFormatVp8TestHelper { void CheckPictureID(); void CheckTl0PicIdx(); void CheckTIDAndKeyIdx(); - void CheckPayload(size_t payload_end); + void CheckPayload(); void CheckLast(bool last) const; - void CheckPacket(size_t send_bytes, size_t expect_bytes, bool last, - bool frag_start); + void CheckPacket(size_t expect_bytes, bool last, bool frag_start); + RtpPacketToSend packet_; uint8_t* payload_data_; - uint8_t* buffer_; uint8_t* data_ptr_; RTPFragmentationHeader* fragmentation_; const RTPVideoHeaderVP8* hdr_info_; int payload_start_; size_t payload_size_; - size_t buffer_size_; bool sloppy_partitioning_; bool inited_; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h index 3feca43..2036ce4 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h @@ -49,15 +49,11 @@ class RtpPacketizerVp9 : public RtpPacketizer { const RTPFragmentationHeader* fragmentation) override; // Gets the next payload with VP9 payload header. - // |buffer| is a pointer to where the output will be written. - // |bytes_to_send| is an output variable that will contain number of bytes - // written to buffer. - // |last_packet| is true for the last packet of the frame, false otherwise - // (i.e. call the function again to get the next packet). + // Write payload and set marker bit of the |packet|. + // The parameter |last_packet| is true for the last packet of the frame, false + // otherwise (i.e., call the function again to get the next packet). // Returns true on success, false otherwise. - bool NextPacket(uint8_t* buffer, - size_t* bytes_to_send, - bool* last_packet) override; + bool NextPacket(RtpPacketToSend* packet, bool* last_packet) override; typedef struct { size_t payload_start_pos; @@ -76,8 +72,7 @@ class RtpPacketizerVp9 : public RtpPacketizer { // |bytes_to_send| contains the number of written bytes to the buffer. // Returns true on success, false otherwise. bool WriteHeaderAndPayload(const PacketInfo& packet_info, - uint8_t* buffer, - size_t* bytes_to_send) const; + RtpPacketToSend* packet) const; // Writes payload descriptor header to |buffer|. // Returns true on success, false otherwise. diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h b/include/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h index beaf989..1b5a7ab 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h @@ -11,113 +11,69 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ -#include +#include +#include "webrtc/base/array_view.h" +#include "webrtc/base/basictypes.h" +#include "webrtc/base/checks.h" +#include "webrtc/config.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/typedefs.h" namespace webrtc { -const uint16_t kRtpOneByteHeaderExtensionId = 0xBEDE; - -const size_t kRtpOneByteHeaderLength = 4; -const size_t kTransmissionTimeOffsetLength = 4; -const size_t kAudioLevelLength = 2; -const size_t kAbsoluteSendTimeLength = 4; -const size_t kVideoRotationLength = 2; -const size_t kTransportSequenceNumberLength = 3; - -struct HeaderExtension { - explicit HeaderExtension(RTPExtensionType extension_type) - : type(extension_type), length(0), active(true) { - Init(); - } - - HeaderExtension(RTPExtensionType extension_type, bool active) - : type(extension_type), length(0), active(active) { - Init(); - } - - void Init() { - // TODO(solenberg): Create handler classes for header extensions so we can - // get rid of switches like these as well as handling code spread out all - // over. - switch (type) { - case kRtpExtensionTransmissionTimeOffset: - length = kTransmissionTimeOffsetLength; - break; - case kRtpExtensionAudioLevel: - length = kAudioLevelLength; - break; - case kRtpExtensionAbsoluteSendTime: - length = kAbsoluteSendTimeLength; - break; - case kRtpExtensionVideoRotation: - length = kVideoRotationLength; - break; - case kRtpExtensionTransportSequenceNumber: - length = kTransportSequenceNumberLength; - break; - default: - assert(false); - } - } - - const RTPExtensionType type; - uint8_t length; - bool active; -}; - class RtpHeaderExtensionMap { public: static constexpr RTPExtensionType kInvalidType = kRtpExtensionNone; static constexpr uint8_t kInvalidId = 0; - RtpHeaderExtensionMap(); - ~RtpHeaderExtensionMap(); - - void Erase(); - - int32_t Register(const RTPExtensionType type, const uint8_t id); - - // Active is a concept for a registered rtp header extension which doesn't - // take effect yet until being activated. Inactive RTP header extensions do - // not take effect and should not be included in size calculations until they - // are activated. - int32_t RegisterInactive(const RTPExtensionType type, const uint8_t id); - bool SetActive(const RTPExtensionType type, bool active); - int32_t Deregister(const RTPExtensionType type); + RtpHeaderExtensionMap(); + explicit RtpHeaderExtensionMap(rtc::ArrayView extensions); - bool IsRegistered(RTPExtensionType type) const; + template + bool Register(uint8_t id) { + return Register(id, Extension::kId, Extension::kValueSizeBytes, + Extension::kUri); + } + bool RegisterByType(uint8_t id, RTPExtensionType type); + bool RegisterByUri(uint8_t id, const std::string& uri); - int32_t GetType(const uint8_t id, RTPExtensionType* type) const; + bool IsRegistered(RTPExtensionType type) const { + return GetId(type) != kInvalidId; + } // Return kInvalidType if not found. - RTPExtensionType GetType(uint8_t id) const; - - int32_t GetId(const RTPExtensionType type, uint8_t* id) const; + RTPExtensionType GetType(uint8_t id) const { + RTC_DCHECK_GE(id, kMinId); + RTC_DCHECK_LE(id, kMaxId); + return types_[id]; + } // Return kInvalidId if not found. - uint8_t GetId(RTPExtensionType type) const; - - // - // Methods below ignore any inactive rtp header extensions. - // + uint8_t GetId(RTPExtensionType type) const { + RTC_DCHECK_GT(type, kRtpExtensionNone); + RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions); + return ids_[type]; + } size_t GetTotalLengthInBytes() const; - int32_t GetLengthUntilBlockStartInBytes(const RTPExtensionType type) const; - - void GetCopy(RtpHeaderExtensionMap* map) const; - - int32_t Size() const; - - RTPExtensionType First() const; - - RTPExtensionType Next(RTPExtensionType type) const; + // TODO(danilchap): Remove use of the functions below. + int32_t Register(RTPExtensionType type, uint8_t id) { + return RegisterByType(id, type) ? 0 : -1; + } + int32_t Deregister(RTPExtensionType type); private: - int32_t Register(const RTPExtensionType type, const uint8_t id, bool active); - std::map extensionMap_; + static constexpr uint8_t kMinId = 1; + static constexpr uint8_t kMaxId = 14; + bool Register(uint8_t id, + RTPExtensionType type, + size_t value_size, + const char* uri); + + size_t total_values_size_bytes_ = 0; + RTPExtensionType types_[kMaxId + 1]; + uint8_t ids_[kRtpExtensionNumberOfExtensions]; }; + } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSION_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h b/include/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h index cdbf806..ea6f9db 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -10,9 +10,9 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ -#include "webrtc/base/basictypes.h" -#include "webrtc/call.h" -#include "webrtc/common_video/rotation.h" +#include + +#include "webrtc/api/video/video_rotation.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { @@ -21,18 +21,24 @@ class AbsoluteSendTime { public: static constexpr RTPExtensionType kId = kRtpExtensionAbsoluteSendTime; static constexpr uint8_t kValueSizeBytes = 3; - static const char* kName; - static bool IsSupportedFor(MediaType type); - static bool Parse(const uint8_t* data, uint32_t* time_ms); + static constexpr const char* kUri = + "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time"; + + static bool Parse(const uint8_t* data, uint32_t* time_24bits); static bool Write(uint8_t* data, int64_t time_ms); + + static constexpr uint32_t MsTo24Bits(int64_t time_ms) { + return static_cast(((time_ms << 18) + 500) / 1000) & 0x00FFFFFF; + } }; class AudioLevel { public: static constexpr RTPExtensionType kId = kRtpExtensionAudioLevel; static constexpr uint8_t kValueSizeBytes = 1; - static const char* kName; - static bool IsSupportedFor(MediaType type); + static constexpr const char* kUri = + "urn:ietf:params:rtp-hdrext:ssrc-audio-level"; + static bool Parse(const uint8_t* data, bool* voice_activity, uint8_t* audio_level); @@ -43,18 +49,19 @@ class TransmissionOffset { public: static constexpr RTPExtensionType kId = kRtpExtensionTransmissionTimeOffset; static constexpr uint8_t kValueSizeBytes = 3; - static const char* kName; - static bool IsSupportedFor(MediaType type); - static bool Parse(const uint8_t* data, int32_t* time_ms); - static bool Write(uint8_t* data, int64_t time_ms); + static constexpr const char* kUri = "urn:ietf:params:rtp-hdrext:toffset"; + + static bool Parse(const uint8_t* data, int32_t* rtp_time); + static bool Write(uint8_t* data, int32_t rtp_time); }; class TransportSequenceNumber { public: static constexpr RTPExtensionType kId = kRtpExtensionTransportSequenceNumber; static constexpr uint8_t kValueSizeBytes = 2; - static const char* kName; - static bool IsSupportedFor(MediaType type); + static constexpr const char* kUri = + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01"; static bool Parse(const uint8_t* data, uint16_t* value); static bool Write(uint8_t* data, uint16_t value); }; @@ -63,13 +70,31 @@ class VideoOrientation { public: static constexpr RTPExtensionType kId = kRtpExtensionVideoRotation; static constexpr uint8_t kValueSizeBytes = 1; - static const char* kName; - static bool IsSupportedFor(MediaType type); + static constexpr const char* kUri = "urn:3gpp:video-orientation"; + static bool Parse(const uint8_t* data, VideoRotation* value); static bool Write(uint8_t* data, VideoRotation value); static bool Parse(const uint8_t* data, uint8_t* value); static bool Write(uint8_t* data, uint8_t value); }; +class PlayoutDelayLimits { + public: + static constexpr RTPExtensionType kId = kRtpExtensionPlayoutDelay; + static constexpr uint8_t kValueSizeBytes = 3; + static constexpr const char* kUri = + "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay"; + + // Playout delay in milliseconds. A playout delay limit (min or max) + // has 12 bits allocated. This allows a range of 0-4095 values which + // translates to a range of 0-40950 in milliseconds. + static constexpr int kGranularityMs = 10; + // Maximum playout delay value in milliseconds. + static constexpr int kMaxMs = 0xfff * kGranularityMs; // 40950. + + static bool Parse(const uint8_t* data, PlayoutDelay* playout_delay); + static bool Write(uint8_t* data, const PlayoutDelay& playout_delay); +}; + } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_packet.h b/include/webrtc/modules/rtp_rtcp/source/rtp_packet.h index b2687ca..3c02125 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_packet.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_packet.h @@ -12,9 +12,9 @@ #include +#include "webrtc/base/array_view.h" #include "webrtc/base/basictypes.h" -#include "webrtc/base/buffer.h" -#include "webrtc/base/constructormagic.h" +#include "webrtc/base/copyonwritebuffer.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { @@ -31,14 +31,13 @@ class Packet { // Parse and copy given buffer into Packet. bool Parse(const uint8_t* buffer, size_t size); + bool Parse(rtc::ArrayView packet); // Parse and move given buffer into Packet. - bool Parse(rtc::Buffer packet); + bool Parse(rtc::CopyOnWriteBuffer packet); - // Maps parsed extensions to their types to allow use of GetExtension. - // Used after parsing when |extensions| can't be provided until base rtp - // header is parsed. - void IdentifyExtensions(const ExtensionManager* extensions); + // Maps extensions id to their types. + void IdentifyExtensions(const ExtensionManager& extensions); // Header. bool Marker() const; @@ -57,9 +56,10 @@ class Packet { // Payload. size_t payload_size() const; size_t padding_size() const; - const uint8_t* payload() const; + rtc::ArrayView payload() const; // Buffer. + rtc::CopyOnWriteBuffer Buffer() const; size_t capacity() const; size_t size() const; const uint8_t* data() const; @@ -70,7 +70,7 @@ class Packet { void Clear(); // Header setters. - void CopyHeader(const Packet& packet); + void CopyHeaderFrom(const Packet& packet); void SetMarker(bool marker_bit); void SetPayloadType(uint8_t payload_type); void SetSequenceNumber(uint16_t seq_no); @@ -83,6 +83,9 @@ class Packet { void SetCsrcs(const std::vector& csrcs); // Header extensions. + template + bool HasExtension() const; + template bool GetExtension(Values...) const; @@ -102,10 +105,14 @@ class Packet { // packet creating and used if available in Parse function. // Adding and getting extensions will fail until |extensions| is // provided via constructor or IdentifyExtensions function. + Packet(); explicit Packet(const ExtensionManager* extensions); + Packet(const Packet&) = default; Packet(const ExtensionManager* extensions, size_t capacity); virtual ~Packet(); + Packet& operator=(const Packet&) = default; + private: struct ExtensionInfo { ExtensionType type; @@ -137,8 +144,6 @@ class Packet { uint8_t* WriteAt(size_t offset); void WriteAt(size_t offset, uint8_t byte); - const ExtensionManager* extensions_; - // Header. bool marker_; uint8_t payload_type_; @@ -149,14 +154,17 @@ class Packet { size_t payload_offset_; // Match header size with csrcs and extensions. size_t payload_size_; - uint8_t num_extensions_ = 0; ExtensionInfo extension_entries_[kMaxExtensionHeaders]; uint16_t extensions_size_ = 0; // Unaligned. - rtc::Buffer buffer_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Packet); + rtc::CopyOnWriteBuffer buffer_; }; +template +bool Packet::HasExtension() const { + uint16_t offset = 0; + return FindExtension(Extension::kId, Extension::kValueSizeBytes, &offset); +} + template bool Packet::GetExtension(Values... values) const { uint16_t offset = 0; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h index b4d48aa..dc2b35a 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_history.h @@ -6,99 +6,80 @@ * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. - * - * Class for storing RTP packets. */ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ +#include #include +#include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/thread_annotations.h" -#include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/typedefs.h" namespace webrtc { class Clock; +class RtpPacketToSend; -static const size_t kMaxHistoryCapacity = 9600; - -class RTPPacketHistory { +class RtpPacketHistory { public: - explicit RTPPacketHistory(Clock* clock); - ~RTPPacketHistory(); + static constexpr size_t kMaxCapacity = 9600; + explicit RtpPacketHistory(Clock* clock); + ~RtpPacketHistory(); void SetStorePacketsStatus(bool enable, uint16_t number_to_store); - bool StorePackets() const; - // Stores RTP packet. - int32_t PutRTPPacket(const uint8_t* packet, - size_t packet_length, - int64_t capture_time_ms, - StorageType type); - - // Gets stored RTP packet corresponding to the input sequence number. - // The packet is copied to the buffer pointed to by ptr_rtp_packet. - // The rtp_packet_length should show the available buffer size. - // Returns true if packet is found. - // packet_length: returns the copied packet length on success. - // min_elapsed_time_ms: the minimum time that must have elapsed since the last - // time the packet was resent (parameter is ignored if set to zero). - // If the packet is found but the minimum time has not elapsed, no bytes are - // copied. - // stored_time_ms: returns the time when the packet was stored. - bool GetPacketAndSetSendTime(uint16_t sequence_number, - int64_t min_elapsed_time_ms, - bool retransmit, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms); - - bool GetBestFittingPacket(uint8_t* packet, size_t* packet_length, - int64_t* stored_time_ms); - - bool HasRTPPacket(uint16_t sequence_number) const; - - bool SetSent(uint16_t sequence_number); + void PutRtpPacket(std::unique_ptr packet, + StorageType type, + bool sent); + + // Gets stored RTP packet corresponding to the input |sequence number|. + // Returns nullptr if packet is not found. + // |min_elapsed_time_ms| is the minimum time that must have elapsed since + // the last time the packet was resent (parameter is ignored if set to zero). + // If the packet is found but the minimum time has not elapsed, returns + // nullptr. + std::unique_ptr GetPacketAndSetSendTime( + uint16_t sequence_number, + int64_t min_elapsed_time_ms, + bool retransmit); + + std::unique_ptr GetBestFittingPacket( + size_t packet_size) const; + + bool HasRtpPacket(uint16_t sequence_number) const; private: - void GetPacket(int index, - uint8_t* packet, - size_t* packet_length, - int64_t* stored_time_ms) const + struct StoredPacket { + uint16_t sequence_number = 0; + int64_t send_time = 0; + StorageType storage_type = kDontRetransmit; + bool has_been_retransmitted = false; + + std::unique_ptr packet; + }; + + std::unique_ptr GetPacket(int index) const EXCLUSIVE_LOCKS_REQUIRED(critsect_); void Allocate(size_t number_to_store) EXCLUSIVE_LOCKS_REQUIRED(critsect_); void Free() EXCLUSIVE_LOCKS_REQUIRED(critsect_); - void VerifyAndAllocatePacketLength(size_t packet_length, uint32_t start_index) - EXCLUSIVE_LOCKS_REQUIRED(critsect_); - bool FindSeqNum(uint16_t sequence_number, int32_t* index) const + bool FindSeqNum(uint16_t sequence_number, int* index) const EXCLUSIVE_LOCKS_REQUIRED(critsect_); int FindBestFittingPacket(size_t size) const EXCLUSIVE_LOCKS_REQUIRED(critsect_); - private: Clock* clock_; rtc::CriticalSection critsect_; bool store_ GUARDED_BY(critsect_); uint32_t prev_index_ GUARDED_BY(critsect_); - - struct StoredPacket { - StoredPacket(); - uint16_t sequence_number = 0; - int64_t time_ms = 0; - int64_t send_time = 0; - StorageType storage_type = kDontRetransmit; - bool has_been_retransmitted = false; - - uint8_t data[IP_PACKET_SIZE]; - size_t length = 0; - }; std::vector stored_packets_ GUARDED_BY(critsect_); + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtpPacketHistory); }; } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_received.h b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_received.h index e2222b9..95674cf 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_received.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_received.h @@ -18,7 +18,7 @@ namespace webrtc { // Class to hold rtp packet with metadata for receiver side. class RtpPacketReceived : public rtp::Packet { public: - RtpPacketReceived() : Packet(nullptr) {} + RtpPacketReceived() = default; explicit RtpPacketReceived(const ExtensionManager* extensions) : Packet(extensions) {} diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h index ad749ff..f2ddc8a 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h @@ -18,9 +18,11 @@ class RtpPacketToSend : public rtp::Packet { public: explicit RtpPacketToSend(const ExtensionManager* extensions) : Packet(extensions) {} + RtpPacketToSend(const RtpPacketToSend& packet) = default; RtpPacketToSend(const ExtensionManager* extensions, size_t capacity) : Packet(extensions, capacity) {} + RtpPacketToSend& operator=(const RtpPacketToSend& packet) = default; // Time in local time base as close as it can to frame capture time. int64_t capture_time_ms() const { return capture_time_ms_; } void set_capture_time_ms(int64_t time) { capture_time_ms_ = time; } diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h index d5d89ba..5fbf738 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_audio.h @@ -36,16 +36,13 @@ class RTPReceiverAudio : public RTPReceiverStrategy, // Is forwarding of outband telephone events turned on/off? bool TelephoneEventForwardToDecoder() const override; - // Is TelephoneEvent configured with payload type payload_type + // Is TelephoneEvent configured with |payload_type|. bool TelephoneEventPayloadType(const int8_t payload_type) const override; TelephoneEventHandler* GetTelephoneEventHandler() override { return this; } - // Returns true if CNG is configured with payload type payload_type. If so, - // the frequency and cng_payload_type_has_changed are filled in. - bool CNGPayloadType(const int8_t payload_type, - uint32_t* frequency, - bool* cng_payload_type_has_changed); + // Returns true if CNG is configured with |payload_type|. + bool CNGPayloadType(const int8_t payload_type); int32_t ParseRtpPacket(WebRtcRTPHeader* rtp_header, const PayloadUnion& specific_payload, @@ -55,16 +52,11 @@ class RTPReceiverAudio : public RTPReceiverStrategy, int64_t timestamp_ms, bool is_first_packet) override; - int GetPayloadTypeFrequency() const override; - RTPAliveType ProcessDeadOrAlive(uint16_t last_payload_length) const override; bool ShouldReportCsrcChanges(uint8_t payload_type) const override; - int32_t OnNewPayloadTypeCreated( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - int8_t payload_type, - uint32_t frequency) override; + int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) override; int32_t InvokeOnInitializeDecoder( RtpFeedback* callback, @@ -72,16 +64,6 @@ class RTPReceiverAudio : public RTPReceiverStrategy, const char payload_name[RTP_PAYLOAD_NAME_SIZE], const PayloadUnion& specific_payload) const override; - // We do not allow codecs to have multiple payload types for audio, so we - // need to override the default behavior (which is to do nothing). - void PossiblyRemoveExistingPayloadType( - RtpUtility::PayloadTypeMap* payload_type_map, - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - size_t payload_name_length, - uint32_t frequency, - uint8_t channels, - uint32_t rate) const; - // We need to look out for special payload types here and sometimes reset // statistics. In addition we sometimes need to tweak the frequency. void CheckPayloadChanged(int8_t payload_type, @@ -97,8 +79,6 @@ class RTPReceiverAudio : public RTPReceiverStrategy, const AudioPayload& audio_specific, bool is_red); - uint32_t last_received_frequency_; - bool telephone_event_forward_to_decoder_; int8_t telephone_event_payload_type_; std::set telephone_event_reported_; @@ -107,12 +87,6 @@ class RTPReceiverAudio : public RTPReceiverStrategy, int8_t cng_wb_payload_type_; int8_t cng_swb_payload_type_; int8_t cng_fb_payload_type_; - int8_t cng_payload_type_; - - // G722 is special since it use the wrong number of RTP samples in timestamp - // VS. number of samples in the frame - int8_t g722_payload_type_; - bool last_received_g722_; uint8_t num_energy_; uint8_t current_remote_energy_[kRtpCsrcSize]; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h index 1ae1c91..4b55248 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h @@ -33,11 +33,8 @@ class RtpReceiverImpl : public RtpReceiver { virtual ~RtpReceiverImpl(); - int32_t RegisterReceivePayload(const char payload_name[RTP_PAYLOAD_NAME_SIZE], - const int8_t payload_type, - const uint32_t frequency, - const size_t channels, - const uint32_t rate) override; + int32_t RegisterReceivePayload(const CodecInst& audio_codec) override; + int32_t RegisterReceivePayload(const VideoCodec& video_codec) override; int32_t DeRegisterReceivePayload(const int8_t payload_type) override; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h index 663b883..490b4c5 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h @@ -19,6 +19,8 @@ namespace webrtc { +struct CodecInst; + class TelephoneEventHandler; // This strategy deals with media-specific RTP packet processing. @@ -46,9 +48,6 @@ class RTPReceiverStrategy { virtual TelephoneEventHandler* GetTelephoneEventHandler() = 0; - // Retrieves the last known applicable frequency. - virtual int GetPayloadTypeFrequency() const = 0; - // Computes the current dead-or-alive state. virtual RTPAliveType ProcessDeadOrAlive( uint16_t last_payload_length) const = 0; @@ -57,12 +56,9 @@ class RTPReceiverStrategy { // TODO(phoglund): should move out of here along with other payload stuff. virtual bool ShouldReportCsrcChanges(uint8_t payload_type) const = 0; - // Notifies the strategy that we have created a new non-RED payload type in - // the payload registry. - virtual int32_t OnNewPayloadTypeCreated( - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - int8_t payloadType, - uint32_t frequency) = 0; + // Notifies the strategy that we have created a new non-RED audio payload type + // in the payload registry. + virtual int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) = 0; // Invokes the OnInitializeDecoder callback in a media-specific way. virtual int32_t InvokeOnInitializeDecoder( diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h index 486eced..c27fe45 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h @@ -13,7 +13,6 @@ #include "webrtc/base/onetimeevent.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/typedefs.h" @@ -36,16 +35,11 @@ class RTPReceiverVideo : public RTPReceiverStrategy { TelephoneEventHandler* GetTelephoneEventHandler() override { return NULL; } - int GetPayloadTypeFrequency() const override; - RTPAliveType ProcessDeadOrAlive(uint16_t last_payload_length) const override; bool ShouldReportCsrcChanges(uint8_t payload_type) const override; - int32_t OnNewPayloadTypeCreated( - const char payload_name[RTP_PAYLOAD_NAME_SIZE], - int8_t payload_type, - uint32_t frequency) override; + int32_t OnNewPayloadTypeCreated(const CodecInst& audio_codec) override; int32_t InvokeOnInitializeDecoder( RtpFeedback* callback, diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h b/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h index a2cd527..5d05058 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h @@ -23,7 +23,6 @@ enum { RTCP_INTERVAL_VIDEO_MS = 1000 }; enum { RTCP_INTERVAL_AUDIO_MS = 5000 }; enum { RTCP_SEND_BEFORE_KEY_FRAME_MS = 100 }; enum { RTCP_MAX_REPORT_BLOCKS = 31 }; // RFC 3550 page 37 -enum { RTCP_MIN_FRAME_LENGTH_MS = 17 }; enum { kRtcpAppCode_DATA_SIZE = 32 * 4 }; // multiple of 4, this is not a limitation of the size @@ -39,8 +38,6 @@ enum { BW_HISTORY_SIZE = 35 }; #define MIN_AUDIO_BW_MANAGEMENT_BITRATE 6 #define MIN_VIDEO_BW_MANAGEMENT_BITRATE 30 -enum { DTMF_OUTBAND_MAX = 20 }; - enum { RTP_MAX_BURST_SLEEP_TIME = 500 }; enum { RTP_AUDIO_LEVEL_UNIQUE_ID = 0xbede }; enum { RTP_MAX_PACKETS_PER_FRAME = 512 }; // must be multiple of 32 diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 7bbb06e..c15515d 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -11,14 +11,15 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RTCP_IMPL_H_ -#include #include #include #include #include "webrtc/base/criticalsection.h" #include "webrtc/base/gtest_prod_util.h" +#include "webrtc/base/optional.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include "webrtc/modules/rtp_rtcp/source/packet_loss_stats.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_receiver.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h" @@ -26,7 +27,7 @@ namespace webrtc { -class ModuleRtpRtcpImpl : public RtpRtcp { +class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { public: explicit ModuleRtpRtcpImpl(const RtpRtcp::Configuration& configuration); @@ -64,6 +65,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp { int32_t DeregisterSendRtpHeaderExtension(RTPExtensionType type) override; + bool HasBweExtensions() const override; + // Get start timestamp. uint32_t StartTimestamp() const override; @@ -89,8 +92,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp { RTCPSender::FeedbackState GetFeedbackState(); - int CurrentSendFrequencyHz() const; - void SetRtxSendStatus(int mode) override; int RtxSendStatus() const override; @@ -99,6 +100,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp { void SetRtxSendPayloadType(int payload_type, int associated_payload_type) override; + rtc::Optional FlexfecSsrc() const override; + // Sends kRtcpByeCode when going from true to false. int32_t SetSendingStatus(bool sending) override; @@ -111,23 +114,26 @@ class ModuleRtpRtcpImpl : public RtpRtcp { // Used by the codec module to deliver a video or audio frame for // packetization. - int32_t SendOutgoingData(FrameType frame_type, - int8_t payload_type, - uint32_t time_stamp, - int64_t capture_time_ms, - const uint8_t* payload_data, - size_t payload_size, - const RTPFragmentationHeader* fragmentation = NULL, - const RTPVideoHeader* rtp_video_hdr = NULL) override; + bool SendOutgoingData(FrameType frame_type, + int8_t payload_type, + uint32_t time_stamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_video_header, + uint32_t* transport_frame_id_out) override; bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number, int64_t capture_time_ms, - bool retransmission) override; + bool retransmission, + const PacedPacketInfo& pacing_info) override; // Returns the number of padding bytes actually sent, which can be more or // less than |bytes|. - size_t TimeToSendPadding(size_t bytes) override; + size_t TimeToSendPadding(size_t bytes, + const PacedPacketInfo& pacing_info) override; // RTCP part. @@ -202,17 +208,13 @@ class ModuleRtpRtcpImpl : public RtpRtcp { void SetTMMBRStatus(bool enable) override; - void SetTMMBN(const std::vector* bounding_set); - - uint16_t MaxPayloadLength() const override; + void SetTmmbn(std::vector bounding_set) override; - uint16_t MaxDataPayloadLength() const override; + size_t MaxPayloadSize() const override; - int32_t SetMaxTransferUnit(uint16_t size) override; + size_t MaxRtpPacketSize() const override; - int32_t SetTransportOverhead(bool tcp, - bool ipv6, - uint8_t authentication_overhead = 0) override; + void SetMaxRtpPacketSize(size_t max_packet_size) override; // (NACK) Negative acknowledgment part. @@ -254,8 +256,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp { // Audio part. - // Set audio packet size, used to determine when it's time to send a DTMF - // packet in silence (CNG). + // This function is deprecated. It was previously used to determine when it + // was time to send a DTMF packet in silence (CNG). int32_t SetAudioPacketSize(uint16_t packet_size_samples) override; // Send a TelephoneEvent tone using RFC 2833 (4733). @@ -263,12 +265,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp { uint16_t time_ms, uint8_t level) override; - // Set payload type for Redundant Audio Data RFC 2198. - int32_t SetSendREDPayloadType(int8_t payload_type) override; - - // Get payload type for Redundant Audio Data RFC 2198. - int32_t SendREDPayloadType(int8_t* payload_type) const override; - // Store the audio level in d_bov for header-extension-for-audio-level- // indication. int32_t SetAudioLevel(uint8_t level_d_bov) override; @@ -283,26 +279,16 @@ class ModuleRtpRtcpImpl : public RtpRtcp { // Send a request for a keyframe. int32_t RequestKeyFrame() override; - void SetTargetSendBitrate(uint32_t bitrate_bps) override; - - void SetGenericFECStatus(bool enable, - uint8_t payload_type_red, - uint8_t payload_type_fec) override; + void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type) override; - void GenericFECStatus(bool* enable, - uint8_t* payload_type_red, - uint8_t* payload_type_fec) override; - - int32_t SetFecParameters(const FecProtectionParams* delta_params, - const FecProtectionParams* key_params) override; + bool SetFecParameters(const FecProtectionParams& delta_params, + const FecProtectionParams& key_params) override; bool LastReceivedNTP(uint32_t* NTPsecs, uint32_t* NTPfrac, uint32_t* remote_sr) const; - bool LastReceivedXrReferenceTimeInfo(RtcpReceiveTimeInfo* info) const; - - int32_t BoundingSet(bool* tmmbr_owner, TMMBRSet* bounding_set_rec); + std::vector BoundingSet(bool* tmmbr_owner); void BitrateSent(uint32_t* total_rate, uint32_t* video_rate, @@ -317,9 +303,13 @@ class ModuleRtpRtcpImpl : public RtpRtcp { StreamDataCountersCallback* GetSendChannelRtpStatisticsCallback() const override; - void OnReceivedNACK(const std::list& nack_sequence_numbers); + void OnReceivedNack( + const std::vector& nack_sequence_numbers) override; + void OnReceivedRtcpReportBlocks( + const ReportBlockList& report_blocks) override; + void OnRequestSendReport() override; - void OnRequestSendReport(); + void SetVideoBitrateAllocation(const BitrateAllocation& bitrate) override; protected: bool UpdateRTCPReceiveInformationTimers(); @@ -343,7 +333,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp { bool TimeToSendFullNackList(int64_t now) const; const bool audio_; - bool collision_detected_; int64_t last_process_time_; int64_t last_bitrate_process_time_; int64_t last_rtt_process_time_; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/include/webrtc/modules/rtp_rtcp/source/rtp_sender.h index f501d27..64eb679 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -11,110 +11,68 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_H_ -#include #include #include #include #include +#include "webrtc/api/call/transport.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/base/deprecation.h" +#include "webrtc/base/optional.h" #include "webrtc/base/random.h" +#include "webrtc/base/rate_statistics.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" +#include "webrtc/modules/rtp_rtcp/include/flexfec_sender.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/bitrate.h" +#include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h" #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" -#include "webrtc/modules/rtp_rtcp/source/ssrc_database.h" -#include "webrtc/transport.h" namespace webrtc { +class OverheadObserver; +class RateLimiter; +class RtcEventLog; +class RtpPacketToSend; class RTPSenderAudio; class RTPSenderVideo; -class RtcEventLog; - -class RTPSenderInterface { - public: - RTPSenderInterface() {} - virtual ~RTPSenderInterface() {} - - enum CVOMode { - kCVONone, - kCVOInactive, // CVO rtp header extension is registered but haven't - // received any frame with rotation pending. - kCVOActivated, // CVO rtp header extension will be present in the rtp - // packets. - }; - - virtual uint32_t SSRC() const = 0; - virtual uint32_t Timestamp() const = 0; - - virtual int32_t BuildRTPheader(uint8_t* data_buffer, - int8_t payload_type, - bool marker_bit, - uint32_t capture_timestamp, - int64_t capture_time_ms, - bool timestamp_provided = true, - bool inc_sequence_number = true) = 0; - - virtual size_t RTPHeaderLength() const = 0; - // Returns the next sequence number to use for a packet and allocates - // 'packets_to_send' number of sequence numbers. It's important all allocated - // sequence numbers are used in sequence to avoid perceived packet loss. - virtual uint16_t AllocateSequenceNumber(uint16_t packets_to_send) = 0; - virtual uint16_t SequenceNumber() const = 0; - virtual size_t MaxPayloadLength() const = 0; - virtual size_t MaxDataPayloadLength() const = 0; - virtual uint16_t ActualSendBitrateKbit() const = 0; - - virtual int32_t SendToNetwork(uint8_t* data_buffer, - size_t payload_length, - size_t rtp_header_length, - int64_t capture_time_ms, - StorageType storage, - RtpPacketSender::Priority priority) = 0; - - virtual bool UpdateVideoRotation(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - VideoRotation rotation) const = 0; - virtual bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) = 0; - virtual CVOMode ActivateCVORtpHeaderExtension() = 0; -}; -class RTPSender : public RTPSenderInterface { +class RTPSender { public: RTPSender(bool audio, Clock* clock, Transport* transport, RtpPacketSender* paced_sender, + // TODO(brandtr): Remove |flexfec_sender| when that is hooked up + // to PacedSender instead. + FlexfecSender* flexfec_sender, TransportSequenceNumberAllocator* sequence_number_allocator, TransportFeedbackObserver* transport_feedback_callback, BitrateStatisticsObserver* bitrate_callback, FrameCountObserver* frame_count_observer, SendSideDelayObserver* send_side_delay_observer, RtcEventLog* event_log, - SendPacketObserver* send_packet_observer); + SendPacketObserver* send_packet_observer, + RateLimiter* nack_rate_limiter, + OverheadObserver* overhead_observer); - virtual ~RTPSender(); + ~RTPSender(); void ProcessBitrate(); - uint16_t ActualSendBitrateKbit() const override; + uint16_t ActualSendBitrateKbit() const; uint32_t VideoBitrateSent() const; uint32_t FecOverheadRate() const; uint32_t NackOverheadRate() const; - void SetTargetBitrate(uint32_t bitrate); - uint32_t GetTargetBitrate(); - - // Includes size of RTP and FEC headers. - size_t MaxDataPayloadLength() const override; + // Excluding size of RTP and FEC headers. + size_t MaxPayloadSize() const; int32_t RegisterPayload(const char* payload_name, const int8_t payload_type, @@ -128,97 +86,50 @@ class RTPSender : public RTPSenderInterface { int8_t SendPayloadType() const; - int SendPayloadFrequency() const; - - void SetSendingStatus(bool enabled); - void SetSendingMediaStatus(bool enabled); bool SendingMedia() const; void GetDataCounters(StreamDataCounters* rtp_stats, StreamDataCounters* rtx_stats) const; - uint32_t StartTimestamp() const; - void SetStartTimestamp(uint32_t timestamp, bool force); + uint32_t TimestampOffset() const; + void SetTimestampOffset(uint32_t timestamp); - uint32_t GenerateNewSSRC(); void SetSSRC(uint32_t ssrc); - uint16_t SequenceNumber() const override; + uint16_t SequenceNumber() const; void SetSequenceNumber(uint16_t seq); void SetCsrcs(const std::vector& csrcs); - void SetMaxPayloadLength(size_t max_payload_length); + void SetMaxRtpPacketSize(size_t max_packet_size); - int32_t SendOutgoingData(FrameType frame_type, - int8_t payload_type, - uint32_t timestamp, - int64_t capture_time_ms, - const uint8_t* payload_data, - size_t payload_size, - const RTPFragmentationHeader* fragmentation, - const RTPVideoHeader* rtp_hdr = NULL); + bool SendOutgoingData(FrameType frame_type, + int8_t payload_type, + uint32_t timestamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* rtp_header, + uint32_t* transport_frame_id_out); // RTP header extension - int32_t SetTransmissionTimeOffset(int32_t transmission_time_offset); - int32_t SetAbsoluteSendTime(uint32_t absolute_send_time); - void SetVideoRotation(VideoRotation rotation); - int32_t SetTransportSequenceNumber(uint16_t sequence_number); - int32_t RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id); - bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) override; + bool IsRtpHeaderExtensionRegistered(RTPExtensionType type) const; int32_t DeregisterRtpHeaderExtension(RTPExtensionType type); - size_t RtpHeaderExtensionTotalLength() const; - - uint16_t BuildRTPHeaderExtension(uint8_t* data_buffer, bool marker_bit) const; - - uint8_t BuildTransmissionTimeOffsetExtension(uint8_t *data_buffer) const; - uint8_t BuildAudioLevelExtension(uint8_t* data_buffer) const; - uint8_t BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const; - uint8_t BuildVideoRotationExtension(uint8_t* data_buffer) const; - uint8_t BuildTransportSequenceNumberExtension(uint8_t* data_buffer, - uint16_t sequence_number) const; - - // Verifies that the specified extension is registered, and that it is - // present in rtp packet. If extension is not registered kNotRegistered is - // returned. If extension cannot be found in the rtp header, or if it is - // malformed, kError is returned. Otherwise *extension_offset is set to the - // offset of the extension from the beginning of the rtp packet and kOk is - // returned. - enum class ExtensionStatus { - kNotRegistered, - kOk, - kError, - }; - ExtensionStatus VerifyExtension(RTPExtensionType extension_type, - uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - size_t extension_length_bytes, - size_t* extension_offset) const - EXCLUSIVE_LOCKS_REQUIRED(send_critsect_); - - bool UpdateAudioLevel(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - bool is_voiced, - uint8_t dBov) const; - - bool UpdateVideoRotation(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - VideoRotation rotation) const override; - - bool TimeToSendPacket(uint16_t sequence_number, int64_t capture_time_ms, - bool retransmission); - size_t TimeToSendPadding(size_t bytes); + bool TimeToSendPacket(uint32_t ssrc, + uint16_t sequence_number, + int64_t capture_time_ms, + bool retransmission, + const PacedPacketInfo& pacing_info); + size_t TimeToSendPadding(size_t bytes, const PacedPacketInfo& pacing_info); // NACK. int SelectiveRetransmissions() const; int SetSelectiveRetransmissions(uint8_t settings); - void OnReceivedNACK(const std::list& nack_sequence_numbers, + void OnReceivedNack(const std::vector& nack_sequence_numbers, int64_t avg_rtt); void SetStorePacketsStatus(bool enable, uint16_t number_to_store); @@ -227,7 +138,8 @@ class RTPSender : public RTPSenderInterface { int32_t ReSendPacket(uint16_t packet_id, int64_t min_resend_time = 0); - bool ProcessNACKBitRate(uint32_t now); + // Feedback to decide when to stop sending playout delay. + void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks); // RTX. void SetRtxStatus(int mode); @@ -238,69 +150,49 @@ class RTPSender : public RTPSenderInterface { void SetRtxPayloadType(int payload_type, int associated_payload_type); - // Functions wrapping RTPSenderInterface. - int32_t BuildRTPheader(uint8_t* data_buffer, - int8_t payload_type, - bool marker_bit, - uint32_t capture_timestamp, - int64_t capture_time_ms, - const bool timestamp_provided = true, - const bool inc_sequence_number = true) override; - - size_t RTPHeaderLength() const override; - uint16_t AllocateSequenceNumber(uint16_t packets_to_send) override; - size_t MaxPayloadLength() const override; - - // Current timestamp. - uint32_t Timestamp() const override; - uint32_t SSRC() const override; - - int32_t SendToNetwork(uint8_t* data_buffer, - size_t payload_length, - size_t rtp_header_length, - int64_t capture_time_ms, - StorageType storage, - RtpPacketSender::Priority priority) override; + // Create empty packet, fills ssrc, csrcs and reserve place for header + // extensions RtpSender updates before sending. + std::unique_ptr AllocatePacket() const; + // Allocate sequence number for provided packet. + // Save packet's fields to generate padding that doesn't break media stream. + // Return false if sending was turned off. + bool AssignSequenceNumber(RtpPacketToSend* packet); + + size_t RtpHeaderLength() const; + uint16_t AllocateSequenceNumber(uint16_t packets_to_send); + // Including RTP headers. + size_t MaxRtpPacketSize() const; + + uint32_t SSRC() const; + + rtc::Optional FlexfecSsrc() const; + + bool SendToNetwork(std::unique_ptr packet, + StorageType storage, + RtpPacketSender::Priority priority); // Audio. // Send a DTMF tone using RFC 2833 (4733). int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level); - // Set audio packet size, used to determine when it's time to send a DTMF - // packet in silence (CNG). - int32_t SetAudioPacketSize(uint16_t packet_size_samples); + // This function is deprecated. It was previously used to determine when it + // was time to send a DTMF packet in silence (CNG). + RTC_DEPRECATED int32_t SetAudioPacketSize(uint16_t packet_size_samples); // Store the audio level in d_bov for // header-extension-for-audio-level-indication. int32_t SetAudioLevel(uint8_t level_d_bov); - // Set payload type for Redundant Audio Data RFC 2198. - int32_t SetRED(int8_t payload_type); - - // Get payload type for Redundant Audio Data RFC 2198. - int32_t RED(int8_t *payload_type) const; - RtpVideoCodecTypes VideoCodecType() const; uint32_t MaxConfiguredBitrateVideo() const; - // FEC. - void SetGenericFECStatus(bool enable, - uint8_t payload_type_red, - uint8_t payload_type_fec); - - void GenericFECStatus(bool* enable, - uint8_t* payload_type_red, - uint8_t* payload_type_fec) const; + // ULPFEC. + void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type); - int32_t SetFecParameters(const FecProtectionParams *delta_params, - const FecProtectionParams *key_params); - - size_t SendPadData(size_t bytes, - bool timestamp_provided, - uint32_t timestamp, - int64_t capture_time_ms); + bool SetFecParameters(const FecProtectionParams& delta_params, + const FecProtectionParams& key_params); // Called on update of RTP statistics. void RegisterRtpStatisticsCallback(StreamDataCountersCallback* callback); @@ -312,7 +204,6 @@ class RTPSender : public RTPSenderInterface { RtpState GetRtpState() const; void SetRtxRtpState(const RtpState& rtp_state); RtpState GetRtxRtpState() const; - CVOMode ActivateCVORtpHeaderExtension() override; protected: int32_t CheckPayloadType(int8_t payload_type, RtpVideoCodecTypes* video_type); @@ -323,112 +214,48 @@ class RTPSender : public RTPSenderInterface { // time. typedef std::map SendDelayMap; - size_t CreateRtpHeader(uint8_t* header, - int8_t payload_type, - uint32_t ssrc, - bool marker_bit, - uint32_t timestamp, - uint16_t sequence_number, - const std::vector& csrcs) const; - - void UpdateNACKBitRate(uint32_t bytes, int64_t now); + size_t SendPadData(size_t bytes, const PacedPacketInfo& pacing_info); - bool PrepareAndSendPacket(uint8_t* buffer, - size_t length, - int64_t capture_time_ms, + bool PrepareAndSendPacket(std::unique_ptr packet, bool send_over_rtx, - bool is_retransmit); + bool is_retransmit, + const PacedPacketInfo& pacing_info); // Return the number of bytes sent. Note that both of these functions may // return a larger value that their argument. - size_t TrySendRedundantPayloads(size_t bytes); + size_t TrySendRedundantPayloads(size_t bytes, + const PacedPacketInfo& pacing_info); - void BuildPaddingPacket(uint8_t* packet, - size_t header_length, - size_t padding_length); + std::unique_ptr BuildRtxPacket( + const RtpPacketToSend& packet); - void BuildRtxPacket(uint8_t* buffer, size_t* length, - uint8_t* buffer_rtx); - - bool SendPacketToNetwork(const uint8_t* packet, - size_t size, - const PacketOptions& options); + bool SendPacketToNetwork(const RtpPacketToSend& packet, + const PacketOptions& options, + const PacedPacketInfo& pacing_info); void UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms); void UpdateOnSendPacket(int packet_id, int64_t capture_time_ms, uint32_t ssrc); - // Find the byte position of the RTP extension as indicated by |type| in - // |rtp_packet|. Return false if such extension doesn't exist. - bool FindHeaderExtensionPosition(RTPExtensionType type, - const uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - size_t* position) const; - - void UpdateTransmissionTimeOffset(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t time_diff_ms) const; - void UpdateAbsoluteSendTime(uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header, - int64_t now_ms) const; - - bool UpdateTransportSequenceNumber(uint16_t sequence_number, - uint8_t* rtp_packet, - size_t rtp_packet_length, - const RTPHeader& rtp_header) const; - - bool AllocateTransportSequenceNumber(int* packet_id) const; - - void UpdateRtpStats(const uint8_t* buffer, - size_t packet_length, - const RTPHeader& header, + bool UpdateTransportSequenceNumber(RtpPacketToSend* packet, + int* packet_id) const; + + void UpdateRtpStats(const RtpPacketToSend& packet, bool is_rtx, bool is_retransmit); - bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const; + bool IsFecPacket(const RtpPacketToSend& packet) const; - class BitrateAggregator { - public: - explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback); + void AddPacketToTransportFeedback(uint16_t packet_id, + const RtpPacketToSend& packet, + const PacedPacketInfo& pacing_info); - void OnStatsUpdated() const; - - Bitrate::Observer* total_bitrate_observer(); - Bitrate::Observer* retransmit_bitrate_observer(); - void set_ssrc(uint32_t ssrc); - - private: - // We assume that these observers are called on the same thread, which is - // true for RtpSender as they are called on the Process thread. - class BitrateObserver : public Bitrate::Observer { - public: - explicit BitrateObserver(const BitrateAggregator& aggregator); - - // Implements Bitrate::Observer. - void BitrateUpdated(const BitrateStatistics& stats) override; - const BitrateStatistics& statistics() const; - - private: - BitrateStatistics statistics_; - const BitrateAggregator& aggregator_; - }; - - BitrateStatisticsObserver* const callback_; - BitrateObserver total_bitrate_observer_; - BitrateObserver retransmit_bitrate_observer_; - uint32_t ssrc_; - }; + void UpdateRtpOverhead(const RtpPacketToSend& packet); Clock* const clock_; const int64_t clock_delta_ms_; Random random_ GUARDED_BY(send_critsect_); - BitrateAggregator bitrates_; - Bitrate total_bitrate_sent_; - const bool audio_configured_; const std::unique_ptr audio_; const std::unique_ptr video_; @@ -439,27 +266,25 @@ class RTPSender : public RTPSenderInterface { int64_t last_capture_time_ms_sent_; rtc::CriticalSection send_critsect_; - Transport *transport_; + Transport* transport_; bool sending_media_ GUARDED_BY(send_critsect_); - size_t max_payload_length_; + size_t max_packet_size_; int8_t payload_type_ GUARDED_BY(send_critsect_); std::map payload_type_map_; - RtpHeaderExtensionMap rtp_header_extension_map_; - int32_t transmission_time_offset_; - uint32_t absolute_send_time_; - VideoRotation rotation_; - CVOMode cvo_mode_; - uint16_t transport_sequence_number_; + RtpHeaderExtensionMap rtp_header_extension_map_ GUARDED_BY(send_critsect_); - // NACK - uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE]; - size_t nack_byte_count_[NACK_BYTECOUNT_SIZE]; - Bitrate nack_bitrate_; + // Tracks the current request for playout delay limits from application + // and decides whether the current RTP frame should include the playout + // delay extension on header. + PlayoutDelayOracle playout_delay_oracle_; - RTPPacketHistory packet_history_; + RtpPacketHistory packet_history_; + // TODO(brandtr): Remove |flexfec_packet_history_| when the FlexfecSender + // is hooked up to the PacedSender. + RtpPacketHistory flexfec_packet_history_; // Statistics rtc::CriticalSection statistics_crit_; @@ -468,38 +293,39 @@ class RTPSender : public RTPSenderInterface { StreamDataCounters rtp_stats_ GUARDED_BY(statistics_crit_); StreamDataCounters rtx_rtp_stats_ GUARDED_BY(statistics_crit_); StreamDataCountersCallback* rtp_stats_callback_ GUARDED_BY(statistics_crit_); + RateStatistics total_bitrate_sent_ GUARDED_BY(statistics_crit_); + RateStatistics nack_bitrate_sent_ GUARDED_BY(statistics_crit_); FrameCountObserver* const frame_count_observer_; SendSideDelayObserver* const send_side_delay_observer_; RtcEventLog* const event_log_; SendPacketObserver* const send_packet_observer_; + BitrateStatisticsObserver* const bitrate_callback_; // RTP variables - bool start_timestamp_forced_ GUARDED_BY(send_critsect_); - uint32_t start_timestamp_ GUARDED_BY(send_critsect_); - SSRCDatabase* const ssrc_db_; + uint32_t timestamp_offset_ GUARDED_BY(send_critsect_); uint32_t remote_ssrc_ GUARDED_BY(send_critsect_); bool sequence_number_forced_ GUARDED_BY(send_critsect_); uint16_t sequence_number_ GUARDED_BY(send_critsect_); uint16_t sequence_number_rtx_ GUARDED_BY(send_critsect_); - bool ssrc_forced_ GUARDED_BY(send_critsect_); - uint32_t ssrc_ GUARDED_BY(send_critsect_); - uint32_t timestamp_ GUARDED_BY(send_critsect_); + // Must be explicitly set by the application, use of rtc::Optional + // only to keep track of correct use. + rtc::Optional ssrc_ GUARDED_BY(send_critsect_); + uint32_t last_rtp_timestamp_ GUARDED_BY(send_critsect_); int64_t capture_time_ms_ GUARDED_BY(send_critsect_); int64_t last_timestamp_time_ms_ GUARDED_BY(send_critsect_); bool media_has_been_sent_ GUARDED_BY(send_critsect_); bool last_packet_marker_bit_ GUARDED_BY(send_critsect_); std::vector csrcs_ GUARDED_BY(send_critsect_); int rtx_ GUARDED_BY(send_critsect_); - uint32_t ssrc_rtx_ GUARDED_BY(send_critsect_); + rtc::Optional ssrc_rtx_ GUARDED_BY(send_critsect_); // Mapping rtx_payload_type_map_[associated] = rtx. std::map rtx_payload_type_map_ GUARDED_BY(send_critsect_); + size_t rtp_overhead_bytes_per_packet_ GUARDED_BY(send_critsect_); + + RateLimiter* const retransmission_rate_limiter_; + OverheadObserver* overhead_observer_; - // Note: Don't access this variable directly, always go through - // SetTargetBitrateKbps or GetTargetBitrateKbps. Also remember - // that by the time the function returns there is no guarantee - // that the target bitrate is still valid. - rtc::CriticalSection target_bitrate_critsect_; - uint32_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_); + const bool send_side_bwe_with_overhead_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender); }; diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h b/include/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h index 4bc0266..cf79120 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_AUDIO_H_ #include "webrtc/common_types.h" +#include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/onetimeevent.h" #include "webrtc/modules/rtp_rtcp/source/dtmf_queue.h" @@ -21,89 +22,77 @@ #include "webrtc/typedefs.h" namespace webrtc { -class RTPSenderAudio : public DTMFqueue { + +class RTPSenderAudio { public: - RTPSenderAudio(Clock* clock, RTPSender* rtpSender); - virtual ~RTPSenderAudio(); + RTPSenderAudio(Clock* clock, RTPSender* rtp_sender); + ~RTPSenderAudio(); int32_t RegisterAudioPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE], - int8_t payloadType, + int8_t payload_type, uint32_t frequency, size_t channels, uint32_t rate, RtpUtility::Payload** payload); - int32_t SendAudio(FrameType frameType, - int8_t payloadType, - uint32_t captureTimeStamp, - const uint8_t* payloadData, - size_t payloadSize, - const RTPFragmentationHeader* fragmentation); - - // set audio packet size, used to determine when it's time to send a DTMF - // packet in silence (CNG) - int32_t SetAudioPacketSize(uint16_t packetSizeSamples); + bool SendAudio(FrameType frame_type, + int8_t payload_type, + uint32_t capture_timestamp, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation); // Store the audio level in dBov for // header-extension-for-audio-level-indication. // Valid range is [0,100]. Actual value is negative. - int32_t SetAudioLevel(uint8_t level_dBov); + int32_t SetAudioLevel(uint8_t level_dbov); // Send a DTMF tone using RFC 2833 (4733) int32_t SendTelephoneEvent(uint8_t key, uint16_t time_ms, uint8_t level); - int AudioFrequency() const; - - // Set payload type for Redundant Audio Data RFC 2198 - int32_t SetRED(int8_t payloadType); - - // Get payload type for Redundant Audio Data RFC 2198 - int32_t RED(int8_t* payloadType) const; - protected: - int32_t SendTelephoneEventPacket( + bool SendTelephoneEventPacket( bool ended, - int8_t dtmf_payload_type, - uint32_t dtmfTimeStamp, + uint32_t dtmf_timestamp, uint16_t duration, - bool markerBit); // set on first packet in talk burst + bool marker_bit); // set on first packet in talk burst - bool MarkerBit(const FrameType frameType, const int8_t payloadType); + bool MarkerBit(FrameType frame_type, int8_t payload_type); private: - Clock* const _clock; - RTPSender* const _rtpSender; - - rtc::CriticalSection _sendAudioCritsect; - - uint16_t _packetSizeSamples GUARDED_BY(_sendAudioCritsect); - - // DTMF - bool _dtmfEventIsOn; - bool _dtmfEventFirstPacketSent; - int8_t _dtmfPayloadType GUARDED_BY(_sendAudioCritsect); - uint32_t _dtmfTimestamp; - uint8_t _dtmfKey; - uint32_t _dtmfLengthSamples; - uint8_t _dtmfLevel; - int64_t _dtmfTimeLastSent; - uint32_t _dtmfTimestampLastSent; - - int8_t _REDPayloadType GUARDED_BY(_sendAudioCritsect); - - // VAD detection, used for markerbit - bool _inbandVADactive GUARDED_BY(_sendAudioCritsect); - int8_t _cngNBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngWBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngSWBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _cngFBPayloadType GUARDED_BY(_sendAudioCritsect); - int8_t _lastPayloadType GUARDED_BY(_sendAudioCritsect); - - // Audio level indication + Clock* const clock_ = nullptr; + RTPSender* const rtp_sender_ = nullptr; + + rtc::CriticalSection send_audio_critsect_; + + // DTMF. + bool dtmf_event_is_on_ = false; + bool dtmf_event_first_packet_sent_ = false; + int8_t dtmf_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + uint32_t dtmf_payload_freq_ GUARDED_BY(send_audio_critsect_) = 8000; + uint32_t dtmf_timestamp_ = 0; + uint32_t dtmf_length_samples_ = 0; + int64_t dtmf_time_last_sent_ = 0; + uint32_t dtmf_timestamp_last_sent_ = 0; + DtmfQueue::Event dtmf_current_event_; + DtmfQueue dtmf_queue_; + + // VAD detection, used for marker bit. + bool inband_vad_active_ GUARDED_BY(send_audio_critsect_) = false; + int8_t cngnb_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + int8_t cngwb_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + int8_t cngswb_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + int8_t cngfb_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + int8_t last_payload_type_ GUARDED_BY(send_audio_critsect_) = -1; + + // Audio level indication. // (https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/) - uint8_t _audioLevel_dBov GUARDED_BY(_sendAudioCritsect); + uint8_t audio_level_dbov_ GUARDED_BY(send_audio_critsect_) = 0; OneTimeEvent first_packet_sent_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSenderAudio); }; + } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_AUDIO_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h b/include/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h index 8307b83..23a4082 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h @@ -12,63 +12,68 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_ #include +#include +#include #include "webrtc/base/criticalsection.h" #include "webrtc/base/onetimeevent.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/rate_statistics.h" +#include "webrtc/base/sequenced_task_checker.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/common_types.h" +#include "webrtc/modules/rtp_rtcp/include/flexfec_sender.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/modules/rtp_rtcp/source/bitrate.h" -#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" -#include "webrtc/modules/rtp_rtcp/source/producer_fec.h" #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/modules/rtp_rtcp/source/ulpfec_generator.h" #include "webrtc/modules/rtp_rtcp/source/video_codec_information.h" #include "webrtc/typedefs.h" namespace webrtc { +class RtpPacketToSend; class RTPSenderVideo { public: - RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender); + RTPSenderVideo(Clock* clock, + RTPSender* rtpSender, + FlexfecSender* flexfec_sender); virtual ~RTPSenderVideo(); virtual RtpVideoCodecTypes VideoCodecType() const; - size_t FECPacketOverhead() const; + size_t FecPacketOverhead() const { + rtc::CritScope cs(&crit_); + return CalculateFecPacketOverhead(); + } static RtpUtility::Payload* CreateVideoPayload( - const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int8_t payloadType); - - int32_t SendVideo(const RtpVideoCodecTypes videoType, - const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const size_t payloadSize, - const RTPFragmentationHeader* fragmentation, - const RTPVideoHeader* video_header); - - int32_t SendRTPIntraRequest(); + const char payload_name[RTP_PAYLOAD_NAME_SIZE], + int8_t payload_type); + + bool SendVideo(RtpVideoCodecTypes video_type, + FrameType frame_type, + int8_t payload_type, + uint32_t capture_timestamp, + int64_t capture_time_ms, + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation, + const RTPVideoHeader* video_header); void SetVideoCodecType(RtpVideoCodecTypes type); - // FEC - void SetGenericFECStatus(const bool enable, - const uint8_t payloadTypeRED, - const uint8_t payloadTypeFEC); - - void GenericFECStatus(bool* enable, - uint8_t* payloadTypeRED, - uint8_t* payloadTypeFEC) const; + // ULPFEC. + void SetUlpfecConfig(int red_payload_type, int ulpfec_payload_type); + void GetUlpfecConfig(int* red_payload_type, int* ulpfec_payload_type) const; - void SetFecParameters(const FecProtectionParams* delta_params, - const FecProtectionParams* key_params); + // FlexFEC/ULPFEC. + void SetFecParameters(const FecProtectionParams& delta_params, + const FecProtectionParams& key_params); - void ProcessBitrate(); + // FlexFEC. + rtc::Optional FlexfecSsrc() const; uint32_t VideoBitrateSent() const; uint32_t FecOverheadRate() const; @@ -77,47 +82,63 @@ class RTPSenderVideo { void SetSelectiveRetransmissions(uint8_t settings); private: - void SendVideoPacket(uint8_t* dataBuffer, - const size_t payloadLength, - const size_t rtpHeaderLength, - uint16_t seq_num, - const uint32_t capture_timestamp, - int64_t capture_time_ms, + size_t CalculateFecPacketOverhead() const EXCLUSIVE_LOCKS_REQUIRED(crit_); + + void SendVideoPacket(std::unique_ptr packet, StorageType storage); - void SendVideoPacketAsRed(uint8_t* dataBuffer, - const size_t payloadLength, - const size_t rtpHeaderLength, - uint16_t video_seq_num, - const uint32_t capture_timestamp, - int64_t capture_time_ms, - StorageType media_packet_storage, - bool protect); + void SendVideoPacketAsRedMaybeWithUlpfec( + std::unique_ptr media_packet, + StorageType media_packet_storage, + bool protect_media_packet); + + // TODO(brandtr): Remove the FlexFEC functions when FlexfecSender has been + // moved to PacedSender. + void SendVideoPacketWithFlexfec(std::unique_ptr media_packet, + StorageType media_packet_storage, + bool protect_media_packet); + + bool red_enabled() const EXCLUSIVE_LOCKS_REQUIRED(crit_) { + return red_payload_type_ >= 0; + } - RTPSenderInterface& _rtpSender; + bool ulpfec_enabled() const EXCLUSIVE_LOCKS_REQUIRED(crit_) { + return ulpfec_payload_type_ >= 0; + } + + bool flexfec_enabled() const { return flexfec_sender_ != nullptr; } + + RTPSender* const rtp_sender_; + Clock* const clock_; // Should never be held when calling out of this class. - const rtc::CriticalSection crit_; + rtc::CriticalSection crit_; + + RtpVideoCodecTypes video_type_; + int32_t retransmission_settings_ GUARDED_BY(crit_); + VideoRotation last_rotation_ GUARDED_BY(crit_); - RtpVideoCodecTypes _videoType; - int32_t _retransmissionSettings GUARDED_BY(crit_); + // RED/ULPFEC. + int red_payload_type_ GUARDED_BY(crit_); + int ulpfec_payload_type_ GUARDED_BY(crit_); + UlpfecGenerator ulpfec_generator_ GUARDED_BY(crit_); - // FEC - ForwardErrorCorrection fec_; - bool fec_enabled_ GUARDED_BY(crit_); - int8_t red_payload_type_ GUARDED_BY(crit_); - int8_t fec_payload_type_ GUARDED_BY(crit_); + // FlexFEC. + FlexfecSender* const flexfec_sender_; + + // FEC parameters, applicable to either ULPFEC or FlexFEC. FecProtectionParams delta_fec_params_ GUARDED_BY(crit_); FecProtectionParams key_fec_params_ GUARDED_BY(crit_); - ProducerFec producer_fec_ GUARDED_BY(crit_); + rtc::CriticalSection stats_crit_; // Bitrate used for FEC payload, RED headers, RTP headers for FEC packets // and any padding overhead. - Bitrate _fecOverheadRate; - // Bitrate used for video payload and RTP headers - Bitrate _videoBitrate; + RateStatistics fec_bitrate_ GUARDED_BY(stats_crit_); + // Bitrate used for video payload and RTP headers. + RateStatistics video_bitrate_ GUARDED_BY(stats_crit_); OneTimeEvent first_frame_sent_; }; + } // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/include/webrtc/modules/rtp_rtcp/source/rtp_utility.h index 474bc6e..0e1d661 100644 --- a/include/webrtc/modules/rtp_rtcp/source/rtp_utility.h +++ b/include/webrtc/modules/rtp_rtcp/source/rtp_utility.h @@ -36,8 +36,6 @@ struct Payload { PayloadUnion typeSpecific; }; -typedef std::map PayloadTypeMap; - bool StringCompare(const char* str1, const char* str2, const uint32_t length); // Round up to the nearest size that is a multiple of 4. @@ -59,9 +57,6 @@ class RtpHeaderParser { const uint8_t* ptrRTPDataExtensionEnd, const uint8_t* ptr) const; - uint8_t ParsePaddingBytes(const uint8_t* ptrRTPDataExtensionEnd, - const uint8_t* ptr) const; - const uint8_t* const _ptrRTPDataBegin; const uint8_t* const _ptrRTPDataEnd; }; diff --git a/include/webrtc/modules/rtp_rtcp/source/ssrc_database.h b/include/webrtc/modules/rtp_rtcp/source/ssrc_database.h deleted file mode 100644 index 2f6357a..0000000 --- a/include/webrtc/modules/rtp_rtcp/source/ssrc_database.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ - -#include - -#include "webrtc/base/criticalsection.h" -#include "webrtc/base/random.h" -#include "webrtc/base/thread_annotations.h" -#include "webrtc/system_wrappers/include/static_instance.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -// TODO(tommi, holmer): Look into whether we can eliminate locking in this -// class or the class itself completely once voice engine doesn't rely on it. -// At the moment voe_auto_test requires locking, but it's not clear if that's -// an issue with the test code or if it reflects real world usage or if that's -// the best design performance wise. -// If we do decide to keep the class, we should at least get rid of using -// StaticInstance. -class SSRCDatabase { - public: - static SSRCDatabase* GetSSRCDatabase(); - static void ReturnSSRCDatabase(); - - uint32_t CreateSSRC(); - void RegisterSSRC(uint32_t ssrc); - void ReturnSSRC(uint32_t ssrc); - - protected: - SSRCDatabase(); - ~SSRCDatabase(); - - static SSRCDatabase* CreateInstance() { return new SSRCDatabase(); } - - // Friend function to allow the SSRC destructor to be accessed from the - // template class. - friend SSRCDatabase* GetStaticInstance( - CountOperation count_operation); - - private: - rtc::CriticalSection crit_; - Random random_ GUARDED_BY(crit_); - std::set ssrcs_ GUARDED_BY(crit_); - // TODO(tommi): Use a thread checker to ensure the object is created and - // deleted on the same thread. At the moment this isn't possible due to - // voe::ChannelOwner in voice engine. To reproduce, run: - // voe_auto_test --automated --gtest_filter=*MixManyChannelsForStressOpus -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_SSRC_DATABASE_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/time_util.h b/include/webrtc/modules/rtp_rtcp/source/time_util.h index 5a9525a..69bbb0a 100644 --- a/include/webrtc/modules/rtp_rtcp/source/time_util.h +++ b/include/webrtc/modules/rtp_rtcp/source/time_util.h @@ -11,7 +11,8 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ -#include "webrtc/base/basictypes.h" +#include + #include "webrtc/system_wrappers/include/ntp_time.h" namespace webrtc { @@ -21,11 +22,6 @@ inline uint32_t NtpToRtp(NtpTime ntp, uint32_t freq) { uint32_t tmp = (static_cast(ntp.fractions()) * freq) >> 32; return ntp.seconds() * freq + tmp; } -// Return the current RTP timestamp from the NTP timestamp -// returned by the specified clock. -inline uint32_t CurrentRtp(const Clock& clock, uint32_t freq) { - return NtpToRtp(NtpTime(clock), freq); -} // Helper function for compact ntp representation: // RFC 3550, Section 4. Time Format. diff --git a/include/webrtc/modules/rtp_rtcp/source/tmmbr_help.h b/include/webrtc/modules/rtp_rtcp/source/tmmbr_help.h index ffafb14..9bd09c3 100644 --- a/include/webrtc/modules/rtp_rtcp/source/tmmbr_help.h +++ b/include/webrtc/modules/rtp_rtcp/source/tmmbr_help.h @@ -12,77 +12,22 @@ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_ #include -#include "webrtc/base/criticalsection.h" #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h" #include "webrtc/typedefs.h" namespace webrtc { -class TMMBRSet : public std::vector -{ -public: - void VerifyAndAllocateSet(uint32_t minimumSize); - void VerifyAndAllocateSetKeepingData(uint32_t minimumSize); - // Number of valid data items in set. - uint32_t lengthOfSet() const { return size(); } - // Presently allocated max size of set. - uint32_t sizeOfSet() const { return capacity(); } - void clearSet() { clear(); } - uint32_t Tmmbr(int i) const { - return (*this)[i].bitrate_bps() / 1000; - } - uint32_t PacketOH(int i) const { - return (*this)[i].packet_overhead(); - } - uint32_t Ssrc(int i) const { - return (*this)[i].ssrc(); - } - void SetEntry(unsigned int i, - uint32_t tmmbrSet, - uint32_t packetOHSet, - uint32_t ssrcSet); - void AddEntry(uint32_t tmmbrSet, - uint32_t packetOHSet, - uint32_t ssrcSet); +class TMMBRHelp { + public: + static std::vector FindBoundingSet( + std::vector candidates); - // Remove one entry from table, and move all others down. - void RemoveEntry(uint32_t sourceIdx); + static bool IsOwner(const std::vector& bounding, + uint32_t ssrc); - void SwapEntries(uint32_t firstIdx, - uint32_t secondIdx); - - // Set entry data to zero, but keep it in table. - void ClearEntry(uint32_t idx); -}; - -class TMMBRHelp -{ -public: - TMMBRHelp(); - virtual ~TMMBRHelp(); - - TMMBRSet* BoundingSet(); // used for debuging - TMMBRSet* CandidateSet(); - - TMMBRSet* VerifyAndAllocateCandidateSet(const uint32_t minimumSize); - int32_t FindTMMBRBoundingSet(TMMBRSet*& boundingSet); - - bool IsOwner(const uint32_t ssrc, const uint32_t length) const; - - bool CalcMinBitRate(uint32_t* minBitrateKbit) const; - -protected: - TMMBRSet* VerifyAndAllocateBoundingSet(uint32_t minimumSize); - int32_t FindTMMBRBoundingSet(int32_t numCandidates, TMMBRSet& candidateSet); - -private: - rtc::CriticalSection _criticalSection; - TMMBRSet _candidateSet; - TMMBRSet _boundingSet; - - float* _ptrIntersectionBoundingSet; - float* _ptrMaxPRBoundingSet; + static uint64_t CalcMinBitrateBps( + const std::vector& candidates); }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_TMMBR_HELP_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/ulpfec_generator.h b/include/webrtc/modules/rtp_rtcp/source/ulpfec_generator.h new file mode 100644 index 0000000..52e03cd --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/ulpfec_generator.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_GENERATOR_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_GENERATOR_H_ + +#include +#include +#include + +#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" + +namespace webrtc { + +class FlexfecSender; + +class RedPacket { + public: + explicit RedPacket(size_t length); + + void CreateHeader(const uint8_t* rtp_header, + size_t header_length, + int red_payload_type, + int payload_type); + void SetSeqNum(int seq_num); + void AssignPayload(const uint8_t* payload, size_t length); + void ClearMarkerBit(); + uint8_t* data() const; + size_t length() const; + + private: + std::unique_ptr data_; + size_t length_; + size_t header_length_; +}; + +class UlpfecGenerator { + friend class FlexfecSender; + + public: + UlpfecGenerator(); + ~UlpfecGenerator(); + + static std::unique_ptr BuildRedPacket(const uint8_t* data_buffer, + size_t payload_length, + size_t rtp_header_length, + int red_payload_type); + + void SetFecParameters(const FecProtectionParams& params); + + // Adds a media packet to the internal buffer. When enough media packets + // have been added, the FEC packets are generated and stored internally. + // These FEC packets are then obtained by calling GetFecPacketsAsRed(). + int AddRtpPacketAndGenerateFec(const uint8_t* data_buffer, + size_t payload_length, + size_t rtp_header_length); + + // Returns true if there are generated FEC packets available. + bool FecAvailable() const; + + size_t NumAvailableFecPackets() const; + + // Returns the overhead, per packet, for FEC (and possibly RED). + size_t MaxPacketOverhead() const; + + // Returns generated FEC packets with RED headers added. + std::vector> GetUlpfecPacketsAsRed( + int red_payload_type, + int ulpfec_payload_type, + uint16_t first_seq_num, + size_t rtp_header_length); + + private: + explicit UlpfecGenerator(std::unique_ptr fec); + + // Overhead is defined as relative to the number of media packets, and not + // relative to total number of packets. This definition is inherited from the + // protection factor produced by video_coding module and how the FEC + // generation is implemented. + int Overhead() const; + + // Returns true if the excess overhead (actual - target) for the FEC is below + // the amount |kMaxExcessOverhead|. This effects the lower protection level + // cases and low number of media packets/frame. The target overhead is given + // by |params_.fec_rate|, and is only achievable in the limit of large number + // of media packets. + bool ExcessOverheadBelowMax() const; + + // Returns true if the number of added media packets is at least + // |min_num_media_packets_|. This condition tries to capture the effect + // that, for the same amount of protection/overhead, longer codes + // (e.g. (2k,2m) vs (k,m)) are generally more effective at recovering losses. + bool MinimumMediaPacketsReached() const; + + void ResetState(); + + std::unique_ptr fec_; + ForwardErrorCorrection::PacketList media_packets_; + std::list generated_fec_packets_; + int num_protected_frames_; + int min_num_media_packets_; + FecProtectionParams params_; + FecProtectionParams new_params_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_GENERATOR_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h b/include/webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h new file mode 100644 index 0000000..4e771aa --- /dev/null +++ b/include/webrtc/modules/rtp_rtcp/source/ulpfec_header_reader_writer.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_HEADER_READER_WRITER_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_HEADER_READER_WRITER_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" + +namespace webrtc { + +// FEC Level 0 Header, 10 bytes. +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |E|L|P|X| CC |M| PT recovery | SN base | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | TS recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | length recovery | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +// FEC Level 1 Header, 4 bytes (L = 0) or 8 bytes (L = 1). +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Protection Length | mask | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | mask cont. (present only when L = 1) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +class UlpfecHeaderReader : public FecHeaderReader { + public: + UlpfecHeaderReader(); + ~UlpfecHeaderReader() override; + + bool ReadFecHeader( + ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const override; +}; + +class UlpfecHeaderWriter : public FecHeaderWriter { + public: + UlpfecHeaderWriter(); + ~UlpfecHeaderWriter() override; + + size_t MinPacketMaskSize(const uint8_t* packet_mask, + size_t packet_mask_size) const override; + + size_t FecHeaderSize(size_t packet_mask_row_size) const override; + + void FinalizeFecHeader( + uint32_t media_ssrc, // Unused by ULPFEC. + uint16_t seq_num_base, + const uint8_t* packet_mask, + size_t packet_mask_size, + ForwardErrorCorrection::Packet* fec_packet) const override; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_HEADER_READER_WRITER_H_ diff --git a/include/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h b/include/webrtc/modules/rtp_rtcp/source/ulpfec_receiver_impl.h similarity index 64% rename from include/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h rename to include/webrtc/modules/rtp_rtcp/source/ulpfec_receiver_impl.h index 0ebca9b..8dbc8af 100644 --- a/include/webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h +++ b/include/webrtc/modules/rtp_rtcp/source/ulpfec_receiver_impl.h @@ -8,23 +8,23 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_RECEIVER_IMPL_H_ -#define WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_RECEIVER_IMPL_H_ +#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_RECEIVER_IMPL_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_RECEIVER_IMPL_H_ -// This header is included to get the nested declaration of Packet structure. +#include #include "webrtc/base/criticalsection.h" -#include "webrtc/modules/rtp_rtcp/include/fec_receiver.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/ulpfec_receiver.h" #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" #include "webrtc/typedefs.h" namespace webrtc { -class FecReceiverImpl : public FecReceiver { +class UlpfecReceiverImpl : public UlpfecReceiver { public: - explicit FecReceiverImpl(RtpData* callback); - virtual ~FecReceiverImpl(); + explicit UlpfecReceiverImpl(RtpData* callback); + virtual ~UlpfecReceiverImpl(); int32_t AddReceivedRedPacket(const RTPHeader& rtp_header, const uint8_t* incoming_rtp_packet, @@ -38,14 +38,15 @@ class FecReceiverImpl : public FecReceiver { private: rtc::CriticalSection crit_sect_; RtpData* recovered_packet_callback_; - ForwardErrorCorrection* fec_; - // TODO(holmer): In the current version received_packet_list_ is never more + std::unique_ptr fec_; + // TODO(holmer): In the current version |received_packets_| is never more // than one packet, since we process FEC every time a new packet // arrives. We should remove the list. - ForwardErrorCorrection::ReceivedPacketList received_packet_list_; - ForwardErrorCorrection::RecoveredPacketList recovered_packet_list_; + ForwardErrorCorrection::ReceivedPacketList received_packets_; + ForwardErrorCorrection::RecoveredPacketList recovered_packets_; FecPacketCounter packet_counter_; }; + } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FEC_RECEIVER_IMPL_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_ULPFEC_RECEIVER_IMPL_H_ diff --git a/include/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h b/include/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h index 44de00a..7454825 100644 --- a/include/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h +++ b/include/webrtc/modules/rtp_rtcp/test/testAPI/test_api.h @@ -10,7 +10,7 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_TEST_TESTAPI_TEST_API_H_ #define WEBRTC_MODULES_RTP_RTCP_TEST_TESTAPI_TEST_API_H_ -#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/api/call/transport.h" #include "webrtc/common_types.h" #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h" #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" @@ -18,7 +18,7 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "webrtc/transport.h" +#include "webrtc/test/gtest.h" namespace webrtc { @@ -55,7 +55,7 @@ class TestRtpReceiver : public NullRtpData { public: int32_t OnReceivedPayloadData( const uint8_t* payload_data, - const size_t payload_size, + size_t payload_size, const webrtc::WebRtcRTPHeader* rtp_header) override; const uint8_t* payload_data() const { return payload_data_; } diff --git a/include/webrtc/modules/utility/include/audio_frame_operations.h b/include/webrtc/modules/utility/include/audio_frame_operations.h index e12e3e5..4bf73df 100644 --- a/include/webrtc/modules/utility/include/audio_frame_operations.h +++ b/include/webrtc/modules/utility/include/audio_frame_operations.h @@ -10,54 +10,11 @@ #ifndef WEBRTC_MODULES_UTILITY_INCLUDE_AUDIO_FRAME_OPERATIONS_H_ #define WEBRTC_MODULES_UTILITY_INCLUDE_AUDIO_FRAME_OPERATIONS_H_ +// The contents of this file have moved to +// //webrtc/audio/utility. This file is deprecated. -#include "webrtc/typedefs.h" - -namespace webrtc { - -class AudioFrame; - -// TODO(andrew): consolidate this with utility.h and audio_frame_manipulator.h. -// Change reference parameters to pointers. Consider using a namespace rather -// than a class. -class AudioFrameOperations { - public: - // Upmixes mono |src_audio| to stereo |dst_audio|. This is an out-of-place - // operation, meaning src_audio and dst_audio must point to different - // buffers. It is the caller's responsibility to ensure that |dst_audio| is - // sufficiently large. - static void MonoToStereo(const int16_t* src_audio, size_t samples_per_channel, - int16_t* dst_audio); - // |frame.num_channels_| will be updated. This version checks for sufficient - // buffer size and that |num_channels_| is mono. - static int MonoToStereo(AudioFrame* frame); - - // Downmixes stereo |src_audio| to mono |dst_audio|. This is an in-place - // operation, meaning |src_audio| and |dst_audio| may point to the same - // buffer. - static void StereoToMono(const int16_t* src_audio, size_t samples_per_channel, - int16_t* dst_audio); - // |frame.num_channels_| will be updated. This version checks that - // |num_channels_| is stereo. - static int StereoToMono(AudioFrame* frame); - - // Swap the left and right channels of |frame|. Fails silently if |frame| is - // not stereo. - static void SwapStereoChannels(AudioFrame* frame); - - // Conditionally zero out contents of |frame| for implementing audio mute: - // |previous_frame_muted| && |current_frame_muted| - Zero out whole frame. - // |previous_frame_muted| && !|current_frame_muted| - Fade-in at frame start. - // !|previous_frame_muted| && |current_frame_muted| - Fade-out at frame end. - // !|previous_frame_muted| && !|current_frame_muted| - Leave frame untouched. - static void Mute(AudioFrame* frame, bool previous_frame_muted, - bool current_frame_muted); - - static int Scale(float left, float right, AudioFrame& frame); - - static int ScaleWithSat(float scale, AudioFrame& frame); -}; - -} // namespace webrtc +// TODO(aleloi): Remove this file when clients have updated their +// includes. See bugs.webrtc.org/6548. +#include "webrtc/audio/utility/audio_frame_operations.h" #endif // #ifndef WEBRTC_MODULES_UTILITY_INCLUDE_AUDIO_FRAME_OPERATIONS_H_ diff --git a/include/webrtc/modules/utility/include/file_player.h b/include/webrtc/modules/utility/include/file_player.h deleted file mode 100644 index 4ca134a..0000000 --- a/include/webrtc/modules/utility/include/file_player.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_UTILITY_INCLUDE_FILE_PLAYER_H_ -#define WEBRTC_MODULES_UTILITY_INCLUDE_FILE_PLAYER_H_ - -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" - -namespace webrtc { -class FileCallback; - -class FilePlayer -{ -public: - // The largest decoded frame size in samples (60ms with 32kHz sample rate). - enum {MAX_AUDIO_BUFFER_IN_SAMPLES = 60*32}; - enum {MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES*2}; - - // Note: will return NULL for unsupported formats. - static FilePlayer* CreateFilePlayer(const uint32_t instanceID, - const FileFormats fileFormat); - - static void DestroyFilePlayer(FilePlayer* player); - - // Read 10 ms of audio at |frequencyInHz| to |outBuffer|. |lengthInSamples| - // will be set to the number of samples read (not the number of samples per - // channel). - virtual int Get10msAudioFromFile( - int16_t* outBuffer, - size_t& lengthInSamples, - int frequencyInHz) = 0; - - // Register callback for receiving file playing notifications. - virtual int32_t RegisterModuleFileCallback( - FileCallback* callback) = 0; - - // API for playing audio from fileName to channel. - // Note: codecInst is used for pre-encoded files. - virtual int32_t StartPlayingFile( - const char* fileName, - bool loop, - uint32_t startPosition, - float volumeScaling, - uint32_t notification, - uint32_t stopPosition = 0, - const CodecInst* codecInst = NULL) = 0; - - // Note: codecInst is used for pre-encoded files. - virtual int32_t StartPlayingFile( - InStream& sourceStream, - uint32_t startPosition, - float volumeScaling, - uint32_t notification, - uint32_t stopPosition = 0, - const CodecInst* codecInst = NULL) = 0; - - virtual int32_t StopPlayingFile() = 0; - - virtual bool IsPlayingFile() const = 0; - - virtual int32_t GetPlayoutPosition(uint32_t& durationMs) = 0; - - // Set audioCodec to the currently used audio codec. - virtual int32_t AudioCodec(CodecInst& audioCodec) const = 0; - - virtual int32_t Frequency() const = 0; - - // Note: scaleFactor is in the range [0.0 - 2.0] - virtual int32_t SetAudioScaling(float scaleFactor) = 0; - - // Return the time in ms until next video frame should be pulled (by - // calling GetVideoFromFile(..)). - // Note: this API reads one video frame from file. This means that it should - // be called exactly once per GetVideoFromFile(..) API call. - virtual int32_t TimeUntilNextVideoFrame() { return -1;} - - virtual int32_t StartPlayingVideoFile( - const char* /*fileName*/, - bool /*loop*/, - bool /*videoOnly*/) { return -1;} - - virtual int32_t video_codec_info(VideoCodec& /*videoCodec*/) const - {return -1;} - - virtual int32_t GetVideoFromFile(VideoFrame& /*videoFrame*/) { return -1; } - - // Same as GetVideoFromFile(). videoFrame will have the resolution specified - // by the width outWidth and height outHeight in pixels. - virtual int32_t GetVideoFromFile(VideoFrame& /*videoFrame*/, - const uint32_t /*outWidth*/, - const uint32_t /*outHeight*/) { - return -1; - } - -protected: - virtual ~FilePlayer() {} - -}; -} // namespace webrtc -#endif // WEBRTC_MODULES_UTILITY_INCLUDE_FILE_PLAYER_H_ diff --git a/include/webrtc/modules/utility/include/file_recorder.h b/include/webrtc/modules/utility/include/file_recorder.h deleted file mode 100644 index 480a4a9..0000000 --- a/include/webrtc/modules/utility/include/file_recorder.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_UTILITY_INCLUDE_FILE_RECORDER_H_ -#define WEBRTC_MODULES_UTILITY_INCLUDE_FILE_RECORDER_H_ - -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/media_file/media_file_defines.h" -#include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" - -namespace webrtc { - -class FileRecorder -{ -public: - - // Note: will return NULL for unsupported formats. - static FileRecorder* CreateFileRecorder(const uint32_t instanceID, - const FileFormats fileFormat); - - static void DestroyFileRecorder(FileRecorder* recorder); - - virtual int32_t RegisterModuleFileCallback( - FileCallback* callback) = 0; - - virtual FileFormats RecordingFileFormat() const = 0; - - virtual int32_t StartRecordingAudioFile( - const char* fileName, - const CodecInst& codecInst, - uint32_t notification) = 0; - - virtual int32_t StartRecordingAudioFile( - OutStream& destStream, - const CodecInst& codecInst, - uint32_t notification) = 0; - - // Stop recording. - // Note: this API is for both audio and video. - virtual int32_t StopRecording() = 0; - - // Return true if recording. - // Note: this API is for both audio and video. - virtual bool IsRecording() const = 0; - - virtual int32_t codec_info(CodecInst& codecInst) const = 0; - - // Write frame to file. Frame should contain 10ms of un-ecoded audio data. - virtual int32_t RecordAudioToFile( - const AudioFrame& frame) = 0; - - // Open/create the file specified by fileName for writing audio/video data - // (relative path is allowed). audioCodecInst specifies the encoding of the - // audio data. videoCodecInst specifies the encoding of the video data. - // Only video data will be recorded if videoOnly is true. amrFormat - // specifies the amr/amrwb storage format. - // Note: the file format is AVI. - virtual int32_t StartRecordingVideoFile( - const char* fileName, - const CodecInst& audioCodecInst, - const VideoCodec& videoCodecInst, - bool videoOnly = false) = 0; - - // Record the video frame in videoFrame to AVI file. - virtual int32_t RecordVideoToFile(const VideoFrame& videoFrame) = 0; - -protected: - virtual ~FileRecorder() {} - -}; -} // namespace webrtc -#endif // WEBRTC_MODULES_UTILITY_INCLUDE_FILE_RECORDER_H_ diff --git a/include/webrtc/modules/utility/include/helpers_ios.h b/include/webrtc/modules/utility/include/helpers_ios.h deleted file mode 100644 index 1b692f1..0000000 --- a/include/webrtc/modules/utility/include/helpers_ios.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_UTILITY_INCLUDE_HELPERS_IOS_H_ -#define WEBRTC_MODULES_UTILITY_INCLUDE_HELPERS_IOS_H_ - -#if defined(WEBRTC_IOS) - -#include - -namespace webrtc { -namespace ios { - -bool CheckAndLogError(BOOL success, NSError* error); - -std::string StdStringFromNSString(NSString* nsString); - -// Return thread ID as a string. -std::string GetThreadId(); - -// Return thread ID as string suitable for debug logging. -std::string GetThreadInfo(); - -// Returns [NSThread currentThread] description as string. -// Example: {number = 1, name = main} -std::string GetCurrentThreadDescription(); - -std::string GetAudioSessionCategory(); - -// Returns the current name of the operating system. -std::string GetSystemName(); - -// Returns the current version of the operating system as a string. -std::string GetSystemVersionAsString(); - -// Returns the version of the operating system in double representation. -// Uses a cached value of the system version. -double GetSystemVersion(); - -// Returns the device type. -// Examples: ”iPhone” and ”iPod touch”. -std::string GetDeviceType(); - -// Returns a more detailed device name. -// Examples: "iPhone 5s (GSM)" and "iPhone 6 Plus". -std::string GetDeviceName(); - -// Returns the name of the process. Does not uniquely identify the process. -std::string GetProcessName(); - -// Returns the identifier of the process (often called process ID). -int GetProcessID(); - -// Returns a string containing the version of the operating system on which the -// process is executing. The string is string is human readable, localized, and -// is appropriate for displaying to the user. -std::string GetOSVersionString(); - -// Returns the number of processing cores available on the device. -int GetProcessorCount(); - -// Indicates whether Low Power Mode is enabled on the iOS device. -bool GetLowPowerModeEnabled(); - -} // namespace ios -} // namespace webrtc - -#endif // defined(WEBRTC_IOS) - -#endif // WEBRTC_MODULES_UTILITY_INCLUDE_HELPERS_IOS_H_ diff --git a/include/webrtc/modules/utility/include/jvm_android.h b/include/webrtc/modules/utility/include/jvm_android.h index 574c977..51a0bd8 100644 --- a/include/webrtc/modules/utility/include/jvm_android.h +++ b/include/webrtc/modules/utility/include/jvm_android.h @@ -64,6 +64,7 @@ class JavaClass { jmethodID GetMethodId(const char* name, const char* signature); jmethodID GetStaticMethodId(const char* name, const char* signature); jobject CallStaticObjectMethod(jmethodID methodID, ...); + jint CallStaticIntMethod(jmethodID methodID, ...); protected: JNIEnv* const jni_; diff --git a/include/webrtc/modules/utility/include/mock/mock_process_thread.h b/include/webrtc/modules/utility/include/mock/mock_process_thread.h index 621fcee..6625a74 100644 --- a/include/webrtc/modules/utility/include/mock/mock_process_thread.h +++ b/include/webrtc/modules/utility/include/mock/mock_process_thread.h @@ -15,7 +15,7 @@ #include "webrtc/modules/utility/include/process_thread.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" namespace webrtc { @@ -28,14 +28,14 @@ class MockProcessThread : public ProcessThread { MOCK_METHOD0(Start, void()); MOCK_METHOD0(Stop, void()); MOCK_METHOD1(WakeUp, void(Module* module)); - MOCK_METHOD1(PostTask, void(ProcessTask* task)); + MOCK_METHOD1(PostTask, void(rtc::QueuedTask* task)); MOCK_METHOD1(RegisterModule, void(Module* module)); MOCK_METHOD1(DeRegisterModule, void(Module* module)); // MOCK_METHOD1 gets confused with mocking this method, so we work around it // by overriding the method from the interface and forwarding the call to a // mocked, simpler method. - void PostTask(std::unique_ptr task) /* override */ { + void PostTask(std::unique_ptr task) /*override*/ { PostTask(task.get()); } }; diff --git a/include/webrtc/modules/utility/include/process_thread.h b/include/webrtc/modules/utility/include/process_thread.h index f6913ea..8524a51 100644 --- a/include/webrtc/modules/utility/include/process_thread.h +++ b/include/webrtc/modules/utility/include/process_thread.h @@ -15,17 +15,23 @@ #include "webrtc/typedefs.h" +#if defined(WEBRTC_WIN) +// Due to a bug in the std::unique_ptr implementation that ships with MSVS, +// we need the full definition of QueuedTask, on Windows. +#include "webrtc/base/task_queue.h" +#else +namespace rtc { +class QueuedTask; +} +#endif + namespace webrtc { class Module; -class ProcessTask { - public: - ProcessTask() {} - virtual ~ProcessTask() {} - - virtual void Run() = 0; -}; - +// TODO(tommi): ProcessThread probably doesn't need to be a virtual +// interface. There exists one override besides ProcessThreadImpl, +// MockProcessThread, but when looking at how it is used, it seems +// a nullptr might suffice (or simply an actual ProcessThread instance). class ProcessThread { public: virtual ~ProcessThread(); @@ -51,7 +57,7 @@ class ProcessThread { // construction thread of the ProcessThread instance, if the task did not // get a chance to run (e.g. posting the task while shutting down or when // the thread never runs). - virtual void PostTask(std::unique_ptr task) = 0; + virtual void PostTask(std::unique_ptr task) = 0; // Adds a module that will start to receive callbacks on the worker thread. // Can be called from any thread. diff --git a/include/webrtc/modules/utility/source/coder.h b/include/webrtc/modules/utility/source/coder.h deleted file mode 100644 index 5f44190..0000000 --- a/include/webrtc/modules/utility/source/coder.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_UTILITY_SOURCE_CODER_H_ -#define WEBRTC_MODULES_UTILITY_SOURCE_CODER_H_ - -#include - -#include "webrtc/common_types.h" -#include "webrtc/modules/audio_coding/acm2/codec_manager.h" -#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" -#include "webrtc/modules/audio_coding/include/audio_coding_module.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -class AudioFrame; - -class AudioCoder : public AudioPacketizationCallback { - public: - AudioCoder(uint32_t instance_id); - ~AudioCoder(); - - int32_t SetEncodeCodec(const CodecInst& codec_inst); - - int32_t SetDecodeCodec(const CodecInst& codec_inst); - - int32_t Decode(AudioFrame& decoded_audio, - uint32_t samp_freq_hz, - const int8_t* incoming_payload, - size_t payload_length); - - int32_t PlayoutData(AudioFrame& decoded_audio, uint16_t& samp_freq_hz); - - int32_t Encode(const AudioFrame& audio, - int8_t* encoded_data, - size_t& encoded_length_in_bytes); - - protected: - int32_t SendData(FrameType frame_type, - uint8_t payload_type, - uint32_t time_stamp, - const uint8_t* payload_data, - size_t payload_size, - const RTPFragmentationHeader* fragmentation) override; - - private: - std::unique_ptr acm_; - acm2::CodecManager codec_manager_; - acm2::RentACodec rent_a_codec_; - - CodecInst receive_codec_; - - uint32_t encode_timestamp_; - int8_t* encoded_data_; - size_t encoded_length_in_bytes_; - - uint32_t decode_timestamp_; -}; -} // namespace webrtc - -#endif // WEBRTC_MODULES_UTILITY_SOURCE_CODER_H_ diff --git a/include/webrtc/modules/utility/source/file_player_impl.h b/include/webrtc/modules/utility/source/file_player_impl.h deleted file mode 100644 index 62887da..0000000 --- a/include/webrtc/modules/utility/source/file_player_impl.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_UTILITY_SOURCE_FILE_PLAYER_IMPL_H_ -#define WEBRTC_MODULES_UTILITY_SOURCE_FILE_PLAYER_IMPL_H_ - -#include "webrtc/common_audio/resampler/include/resampler.h" -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/modules/media_file/media_file.h" -#include "webrtc/modules/media_file/media_file_defines.h" -#include "webrtc/modules/utility/include/file_player.h" -#include "webrtc/modules/utility/source/coder.h" -#include "webrtc/system_wrappers/include/critical_section_wrapper.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -class FilePlayerImpl : public FilePlayer -{ -public: - FilePlayerImpl(uint32_t instanceID, FileFormats fileFormat); - ~FilePlayerImpl(); - - virtual int Get10msAudioFromFile( - int16_t* outBuffer, - size_t& lengthInSamples, - int frequencyInHz); - virtual int32_t RegisterModuleFileCallback(FileCallback* callback); - virtual int32_t StartPlayingFile( - const char* fileName, - bool loop, - uint32_t startPosition, - float volumeScaling, - uint32_t notification, - uint32_t stopPosition = 0, - const CodecInst* codecInst = NULL); - virtual int32_t StartPlayingFile( - InStream& sourceStream, - uint32_t startPosition, - float volumeScaling, - uint32_t notification, - uint32_t stopPosition = 0, - const CodecInst* codecInst = NULL); - virtual int32_t StopPlayingFile(); - virtual bool IsPlayingFile() const; - virtual int32_t GetPlayoutPosition(uint32_t& durationMs); - virtual int32_t AudioCodec(CodecInst& audioCodec) const; - virtual int32_t Frequency() const; - virtual int32_t SetAudioScaling(float scaleFactor); - -protected: - int32_t SetUpAudioDecoder(); - - uint32_t _instanceID; - const FileFormats _fileFormat; - MediaFile& _fileModule; - - uint32_t _decodedLengthInMS; - -private: - AudioCoder _audioDecoder; - - CodecInst _codec; - int32_t _numberOf10MsPerFrame; - int32_t _numberOf10MsInDecoder; - - Resampler _resampler; - float _scaling; -}; -} // namespace webrtc -#endif // WEBRTC_MODULES_UTILITY_SOURCE_FILE_PLAYER_IMPL_H_ diff --git a/include/webrtc/modules/utility/source/file_recorder_impl.h b/include/webrtc/modules/utility/source/file_recorder_impl.h deleted file mode 100644 index 96f811d..0000000 --- a/include/webrtc/modules/utility/source/file_recorder_impl.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This file contains a class that can write audio and/or video to file in -// multiple file formats. The unencoded input data is written to file in the -// encoded format specified. - -#ifndef WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_ -#define WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_ - -#include - -#include "webrtc/base/platform_thread.h" -#include "webrtc/common_audio/resampler/include/resampler.h" -#include "webrtc/common_types.h" -#include "webrtc/engine_configurations.h" -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/media_file/media_file.h" -#include "webrtc/modules/media_file/media_file_defines.h" -#include "webrtc/modules/utility/include/file_recorder.h" -#include "webrtc/modules/utility/source/coder.h" -#include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/typedefs.h" - -namespace webrtc { -// The largest decoded frame size in samples (60ms with 32kHz sample rate). -enum { MAX_AUDIO_BUFFER_IN_SAMPLES = 60*32}; -enum { MAX_AUDIO_BUFFER_IN_BYTES = MAX_AUDIO_BUFFER_IN_SAMPLES*2}; -enum { kMaxAudioBufferQueueLength = 100 }; - -class CriticalSectionWrapper; - -class FileRecorderImpl : public FileRecorder -{ -public: - FileRecorderImpl(uint32_t instanceID, FileFormats fileFormat); - virtual ~FileRecorderImpl(); - - // FileRecorder functions. - int32_t RegisterModuleFileCallback(FileCallback* callback) override; - FileFormats RecordingFileFormat() const override; - int32_t StartRecordingAudioFile( - const char* fileName, - const CodecInst& codecInst, - uint32_t notificationTimeMs) override; - int32_t StartRecordingAudioFile( - OutStream& destStream, - const CodecInst& codecInst, - uint32_t notificationTimeMs) override; - int32_t StopRecording() override; - bool IsRecording() const override; - int32_t codec_info(CodecInst& codecInst) const override; - int32_t RecordAudioToFile(const AudioFrame& frame) override; - int32_t StartRecordingVideoFile( - const char* fileName, - const CodecInst& audioCodecInst, - const VideoCodec& videoCodecInst, - bool videoOnly = false) override - { - return -1; - } - int32_t RecordVideoToFile(const VideoFrame& videoFrame) override { - return -1; - } - -protected: - int32_t WriteEncodedAudioData(const int8_t* audioBuffer, - size_t bufferLength); - - int32_t SetUpAudioEncoder(); - - uint32_t _instanceID; - FileFormats _fileFormat; - MediaFile* _moduleFile; - -private: - CodecInst codec_info_; - int8_t _audioBuffer[MAX_AUDIO_BUFFER_IN_BYTES]; - AudioCoder _audioEncoder; - Resampler _audioResampler; -}; -} // namespace webrtc -#endif // WEBRTC_MODULES_UTILITY_SOURCE_FILE_RECORDER_IMPL_H_ diff --git a/include/webrtc/modules/utility/source/process_thread_impl.h b/include/webrtc/modules/utility/source/process_thread_impl.h index 330aec9..510ab52 100644 --- a/include/webrtc/modules/utility/source/process_thread_impl.h +++ b/include/webrtc/modules/utility/source/process_thread_impl.h @@ -33,7 +33,7 @@ class ProcessThreadImpl : public ProcessThread { void Stop() override; void WakeUp(Module* module) override; - void PostTask(std::unique_ptr task) override; + void PostTask(std::unique_ptr task) override; void RegisterModule(Module* module) override; void DeRegisterModule(Module* module) override; @@ -75,8 +75,7 @@ class ProcessThreadImpl : public ProcessThread { std::unique_ptr thread_; ModuleList modules_; - // TODO(tommi): Support delayed tasks. - std::queue queue_; + std::queue queue_; bool stop_; const char* thread_name_; }; diff --git a/include/webrtc/modules/video_capture/device_info_impl.h b/include/webrtc/modules/video_capture/device_info_impl.h index 44e7dd5..463e10d 100644 --- a/include/webrtc/modules/video_capture/device_info_impl.h +++ b/include/webrtc/modules/video_capture/device_info_impl.h @@ -14,7 +14,6 @@ #include #include "webrtc/modules/video_capture/video_capture.h" -#include "webrtc/modules/video_capture/video_capture_delay.h" #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" namespace webrtc @@ -24,7 +23,7 @@ namespace videocapturemodule class DeviceInfoImpl: public VideoCaptureModule::DeviceInfo { public: - DeviceInfoImpl(const int32_t id); + DeviceInfoImpl(); virtual ~DeviceInfoImpl(void); virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8); virtual int32_t GetCapability( @@ -48,15 +47,8 @@ class DeviceInfoImpl: public VideoCaptureModule::DeviceInfo */ virtual int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8)=0; - /* Returns the expected Capture delay*/ - int32_t GetExpectedCaptureDelay(const DelayValues delayValues[], - const uint32_t sizeOfDelayValues, - const char* productId, - const uint32_t width, - const uint32_t height); protected: // Data members - int32_t _id; typedef std::vector VideoCaptureCapabilities; VideoCaptureCapabilities _captureCapabilities; RWLockWrapper& _apiLock; diff --git a/include/webrtc/modules/video_capture/linux/device_info_linux.h b/include/webrtc/modules/video_capture/linux/device_info_linux.h index cffb222..80a8e77 100644 --- a/include/webrtc/modules/video_capture/linux/device_info_linux.h +++ b/include/webrtc/modules/video_capture/linux/device_info_linux.h @@ -21,7 +21,7 @@ namespace videocapturemodule class DeviceInfoLinux: public DeviceInfoImpl { public: - DeviceInfoLinux(const int32_t id); + DeviceInfoLinux(); virtual ~DeviceInfoLinux(); virtual uint32_t NumberOfDevices(); virtual int32_t GetDeviceName( diff --git a/include/webrtc/modules/video_capture/linux/video_capture_linux.h b/include/webrtc/modules/video_capture/linux/video_capture_linux.h index 7226664..e048e88 100644 --- a/include/webrtc/modules/video_capture/linux/video_capture_linux.h +++ b/include/webrtc/modules/video_capture/linux/video_capture_linux.h @@ -25,7 +25,7 @@ namespace videocapturemodule class VideoCaptureModuleV4L2: public VideoCaptureImpl { public: - VideoCaptureModuleV4L2(int32_t id); + VideoCaptureModuleV4L2(); virtual ~VideoCaptureModuleV4L2(); virtual int32_t Init(const char* deviceUniqueId); virtual int32_t StartCapture(const VideoCaptureCapability& capability); diff --git a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h b/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h deleted file mode 100644 index e3ddd9f..0000000 --- a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_H_ - -#import -#include - -#include "webrtc/modules/video_capture/device_info_impl.h" -#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h" -#include "webrtc/modules/video_capture/video_capture_impl.h" - -@class VideoCaptureMacQTKitObjC; -@class VideoCaptureMacQTKitInfoObjC; - -namespace webrtc -{ -namespace videocapturemodule -{ - -class VideoCaptureMacQTKit : public VideoCaptureImpl -{ -public: - VideoCaptureMacQTKit(const int32_t id); - virtual ~VideoCaptureMacQTKit(); - - /* - * Create a video capture module object - * - * id - unique identifier of this video capture module object - * deviceUniqueIdUTF8 - name of the device. Available names can be found - * by using GetDeviceName - * deviceUniqueIdUTF8Length - length of deviceUniqueIdUTF8 - */ - static void Destroy(VideoCaptureModule* module); - - int32_t Init(const int32_t id, const char* deviceUniqueIdUTF8); - - - // Start/Stop - virtual int32_t StartCapture( - const VideoCaptureCapability& capability); - virtual int32_t StopCapture(); - - // Properties of the set device - - virtual bool CaptureStarted(); - - int32_t CaptureSettings(VideoCaptureCapability& settings); - -protected: - // Help functions - int32_t SetCameraOutput(); - -private: - VideoCaptureMacQTKitObjC* _captureDevice; - VideoCaptureMacQTKitInfoObjC* _captureInfo; - bool _isCapturing; - int32_t _id; - int32_t _captureWidth; - int32_t _captureHeight; - int32_t _captureFrameRate; - char _currentDeviceNameUTF8[MAX_NAME_LENGTH]; - char _currentDeviceUniqueIdUTF8[MAX_NAME_LENGTH]; - char _currentDeviceProductUniqueIDUTF8[MAX_NAME_LENGTH]; - int32_t _frameCount; -}; -} // namespace videocapturemodule -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_H_ diff --git a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h b/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h deleted file mode 100644 index fd994ad..0000000 --- a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_H_ - -#include "webrtc/modules/video_capture/device_info_impl.h" -#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h" -#include "webrtc/modules/video_capture/video_capture_impl.h" - - -@class VideoCaptureMacQTKitInfoObjC; - -namespace webrtc -{ -namespace videocapturemodule -{ - -class VideoCaptureMacQTKitInfo: public DeviceInfoImpl -{ -public: - - VideoCaptureMacQTKitInfo(const int32_t id); - virtual ~VideoCaptureMacQTKitInfo(); - - int32_t Init(); - - virtual uint32_t NumberOfDevices(); - - /* - * Returns the available capture devices. - * deviceNumber -[in] index of capture device - * deviceNameUTF8 - friendly name of the capture device - * deviceUniqueIdUTF8 - unique name of the capture device if it exist. - * Otherwise same as deviceNameUTF8 - * productUniqueIdUTF8 - unique product id if it exist. Null terminated - * otherwise. - */ - virtual int32_t GetDeviceName( - uint32_t deviceNumber, char* deviceNameUTF8, - uint32_t deviceNameLength, char* deviceUniqueIdUTF8, - uint32_t deviceUniqueIdUTF8Length, - char* productUniqueIdUTF8 = 0, - uint32_t productUniqueIdUTF8Length = 0); - - /* - * Returns the number of capabilities for this device - */ - virtual int32_t NumberOfCapabilities( - const char* deviceUniqueIdUTF8); - - /* - * Gets the capabilities of the named device - */ - virtual int32_t GetCapability( - const char* deviceUniqueIdUTF8, - const uint32_t deviceCapabilityNumber, - VideoCaptureCapability& capability); - - /* - * Gets the capability that best matches the requested width, height and frame rate. - * Returns the deviceCapabilityNumber on success. - */ - virtual int32_t GetBestMatchedCapability( - const char* deviceUniqueIdUTF8, - const VideoCaptureCapability& requested, - VideoCaptureCapability& resulting); - - /* - * Display OS /capture device specific settings dialog - */ - virtual int32_t DisplayCaptureSettingsDialogBox( - const char* deviceUniqueIdUTF8, - const char* dialogTitleUTF8, void* parentWindow, - uint32_t positionX, uint32_t positionY); - -protected: - virtual int32_t CreateCapabilityMap( - const char* deviceUniqueIdUTF8); - - VideoCaptureMacQTKitInfoObjC* _captureInfo; -}; -} // namespace videocapturemodule -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_H_ diff --git a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info_objc.h b/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info_objc.h deleted file mode 100644 index c03aa93..0000000 --- a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info_objc.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// -// video_capture_qtkit_info_objc.h -// -// - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_OBJC_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_OBJC_H_ - -#import -#import - -#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.h" -#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h" - -@interface VideoCaptureMacQTKitInfoObjC : NSObject{ - bool _OSSupportedInfo; - NSArray* _captureDevicesInfo; - NSAutoreleasePool* _poolInfo; - int _captureDeviceCountInfo; - -} - -/************************************************************************** - * - * The following functions are considered to be private - * - ***************************************************************************/ - -- (NSNumber*)getCaptureDevices; -- (NSNumber*)initializeVariables; -- (void)checkOSSupported; - - -/************************************************************************** - * - * The following functions are considered to be public and called by VideoCaptureMacQTKitInfo class - * - ***************************************************************************/ - -- (NSNumber*)getCaptureDeviceCount; - -- (NSNumber*)getDeviceNamesFromIndex:(uint32_t)index - DefaultName:(char*)deviceName - WithLength:(uint32_t)deviceNameLength - AndUniqueID:(char*)deviceUniqueID - WithLength:(uint32_t)deviceUniqueIDLength - AndProductID:(char*)deviceProductID - WithLength:(uint32_t)deviceProductIDLength; - -- (NSNumber*)displayCaptureSettingsDialogBoxWithDevice: - (const char*)deviceUniqueIdUTF8 - AndTitle:(const char*)dialogTitleUTF8 - AndParentWindow:(void*) parentWindow AtX:(uint32_t)positionX - AndY:(uint32_t) positionY; -@end - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_INFO_OBJC_H_ diff --git a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h b/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h deleted file mode 100644 index 5007600..0000000 --- a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_objc.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// -// video_capture_qtkit_objc.h -// -// - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_OBJC_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_OBJC_H_ - -#import -#import -#import -#import -#import -#import - -#include "webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.h" - -@interface VideoCaptureMacQTKitObjC : NSObject { - bool _capturing; - int _frameRate; - int _frameWidth; - int _frameHeight; - int _framesDelivered; - int _framesRendered; - bool _captureInitialized; - - webrtc::videocapturemodule::VideoCaptureMacQTKit* _owner; - NSLock* _lock; - - QTCaptureSession* _captureSession; - QTCaptureDeviceInput* _captureVideoDeviceInput; - QTCaptureDecompressedVideoOutput* _captureDecompressedVideoOutput; - NSArray* _captureDevices; - int _captureDeviceCount; - char _captureDeviceNameUTF8[1024]; - char _captureDeviceNameUniqueID[1024]; -} - -- (void)getCaptureDevices; -- (BOOL)initializeVideoCapture; -- (BOOL)initializeVariables; - -- (void)registerOwner:(webrtc::videocapturemodule::VideoCaptureMacQTKit*)owner; -- (BOOL)setCaptureDeviceById:(char*)uniqueId; -- (void)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate; -- (void)startCapture; -- (void)stopCapture; - -@end - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_OBJC_H_ diff --git a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h b/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h deleted file mode 100644 index 5ef0b96..0000000 --- a/include/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_utility.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -/* - * video_capture_qtkit_utility.h - * - */ - - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_UTILITY_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_UTILITY_H_ - -#define MAX_NAME_LENGTH 1024 - -#define QTKIT_MIN_WIDTH 0 -#define QTKIT_MAX_WIDTH 2560 -#define QTKIT_DEFAULT_WIDTH 352 - -#define QTKIT_MIN_HEIGHT 0 -#define QTKIT_MAX_HEIGHT 1440 -#define QTKIT_DEFAULT_HEIGHT 288 - -#define QTKIT_MIN_FRAME_RATE 1 -#define QTKIT_MAX_FRAME_RATE 60 -#define QTKIT_DEFAULT_FRAME_RATE 30 - -#define RELEASE_AND_CLEAR(p) if (p) { (p) -> Release () ; (p) = NULL ; } - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_MAC_QTKIT_VIDEO_CAPTURE_QTKIT_UTILITY_H_ diff --git a/include/webrtc/modules/video_capture/ios/device_info_ios.h b/include/webrtc/modules/video_capture/objc/device_info.h similarity index 89% rename from include/webrtc/modules/video_capture/ios/device_info_ios.h rename to include/webrtc/modules/video_capture/objc/device_info.h index 6af7c33..67d5877 100644 --- a/include/webrtc/modules/video_capture/ios/device_info_ios.h +++ b/include/webrtc/modules/video_capture/objc/device_info.h @@ -8,18 +8,19 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_H_ +#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_H_ +#define WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_H_ #include "webrtc/modules/video_capture/device_info_impl.h" #include +#include namespace webrtc { namespace videocapturemodule { class DeviceInfoIos : public DeviceInfoImpl { public: - explicit DeviceInfoIos(const int32_t device_id); + DeviceInfoIos(); virtual ~DeviceInfoIos(); // Implementation of DeviceInfoImpl. @@ -57,4 +58,4 @@ class DeviceInfoIos : public DeviceInfoImpl { } // namespace videocapturemodule } // namespace webrtc -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_H_ +#endif // WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_H_ diff --git a/include/webrtc/modules/video_capture/ios/device_info_ios_objc.h b/include/webrtc/modules/video_capture/objc/device_info_objc.h similarity index 82% rename from include/webrtc/modules/video_capture/ios/device_info_ios_objc.h rename to include/webrtc/modules/video_capture/objc/device_info_objc.h index d67b559..b5db689 100644 --- a/include/webrtc/modules/video_capture/ios/device_info_ios_objc.h +++ b/include/webrtc/modules/video_capture/objc/device_info_objc.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_OBJC_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_OBJC_H_ +#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_OBJC_H_ +#define WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_OBJC_H_ #import @@ -26,4 +26,4 @@ @end -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_IOS_DEVICE_INFO_IOS_OBJC_H_ +#endif // WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_DEVICE_INFO_OBJC_H_ diff --git a/include/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h b/include/webrtc/modules/video_capture/objc/rtc_video_capture_objc.h similarity index 76% rename from include/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h rename to include/webrtc/modules/video_capture/objc/rtc_video_capture_objc.h index 2653958..71f8d8e 100644 --- a/include/webrtc/modules/video_capture/ios/rtc_video_capture_ios_objc.h +++ b/include/webrtc/modules/video_capture/objc/rtc_video_capture_objc.h @@ -8,13 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_OBJC_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_OBJC_H_ +#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_RTC_VIDEO_CAPTURE_OBJC_H_ +#define WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_RTC_VIDEO_CAPTURE_OBJC_H_ #import +#ifdef WEBRTC_IOS #import +#endif -#include "webrtc/modules/video_capture/ios/video_capture_ios.h" +#include "webrtc/modules/video_capture/objc/video_capture.h" // The following class listens to a notification with name: // 'StatusBarOrientationDidChange'. @@ -28,12 +30,11 @@ // custom initializer. Instance of VideoCaptureIos is needed // for callback purposes. // default init methods have been overridden to return nil. -- (id)initWithOwner:(webrtc::videocapturemodule::VideoCaptureIos*)owner - captureId:(int)captureId; +- (id)initWithOwner:(webrtc::videocapturemodule::VideoCaptureIos*)owner; - (BOOL)setCaptureDeviceByUniqueId:(NSString*)uniqueId; - (BOOL)startCaptureWithCapability: - (const webrtc::VideoCaptureCapability&)capability; + (const webrtc::VideoCaptureCapability&)capability; - (BOOL)stopCapture; @end -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_OBJC_H_ +#endif // WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_RTC_VIDEO_CAPTURE_OBJC_H_ diff --git a/include/webrtc/modules/video_capture/ios/video_capture_ios.h b/include/webrtc/modules/video_capture/objc/video_capture.h similarity index 80% rename from include/webrtc/modules/video_capture/ios/video_capture_ios.h rename to include/webrtc/modules/video_capture/objc/video_capture.h index 5172855..325d511 100644 --- a/include/webrtc/modules/video_capture/ios/video_capture_ios.h +++ b/include/webrtc/modules/video_capture/objc/video_capture.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_H_ +#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_VIDEO_CAPTURE_H_ +#define WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_VIDEO_CAPTURE_H_ #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/modules/video_capture/video_capture_impl.h" @@ -20,11 +20,10 @@ namespace webrtc { namespace videocapturemodule { class VideoCaptureIos : public VideoCaptureImpl { public: - explicit VideoCaptureIos(const int32_t capture_id); + VideoCaptureIos(); virtual ~VideoCaptureIos(); static rtc::scoped_refptr Create( - const int32_t capture_id, const char* device_unique_id_utf8); // Implementation of VideoCaptureImpl. @@ -36,11 +35,10 @@ class VideoCaptureIos : public VideoCaptureImpl { private: RTCVideoCaptureIosObjC* capture_device_; bool is_capturing_; - int32_t id_; VideoCaptureCapability capability_; }; } // namespace videocapturemodule } // namespace webrtc -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_IOS_VIDEO_CAPTURE_IOS_H_ +#endif // WEBRTC_MODULES_VIDEO_CAPTURE_OBJC_VIDEO_CAPTURE_H_ diff --git a/include/webrtc/modules/video_capture/video_capture.h b/include/webrtc/modules/video_capture/video_capture.h index 08d0221..884953b 100644 --- a/include/webrtc/modules/video_capture/video_capture.h +++ b/include/webrtc/modules/video_capture/video_capture.h @@ -11,13 +11,14 @@ #ifndef WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_H_ #define WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_H_ -#include "webrtc/common_video/rotation.h" +#include "webrtc/api/video/video_rotation.h" +#include "webrtc/media/base/videosinkinterface.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/video_capture/video_capture_defines.h" namespace webrtc { -class VideoCaptureModule: public RefCountedModule { +class VideoCaptureModule: public rtc::RefCountInterface { public: // Interface for receiving information about available camera devices. class DeviceInfo { @@ -75,40 +76,13 @@ class VideoCaptureModule: public RefCountedModule { virtual ~DeviceInfo() {} }; - class VideoCaptureEncodeInterface { - public: - virtual int32_t ConfigureEncoder(const VideoCodec& codec, - uint32_t maxPayloadSize) = 0; - // Inform the encoder about the new target bit rate. - // - newBitRate : New target bit rate in Kbit/s. - // - frameRate : The target frame rate. - virtual int32_t SetRates(int32_t newBitRate, int32_t frameRate) = 0; - // Inform the encoder about the packet loss and the round-trip time. - // - packetLoss : Fraction lost - // (loss rate in percent = 100 * packetLoss / 255). - // - rtt : Round-trip time in milliseconds. - virtual int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) = 0; - - // Encode the next frame as key frame. - virtual int32_t EncodeFrameType(const FrameType type) = 0; - protected: - virtual ~VideoCaptureEncodeInterface() { - } - }; - // Register capture data callback virtual void RegisterCaptureDataCallback( - VideoCaptureDataCallback& dataCallback) = 0; + rtc::VideoSinkInterface *dataCallback) = 0; // Remove capture data callback virtual void DeRegisterCaptureDataCallback() = 0; - // Register capture callback. - virtual void RegisterCaptureCallback(VideoCaptureFeedBack& callBack) = 0; - - // Remove capture callback. - virtual void DeRegisterCaptureCallback() = 0; - // Start capture device virtual int32_t StartCapture( const VideoCaptureCapability& capability) = 0; @@ -124,11 +98,6 @@ class VideoCaptureModule: public RefCountedModule { // Gets the current configuration. virtual int32_t CaptureSettings(VideoCaptureCapability& settings) = 0; - virtual void SetCaptureDelay(int32_t delayMS) = 0; - - // Returns the current CaptureDelay. Only valid when the camera is running. - virtual int32_t CaptureDelay() = 0; - // Set the rotation of the captured frames. // If the rotation is set to the same as returned by // DeviceInfo::GetOrientation the captured frames are @@ -144,14 +113,6 @@ class VideoCaptureModule: public RefCountedModule { // Return whether the rotation is applied or left pending. virtual bool GetApplyRotation() = 0; - // Gets a pointer to an encode interface if the capture device supports the - // requested type and size. NULL otherwise. - virtual VideoCaptureEncodeInterface* GetEncodeInterface( - const VideoCodec& codec) = 0; - - virtual void EnableFrameRateCallback(const bool enable) = 0; - virtual void EnableNoPictureAlarm(const bool enable) = 0; - protected: virtual ~VideoCaptureModule() {}; }; diff --git a/include/webrtc/modules/video_capture/video_capture_defines.h b/include/webrtc/modules/video_capture/video_capture_defines.h index ef97eca..90693ad 100644 --- a/include/webrtc/modules/video_capture/video_capture_defines.h +++ b/include/webrtc/modules/video_capture/video_capture_defines.h @@ -11,9 +11,9 @@ #ifndef WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_DEFINES_H_ #define WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_DEFINES_H_ +#include "webrtc/api/video/video_frame.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" namespace webrtc { @@ -31,9 +31,7 @@ struct VideoCaptureCapability int32_t width; int32_t height; int32_t maxFPS; - int32_t expectedCaptureDelay; RawVideoType rawType; - VideoCodecType codecType; bool interlaced; VideoCaptureCapability() @@ -41,9 +39,7 @@ struct VideoCaptureCapability width = 0; height = 0; maxFPS = 0; - expectedCaptureDelay = 0; rawType = kVideoUnknown; - codecType = kVideoCodecUnknown; interlaced = false; } ; @@ -57,8 +53,6 @@ struct VideoCaptureCapability return true; if (rawType != other.rawType) return true; - if (codecType != other.codecType) - return true; if (interlaced != other.interlaced) return true; return false; @@ -69,12 +63,6 @@ struct VideoCaptureCapability } }; -enum VideoCaptureAlarm -{ - Raised = 0, - Cleared = 1 -}; - /* External Capture interface. Returned by Create and implemented by the capture module. */ @@ -90,29 +78,6 @@ class VideoCaptureExternal ~VideoCaptureExternal() {} }; -// Callback class to be implemented by module user -class VideoCaptureDataCallback -{ -public: - virtual void OnIncomingCapturedFrame(const int32_t id, - const VideoFrame& videoFrame) = 0; - virtual void OnCaptureDelayChanged(const int32_t id, - const int32_t delay) = 0; -protected: - virtual ~VideoCaptureDataCallback(){} -}; - -class VideoCaptureFeedBack -{ -public: - virtual void OnCaptureFrameRate(const int32_t id, - const uint32_t frameRate) = 0; - virtual void OnNoPictureAlarm(const int32_t id, - const VideoCaptureAlarm alarm) = 0; -protected: - virtual ~VideoCaptureFeedBack(){} -}; - } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_DEFINES_H_ diff --git a/include/webrtc/modules/video_capture/video_capture_delay.h b/include/webrtc/modules/video_capture/video_capture_delay.h deleted file mode 100644 index f8924e2..0000000 --- a/include/webrtc/modules/video_capture/video_capture_delay.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_VIDEO_CAPTURE_DELAY_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_VIDEO_CAPTURE_DELAY_H_ - -namespace webrtc -{ -namespace videocapturemodule -{ - -struct DelayValue -{ - int32_t width; - int32_t height; - int32_t delay; -}; - -enum { NoOfDelayValues = 40 }; -struct DelayValues -{ - char * deviceName; - char* productId; - DelayValue delayValues[NoOfDelayValues]; -}; - -} // namespace videocapturemodule -} // namespace webrtc -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_MAIN_SOURCE_VIDEO_CAPTURE_DELAY_H_ diff --git a/include/webrtc/modules/video_capture/video_capture_factory.h b/include/webrtc/modules/video_capture/video_capture_factory.h index f05609a..c219a2a 100644 --- a/include/webrtc/modules/video_capture/video_capture_factory.h +++ b/include/webrtc/modules/video_capture/video_capture_factory.h @@ -25,18 +25,15 @@ class VideoCaptureFactory { // deviceUniqueIdUTF8 - name of the device. // Available names can be found by using GetDeviceName static rtc::scoped_refptr Create( - const int32_t id, const char* deviceUniqueIdUTF8); // Create a video capture module object used for external capture. // id - unique identifier of this video capture module object // externalCapture - [out] interface to call when a new frame is captured. static rtc::scoped_refptr Create( - const int32_t id, VideoCaptureExternal*& externalCapture); - static VideoCaptureModule::DeviceInfo* CreateDeviceInfo( - const int32_t id); + static VideoCaptureModule::DeviceInfo* CreateDeviceInfo(); private: ~VideoCaptureFactory(); diff --git a/include/webrtc/modules/video_capture/video_capture_impl.h b/include/webrtc/modules/video_capture/video_capture_impl.h index 7d785c3..559e14e 100644 --- a/include/webrtc/modules/video_capture/video_capture_impl.h +++ b/include/webrtc/modules/video_capture/video_capture_impl.h @@ -15,12 +15,11 @@ * video_capture_impl.h */ +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/common_video/rotation.h" #include "webrtc/modules/video_capture/video_capture.h" #include "webrtc/modules/video_capture/video_capture_config.h" -#include "webrtc/video_frame.h" namespace webrtc { @@ -39,7 +38,6 @@ class VideoCaptureImpl: public VideoCaptureModule, public VideoCaptureExternal * deviceUniqueIdUTF8 - name of the device. Available names can be found by using GetDeviceName */ static rtc::scoped_refptr Create( - const int32_t id, const char* deviceUniqueIdUTF8); /* @@ -49,10 +47,9 @@ class VideoCaptureImpl: public VideoCaptureModule, public VideoCaptureExternal * externalCapture - [out] interface to call when a new frame is captured. */ static rtc::scoped_refptr Create( - const int32_t id, VideoCaptureExternal*& externalCapture); - static DeviceInfo* CreateDeviceInfo(const int32_t id); + static DeviceInfo* CreateDeviceInfo(); // Helpers for converting between (integral) degrees and // VideoRotation values. Return 0 on success. @@ -60,76 +57,54 @@ class VideoCaptureImpl: public VideoCaptureModule, public VideoCaptureExternal static int32_t RotationInDegrees(VideoRotation rotation, int* degrees); //Call backs - virtual void RegisterCaptureDataCallback( - VideoCaptureDataCallback& dataCallback); - virtual void DeRegisterCaptureDataCallback(); - virtual void RegisterCaptureCallback(VideoCaptureFeedBack& callBack); - virtual void DeRegisterCaptureCallback(); - - virtual void SetCaptureDelay(int32_t delayMS); - virtual int32_t CaptureDelay(); - virtual int32_t SetCaptureRotation(VideoRotation rotation); - virtual bool SetApplyRotation(bool enable); - virtual bool GetApplyRotation() { + void RegisterCaptureDataCallback( + rtc::VideoSinkInterface* dataCallback) override; + void DeRegisterCaptureDataCallback() override; + + int32_t SetCaptureRotation(VideoRotation rotation) override; + bool SetApplyRotation(bool enable) override; + bool GetApplyRotation() override { return apply_rotation_; } - virtual void EnableFrameRateCallback(const bool enable); - virtual void EnableNoPictureAlarm(const bool enable); - - virtual const char* CurrentDeviceName() const; - - // Module handling - virtual int64_t TimeUntilNextProcess(); - virtual void Process(); + const char* CurrentDeviceName() const override; // Implement VideoCaptureExternal // |capture_time| must be specified in NTP time format in milliseconds. - virtual int32_t IncomingFrame(uint8_t* videoFrame, - size_t videoFrameLength, - const VideoCaptureCapability& frameInfo, - int64_t captureTime = 0); + int32_t IncomingFrame(uint8_t* videoFrame, + size_t videoFrameLength, + const VideoCaptureCapability& frameInfo, + int64_t captureTime = 0) override; // Platform dependent - virtual int32_t StartCapture(const VideoCaptureCapability& capability) + int32_t StartCapture(const VideoCaptureCapability& capability) override { _requestedCapability = capability; return -1; } - virtual int32_t StopCapture() { return -1; } - virtual bool CaptureStarted() {return false; } - virtual int32_t CaptureSettings(VideoCaptureCapability& /*settings*/) + int32_t StopCapture() override { return -1; } + bool CaptureStarted() override {return false; } + int32_t CaptureSettings(VideoCaptureCapability& /*settings*/) override { return -1; } - VideoCaptureEncodeInterface* GetEncodeInterface(const VideoCodec& /*codec*/) - { return NULL; } protected: - VideoCaptureImpl(const int32_t id); + VideoCaptureImpl(); virtual ~VideoCaptureImpl(); int32_t DeliverCapturedFrame(VideoFrame& captureFrame); - int32_t _id; // Module ID char* _deviceUniqueId; // current Device unique name; CriticalSectionWrapper& _apiCs; - int32_t _captureDelay; // Current capture delay. May be changed of platform dependent parts. VideoCaptureCapability _requestedCapability; // Should be set by platform dependent code in StartCapture. private: void UpdateFrameCount(); uint32_t CalculateFrameRate(int64_t now_ns); - CriticalSectionWrapper& _callBackCs; - // last time the module process function was called. int64_t _lastProcessTimeNanos; // last time the frame rate callback function was called. int64_t _lastFrameRateCallbackTimeNanos; - bool _frameRateCallBack; // true if EnableFrameRateCallback - bool _noPictureAlarmCallBack; //true if EnableNoPictureAlarm - VideoCaptureAlarm _captureAlarm; // current value of the noPictureAlarm - int32_t _setCaptureDelay; // The currently used capture delay - VideoCaptureDataCallback* _dataCallBack; - VideoCaptureFeedBack* _captureCallBack; + rtc::VideoSinkInterface* _dataCallBack; int64_t _lastProcessFrameTimeNanos; // timestamp for local captured frames @@ -137,8 +112,6 @@ class VideoCaptureImpl: public VideoCaptureModule, public VideoCaptureExternal VideoRotation _rotateFrame; // Set if the frame should be rotated by the // capture module. - VideoFrame _captureFrame; - // Indicate whether rotation should be applied before delivered externally. bool apply_rotation_; }; diff --git a/include/webrtc/modules/video_capture/video_capture_internal.h b/include/webrtc/modules/video_capture/video_capture_internal.h deleted file mode 100644 index 1a90af1..0000000 --- a/include/webrtc/modules/video_capture/video_capture_internal.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_INTERNAL_H_ -#define WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_INTERNAL_H_ - -#ifdef ANDROID -#include - -namespace webrtc { - -// In order to be able to use the internal webrtc video capture -// for android, the jvm objects must be set via this method. -int32_t SetCaptureAndroidVM(JavaVM* javaVM, jobject context); - -} // namespace webrtc - -#endif // ANDROID - -#endif // WEBRTC_MODULES_VIDEO_CAPTURE_VIDEO_CAPTURE_INTERNAL_H_ diff --git a/include/webrtc/modules/video_capture/windows/device_info_ds.h b/include/webrtc/modules/video_capture/windows/device_info_ds.h index 7acbfa6..0f71196 100644 --- a/include/webrtc/modules/video_capture/windows/device_info_ds.h +++ b/include/webrtc/modules/video_capture/windows/device_info_ds.h @@ -35,9 +35,9 @@ class DeviceInfoDS: public DeviceInfoImpl { public: // Factory function. - static DeviceInfoDS* Create(const int32_t id); + static DeviceInfoDS* Create(); - DeviceInfoDS(const int32_t id); + DeviceInfoDS(); virtual ~DeviceInfoDS(); int32_t Init(); diff --git a/include/webrtc/modules/video_capture/windows/device_info_mf.h b/include/webrtc/modules/video_capture/windows/device_info_mf.h index b787e00..7512277 100644 --- a/include/webrtc/modules/video_capture/windows/device_info_mf.h +++ b/include/webrtc/modules/video_capture/windows/device_info_mf.h @@ -19,7 +19,7 @@ namespace videocapturemodule { // Provides video capture device information using the Media Foundation API. class DeviceInfoMF : public DeviceInfoImpl { public: - explicit DeviceInfoMF(const int32_t id); + DeviceInfoMF(); virtual ~DeviceInfoMF(); int32_t Init(); diff --git a/include/webrtc/modules/video_capture/windows/sink_filter_ds.h b/include/webrtc/modules/video_capture/windows/sink_filter_ds.h index 6be74f6..f065f91 100644 --- a/include/webrtc/modules/video_capture/windows/sink_filter_ds.h +++ b/include/webrtc/modules/video_capture/windows/sink_filter_ds.h @@ -29,14 +29,11 @@ class CaptureSinkFilter; class CaptureInputPin: public CBaseInputPin { public: - int32_t _moduleId; - VideoCaptureCapability _requestedCapability; VideoCaptureCapability _resultingCapability; HANDLE _threadHandle; - CaptureInputPin(int32_t moduleId, - IN TCHAR* szName, + CaptureInputPin(IN TCHAR* szName, IN CaptureSinkFilter* pFilter, IN CCritSec * pLock, OUT HRESULT * pHr, @@ -56,8 +53,7 @@ class CaptureSinkFilter: public CBaseFilter CaptureSinkFilter(IN TCHAR * tszName, IN LPUNKNOWN punk, OUT HRESULT * phr, - VideoCaptureExternal& captureObserver, - int32_t moduleId); + VideoCaptureExternal& captureObserver); virtual ~CaptureSinkFilter(); // -------------------------------------------------------------------- @@ -93,7 +89,6 @@ DECLARE_IUNKNOWN ; CCritSec m_crtRecv; // receiver lock; always acquire before filter lock CaptureInputPin * m_pInput; VideoCaptureExternal& _captureObserver; - int32_t _moduleId; }; } // namespace videocapturemodule } // namespace webrtc diff --git a/include/webrtc/modules/video_capture/windows/video_capture_ds.h b/include/webrtc/modules/video_capture/windows/video_capture_ds.h index 1f6193d..7e63e56 100644 --- a/include/webrtc/modules/video_capture/windows/video_capture_ds.h +++ b/include/webrtc/modules/video_capture/windows/video_capture_ds.h @@ -27,9 +27,9 @@ class CaptureSinkFilter; class VideoCaptureDS: public VideoCaptureImpl { public: - VideoCaptureDS(const int32_t id); + VideoCaptureDS(); - virtual int32_t Init(const int32_t id, const char* deviceUniqueIdUTF8); + virtual int32_t Init(const char* deviceUniqueIdUTF8); /************************************************************************* * diff --git a/include/webrtc/modules/video_capture/windows/video_capture_mf.h b/include/webrtc/modules/video_capture/windows/video_capture_mf.h index 076ef55..5b58f89 100644 --- a/include/webrtc/modules/video_capture/windows/video_capture_mf.h +++ b/include/webrtc/modules/video_capture/windows/video_capture_mf.h @@ -22,9 +22,9 @@ namespace videocapturemodule { // for supported platforms. class VideoCaptureMF : public VideoCaptureImpl { public: - explicit VideoCaptureMF(const int32_t id); + VideoCaptureMF(); - int32_t Init(const int32_t id, const char* device_id); + int32_t Init(const char* device_id); // Overrides from VideoCaptureImpl. virtual int32_t StartCapture(const VideoCaptureCapability& capability); diff --git a/include/webrtc/modules/video_coding/codec_database.h b/include/webrtc/modules/video_coding/codec_database.h index 4ba72f7..5a7e875 100644 --- a/include/webrtc/modules/video_coding/codec_database.h +++ b/include/webrtc/modules/video_coding/codec_database.h @@ -44,8 +44,7 @@ struct VCMExtDecoderMapItem { class VCMCodecDataBase { public: - VCMCodecDataBase(VideoEncoderRateObserver* encoder_rate_observer, - VCMEncodedFrameCallback* encoded_frame_callback); + explicit VCMCodecDataBase(VCMEncodedFrameCallback* encoded_frame_callback); ~VCMCodecDataBase(); // Sender Side @@ -154,7 +153,6 @@ class VCMCodecDataBase { uint8_t encoder_payload_type_; VideoEncoder* external_encoder_; bool internal_source_; - VideoEncoderRateObserver* const encoder_rate_observer_; VCMEncodedFrameCallback* const encoded_frame_callback_; std::unique_ptr ptr_encoder_; VCMGenericDecoder* ptr_decoder_; diff --git a/include/webrtc/modules/video_coding/codec_timer.h b/include/webrtc/modules/video_coding/codec_timer.h index 90ef6bb..3fd081b 100644 --- a/include/webrtc/modules/video_coding/codec_timer.h +++ b/include/webrtc/modules/video_coding/codec_timer.h @@ -13,8 +13,8 @@ #include +#include "webrtc/base/numerics/percentile_filter.h" #include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/video_coding/percentile_filter.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -43,7 +43,7 @@ class VCMCodecTimer { std::queue history_; // |filter_| contains the same values as |history_|, but in a data structure // that allows efficient retrieval of the percentile value. - PercentileFilter filter_; + PercentileFilter filter_; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.h b/include/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.h index e724c37..fc730a4 100644 --- a/include/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.h +++ b/include/webrtc/modules/video_coding/codecs/h264/h264_decoder_impl.h @@ -52,6 +52,8 @@ class H264DecoderImpl : public H264Decoder { const CodecSpecificInfo* codec_specific_info = nullptr, int64_t render_time_ms = -1) override; + const char* ImplementationName() const override; + private: // Called by FFmpeg when it needs a frame buffer to store decoded frames in. // The |VideoFrame| returned by FFmpeg at |Decode| originate from here. Their diff --git a/include/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h b/include/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h index d7493e0..a455259 100644 --- a/include/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h +++ b/include/webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h @@ -12,11 +12,14 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_ENCODER_IMPL_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_ENCODER_IMPL_H_ -#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" - #include #include +#include "webrtc/common_video/h264/h264_bitstream_parser.h" +#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" +#include "webrtc/modules/video_coding/utility/quality_scaler.h" + +#include "third_party/openh264/src/codec/api/svc/codec_app_def.h" class ISVCEncoder; @@ -24,7 +27,7 @@ namespace webrtc { class H264EncoderImpl : public H264Encoder { public: - H264EncoderImpl(); + explicit H264EncoderImpl(const cricket::VideoCodec& codec); ~H264EncoderImpl() override; // |max_payload_size| is ignored. @@ -36,12 +39,13 @@ class H264EncoderImpl : public H264Encoder { // - height int32_t InitEncode(const VideoCodec* codec_settings, int32_t number_of_cores, - size_t /*max_payload_size*/) override; + size_t max_payload_size) override; int32_t Release() override; int32_t RegisterEncodeCompleteCallback( EncodedImageCallback* callback) override; - int32_t SetRates(uint32_t bitrate, uint32_t framerate) override; + int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation, + uint32_t framerate) override; // The result of encoding - an EncodedImage and RTPFragmentationHeader - are // passed to the encode complete callback. @@ -49,20 +53,43 @@ class H264EncoderImpl : public H264Encoder { const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types) override; + const char* ImplementationName() const override; + + VideoEncoder::ScalingSettings GetScalingSettings() const override; + // Unsupported / Do nothing. int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; int32_t SetPeriodicKeyFrames(bool enable) override; - void OnDroppedFrame() override; + + // Exposed for testing. + H264PacketizationMode PacketizationModeForTesting() const { + return packetization_mode_; + } private: bool IsInitialized() const; + SEncParamExt CreateEncoderParams() const; + webrtc::H264BitstreamParser h264_bitstream_parser_; // Reports statistics with histograms. void ReportInit(); void ReportError(); ISVCEncoder* openh264_encoder_; - VideoCodec codec_settings_; + // Settings that are used by this encoder. + int width_; + int height_; + float max_frame_rate_; + uint32_t target_bps_; + uint32_t max_bps_; + VideoCodecMode mode_; + // H.264 specifc parameters + bool frame_dropping_on_; + int key_frame_interval_; + H264PacketizationMode packetization_mode_; + + size_t max_payload_size_; + int32_t number_of_cores_; EncodedImage encoded_image_; std::unique_ptr encoded_image_buffer_; diff --git a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h b/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h deleted file mode 100644 index 1fbccda..0000000 --- a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_decoder.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - * - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_DECODER_H_ -#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_DECODER_H_ - -#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" - -#if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) - -#include - -// This file provides a H264 encoder implementation using the VideoToolbox -// APIs. Since documentation is almost non-existent, this is largely based on -// the information in the VideoToolbox header files, a talk from WWDC 2014 and -// experimentation. - -namespace webrtc { - -class H264VideoToolboxDecoder : public H264Decoder { - public: - H264VideoToolboxDecoder(); - - ~H264VideoToolboxDecoder() override; - - int InitDecode(const VideoCodec* video_codec, int number_of_cores) override; - - int Decode(const EncodedImage& input_image, - bool missing_frames, - const RTPFragmentationHeader* fragmentation, - const CodecSpecificInfo* codec_specific_info, - int64_t render_time_ms) override; - - int RegisterDecodeCompleteCallback(DecodedImageCallback* callback) override; - - int Release() override; - - const char* ImplementationName() const override; - - private: - int ResetDecompressionSession(); - void ConfigureDecompressionSession(); - void DestroyDecompressionSession(); - void SetVideoFormat(CMVideoFormatDescriptionRef video_format); - - DecodedImageCallback* callback_; - CMVideoFormatDescriptionRef video_format_; - VTDecompressionSessionRef decompression_session_; -}; // H264VideoToolboxDecoder - -} // namespace webrtc - -#endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) -#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_DECODER_H_ diff --git a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h b/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h deleted file mode 100644 index d54fa61..0000000 --- a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_encoder.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - * - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_ -#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_ - -#include "webrtc/common_video/include/bitrate_adjuster.h" -#include "webrtc/common_video/rotation.h" -#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" - -#if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) - -#include -#include - -// This file provides a H264 encoder implementation using the VideoToolbox -// APIs. Since documentation is almost non-existent, this is largely based on -// the information in the VideoToolbox header files, a talk from WWDC 2014 and -// experimentation. - -namespace webrtc { - -class H264VideoToolboxEncoder : public H264Encoder { - public: - H264VideoToolboxEncoder(); - - ~H264VideoToolboxEncoder() override; - - int InitEncode(const VideoCodec* codec_settings, - int number_of_cores, - size_t max_payload_size) override; - - int Encode(const VideoFrame& input_image, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) override; - - int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override; - - int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; - - int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) override; - - int Release() override; - - const char* ImplementationName() const override; - - void OnEncodedFrame(OSStatus status, - VTEncodeInfoFlags info_flags, - CMSampleBufferRef sample_buffer, - CodecSpecificInfo codec_specific_info, - int32_t width, - int32_t height, - int64_t render_time_ms, - uint32_t timestamp, - VideoRotation rotation); - - private: - int ResetCompressionSession(); - void ConfigureCompressionSession(); - void DestroyCompressionSession(); - void SetBitrateBps(uint32_t bitrate_bps); - void SetEncoderBitrateBps(uint32_t bitrate_bps); - - EncodedImageCallback* callback_; - VTCompressionSessionRef compression_session_; - BitrateAdjuster bitrate_adjuster_; - uint32_t target_bitrate_bps_; - uint32_t encoder_bitrate_bps_; - int32_t width_; - int32_t height_; -}; // H264VideoToolboxEncoder - -} // namespace webrtc - -#endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) -#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_ENCODER_H_ diff --git a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h b/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h deleted file mode 100644 index 5094253..0000000 --- a/include/webrtc/modules/video_coding/codecs/h264/h264_video_toolbox_nalu.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - * - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_NALU_H_ -#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_NALU_H_ - -#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" - -#if defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) - -#include - -#include "webrtc/base/buffer.h" -#include "webrtc/modules/include/module_common_types.h" - -namespace webrtc { - -// Converts a sample buffer emitted from the VideoToolbox encoder into a buffer -// suitable for RTP. The sample buffer is in avcc format whereas the rtp buffer -// needs to be in Annex B format. Data is written directly to |annexb_buffer| -// and a new RTPFragmentationHeader is returned in |out_header|. -bool H264CMSampleBufferToAnnexBBuffer( - CMSampleBufferRef avcc_sample_buffer, - bool is_keyframe, - rtc::Buffer* annexb_buffer, - webrtc::RTPFragmentationHeader** out_header); - -// Converts a buffer received from RTP into a sample buffer suitable for the -// VideoToolbox decoder. The RTP buffer is in annex b format whereas the sample -// buffer is in avcc format. -// If |is_keyframe| is true then |video_format| is ignored since the format will -// be read from the buffer. Otherwise |video_format| must be provided. -// Caller is responsible for releasing the created sample buffer. -bool H264AnnexBBufferToCMSampleBuffer(const uint8_t* annexb_buffer, - size_t annexb_buffer_size, - CMVideoFormatDescriptionRef video_format, - CMSampleBufferRef* out_sample_buffer); - -// Returns true if the type of the first NALU in the supplied Annex B buffer is -// the SPS type. -bool H264AnnexBBufferHasVideoFormatDescription(const uint8_t* annexb_buffer, - size_t annexb_buffer_size); - -// Returns a video format description created from the sps/pps information in -// the Annex B buffer. If there is no such information, nullptr is returned. -// The caller is responsible for releasing the description. -CMVideoFormatDescriptionRef CreateVideoFormatDescription( - const uint8_t* annexb_buffer, - size_t annexb_buffer_size); - -// Helper class for reading NALUs from an RTP Annex B buffer. -class AnnexBBufferReader final { - public: - AnnexBBufferReader(const uint8_t* annexb_buffer, size_t length); - ~AnnexBBufferReader() {} - AnnexBBufferReader(const AnnexBBufferReader& other) = delete; - void operator=(const AnnexBBufferReader& other) = delete; - - // Returns a pointer to the beginning of the next NALU slice without the - // header bytes and its length. Returns false if no more slices remain. - bool ReadNalu(const uint8_t** out_nalu, size_t* out_length); - - // Returns the number of unread NALU bytes, including the size of the header. - // If the buffer has no remaining NALUs this will return zero. - size_t BytesRemaining() const; - - private: - // Returns the the next offset that contains NALU data. - size_t FindNextNaluHeader(const uint8_t* start, - size_t length, - size_t offset) const; - - const uint8_t* const start_; - size_t offset_; - size_t next_offset_; - const size_t length_; -}; - -// Helper class for writing NALUs using avcc format into a buffer. -class AvccBufferWriter final { - public: - AvccBufferWriter(uint8_t* const avcc_buffer, size_t length); - ~AvccBufferWriter() {} - AvccBufferWriter(const AvccBufferWriter& other) = delete; - void operator=(const AvccBufferWriter& other) = delete; - - // Writes the data slice into the buffer. Returns false if there isn't - // enough space left. - bool WriteNalu(const uint8_t* data, size_t data_size); - - // Returns the unused bytes in the buffer. - size_t BytesRemaining() const; - - private: - uint8_t* const start_; - size_t offset_; - const size_t length_; -}; - -} // namespace webrtc - -#endif // defined(WEBRTC_VIDEO_TOOLBOX_SUPPORTED) -#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_H264_VIDEO_TOOLBOX_NALU_H_ diff --git a/include/webrtc/modules/video_coding/codecs/h264/include/h264.h b/include/webrtc/modules/video_coding/codecs/h264/include/h264.h index 2c404b2..2d92473 100644 --- a/include/webrtc/modules/video_coding/codecs/h264/include/h264.h +++ b/include/webrtc/modules/video_coding/codecs/h264/include/h264.h @@ -12,17 +12,7 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_H_ -#if defined(WEBRTC_IOS) || defined(WEBRTC_MAC) - -#include -#if (defined(__IPHONE_8_0) && \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0) || \ - (defined(__MAC_10_8) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_8) -#define WEBRTC_VIDEO_TOOLBOX_SUPPORTED 1 -#endif - -#endif // defined(WEBRTC_IOS) || defined(WEBRTC_MAC) - +#include "webrtc/media/base/codec.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" namespace webrtc { @@ -35,7 +25,7 @@ void DisableRtcUseH264(); class H264Encoder : public VideoEncoder { public: - static H264Encoder* Create(); + static H264Encoder* Create(const cricket::VideoCodec& codec); // If H.264 is supported (any implementation). static bool IsSupported(); diff --git a/include/webrtc/modules/video_coding/codecs/h264/include/h264_globals.h b/include/webrtc/modules/video_coding/codecs/h264/include/h264_globals.h new file mode 100644 index 0000000..93c8887 --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/h264/include/h264_globals.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains codec dependent definitions that are needed in +// order to compile the WebRTC codebase, even if this codec is not used. + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_GLOBALS_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_GLOBALS_H_ + +namespace webrtc { + +// The packetization types that we support: single, aggregated, and fragmented. +enum H264PacketizationTypes { + kH264SingleNalu, // This packet contains a single NAL unit. + kH264StapA, // This packet contains STAP-A (single time + // aggregation) packets. If this packet has an + // associated NAL unit type, it'll be for the + // first such aggregated packet. + kH264FuA, // This packet contains a FU-A (fragmentation + // unit) packet, meaning it is a part of a frame + // that was too large to fit into a single packet. +}; + +// Packetization modes are defined in RFC 6184 section 6 +// Due to the structure containing this being initialized with zeroes +// in some places, and mode 1 being default, mode 1 needs to have the value +// zero. https://crbug.com/webrtc/6803 +enum class H264PacketizationMode { + NonInterleaved = 0, // Mode 1 - STAP-A, FU-A is allowed + SingleNalUnit // Mode 0 - only single NALU allowed +}; + +// This function is declared inline because it is not clear which +// .cc file it should belong to. +// TODO(hta): Refactor. https://bugs.webrtc.org/6842 +inline std::ostream& operator<<(std::ostream& stream, + H264PacketizationMode mode) { + switch (mode) { + case H264PacketizationMode::NonInterleaved: + stream << "NonInterleaved"; + break; + case H264PacketizationMode::SingleNalUnit: + stream << "SingleNalUnit"; + break; + } + return stream; +} + +struct NaluInfo { + uint8_t type; + int sps_id; + int pps_id; + + // Offset and size are only valid for non-FuA packets. + size_t offset; + size_t size; +}; + +const size_t kMaxNalusPerPacket = 10; + +struct RTPVideoHeaderH264 { + // The NAL unit type. If this is a header for a + // fragmented packet, it's the NAL unit type of + // the original data. If this is the header for an + // aggregated packet, it's the NAL unit type of + // the first NAL unit in the packet. + uint8_t nalu_type; + // The packetization type of this buffer - single, aggregated or fragmented. + H264PacketizationTypes packetization_type; + NaluInfo nalus[kMaxNalusPerPacket]; + size_t nalus_length; + // The packetization mode of this transport. Packetization mode + // determines which packetization types are allowed when packetizing. + H264PacketizationMode packetization_mode; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_H264_INCLUDE_H264_GLOBALS_H_ diff --git a/include/webrtc/modules/video_coding/codecs/i420/include/i420.h b/include/webrtc/modules/video_coding/codecs/i420/include/i420.h index 220aea4..1047ae0 100644 --- a/include/webrtc/modules/video_coding/codecs/i420/include/i420.h +++ b/include/webrtc/modules/video_coding/codecs/i420/include/i420.h @@ -13,6 +13,7 @@ #include +#include "webrtc/base/checks.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" #include "webrtc/typedefs.h" @@ -65,16 +66,10 @@ class I420Encoder : public VideoEncoder { // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. int Release() override; - int SetRates(uint32_t /*newBitRate*/, uint32_t /*frameRate*/) override { - return WEBRTC_VIDEO_CODEC_OK; - } - int SetChannelParameters(uint32_t /*packetLoss*/, int64_t /*rtt*/) override { return WEBRTC_VIDEO_CODEC_OK; } - void OnDroppedFrame() override {} - private: static uint8_t* InsertHeader(uint8_t* buffer, uint16_t width, @@ -136,7 +131,6 @@ class I420Decoder : public VideoDecoder { uint16_t* width, uint16_t* height); - VideoFrame _decodedImage; int _width; int _height; bool _inited; diff --git a/include/webrtc/modules/video_coding/codecs/interface/common_constants.h b/include/webrtc/modules/video_coding/codecs/interface/common_constants.h new file mode 100644 index 0000000..8ed26c4 --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/interface/common_constants.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains constants that are used by multiple global +// codec definitions (modules/video_coding/codecs/*/include/*_globals.h) + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_INTERFACE_COMMON_CONSTANTS_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_INTERFACE_COMMON_CONSTANTS_H_ + +namespace webrtc { + +const int16_t kNoPictureId = -1; +const int16_t kNoTl0PicIdx = -1; +const uint8_t kNoTemporalIdx = 0xFF; +const int kNoKeyIdx = -1; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_INTERFACE_COMMON_CONSTANTS_H_ diff --git a/include/webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h b/include/webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h index cdee8c5..e58da79 100644 --- a/include/webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h +++ b/include/webrtc/modules/video_coding/codecs/interface/mock/mock_video_codec_interface.h @@ -16,8 +16,8 @@ #include #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h b/include/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h index 6bcfa90..98b5040 100644 --- a/include/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h +++ b/include/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h @@ -15,13 +15,13 @@ "use video_coding/include") #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/common_types.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/include/video_error_codes.h" #include "webrtc/typedefs.h" #include "webrtc/video_decoder.h" #include "webrtc/video_encoder.h" -#include "webrtc/video_frame.h" namespace webrtc { diff --git a/include/webrtc/modules/video_coding/codecs/test/android_test_initializer.h b/include/webrtc/modules/video_coding/codecs/test/android_test_initializer.h new file mode 100644 index 0000000..a4ec9d2 --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/test/android_test_initializer.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ + +namespace webrtc { + +void InitializeAndroidObjects(); + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_ANDROID_TEST_INITIALIZER_H_ diff --git a/include/webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h b/include/webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h index 1e2c9b8..4096a93 100644 --- a/include/webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h +++ b/include/webrtc/modules/video_coding/codecs/test/mock/mock_packet_manipulator.h @@ -15,7 +15,7 @@ #include -#include "testing/gmock/include/gmock/gmock.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" #include "webrtc/video_frame.h" diff --git a/include/webrtc/modules/video_coding/codecs/test/stats.h b/include/webrtc/modules/video_coding/codecs/test/stats.h index 9092631..d2dd303 100644 --- a/include/webrtc/modules/video_coding/codecs/test/stats.h +++ b/include/webrtc/modules/video_coding/codecs/test/stats.h @@ -28,6 +28,7 @@ struct FrameStatistic { int decode_return_code; int encode_time_in_us; int decode_time_in_us; + int qp; int frame_number; // How many packets were discarded of the encoded frame data (if any). int packets_dropped; diff --git a/include/webrtc/modules/video_coding/codecs/test/videoprocessor.h b/include/webrtc/modules/video_coding/codecs/test/videoprocessor.h index f0322dd..8623476 100644 --- a/include/webrtc/modules/video_coding/codecs/test/videoprocessor.h +++ b/include/webrtc/modules/video_coding/codecs/test/videoprocessor.h @@ -11,19 +11,23 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_H_ +#include #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/checks.h" -#include "webrtc/common_video/libyuv/include/scaler.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" #include "webrtc/modules/video_coding/codecs/test/stats.h" +#include "webrtc/modules/video_coding/utility/ivf_file_writer.h" #include "webrtc/test/testsupport/frame_reader.h" #include "webrtc/test/testsupport/frame_writer.h" -#include "webrtc/video_frame.h" namespace webrtc { + +class VideoBitrateAllocator; + namespace test { // Defines which frame types shall be excluded from packet loss and when. @@ -35,10 +39,11 @@ enum ExcludeFrameTypes { // sequence they occur. kExcludeAllKeyFrames }; + // Returns a string representation of the enum value. const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e); -// Test configuration for a test run +// Test configuration for a test run. struct TestConfig { TestConfig(); ~TestConfig(); @@ -105,9 +110,6 @@ struct TestConfig { bool verbose; }; -// Returns a string representation of the enum value. -const char* VideoCodecTypeToStr(webrtc::VideoCodecType e); - // Handles encoding/decoding of video using the VideoEncoder/VideoDecoder // interfaces. This is done in a sequential manner in order to be able to // measure times properly. @@ -136,7 +138,7 @@ class VideoProcessor { // Processes a single frame. Returns true as long as there's more frames // available in the source clip. - // Frame number must be an integer >=0. + // Frame number must be an integer >= 0. virtual bool ProcessFrame(int frame_number) = 0; // Updates the encoder with the target bit rate and the frame rate. @@ -160,103 +162,141 @@ class VideoProcessorImpl : public VideoProcessor { public: VideoProcessorImpl(webrtc::VideoEncoder* encoder, webrtc::VideoDecoder* decoder, - FrameReader* frame_reader, - FrameWriter* frame_writer, + FrameReader* analysis_frame_reader, + FrameWriter* analysis_frame_writer, PacketManipulator* packet_manipulator, const TestConfig& config, - Stats* stats); + Stats* stats, + FrameWriter* source_frame_writer, + IvfFileWriter* encoded_frame_writer, + FrameWriter* decoded_frame_writer); virtual ~VideoProcessorImpl(); bool Init() override; bool ProcessFrame(int frame_number) override; private: + // Callback class required to implement according to the VideoEncoder API. + class VideoProcessorEncodeCompleteCallback + : public webrtc::EncodedImageCallback { + public: + explicit VideoProcessorEncodeCompleteCallback(VideoProcessorImpl* vp) + : video_processor_(vp) {} + Result OnEncodedImage( + const webrtc::EncodedImage& encoded_image, + const webrtc::CodecSpecificInfo* codec_specific_info, + const webrtc::RTPFragmentationHeader* fragmentation) override { + // Forward to parent class. + RTC_CHECK(codec_specific_info); + video_processor_->FrameEncoded(codec_specific_info->codecType, + encoded_image, fragmentation); + return Result(Result::OK, 0); + } + + private: + VideoProcessorImpl* const video_processor_; + }; + + // Callback class required to implement according to the VideoDecoder API. + class VideoProcessorDecodeCompleteCallback + : public webrtc::DecodedImageCallback { + public: + explicit VideoProcessorDecodeCompleteCallback(VideoProcessorImpl* vp) + : video_processor_(vp) {} + int32_t Decoded(webrtc::VideoFrame& image) override { + // Forward to parent class. + video_processor_->FrameDecoded(image); + return 0; + } + int32_t Decoded(webrtc::VideoFrame& image, + int64_t decode_time_ms) override { + return Decoded(image); + } + void Decoded(webrtc::VideoFrame& image, + rtc::Optional decode_time_ms, + rtc::Optional qp) override { + Decoded(image, + decode_time_ms ? static_cast(*decode_time_ms) : -1); + } + + private: + VideoProcessorImpl* const video_processor_; + }; + // Invoked by the callback when a frame has completed encoding. void FrameEncoded(webrtc::VideoCodecType codec, const webrtc::EncodedImage& encodedImage, const webrtc::RTPFragmentationHeader* fragmentation); + // Invoked by the callback when a frame has completed decoding. void FrameDecoded(const webrtc::VideoFrame& image); + // Used for getting a 32-bit integer representing time // (checks the size is within signed 32-bit bounds before casting it) int GetElapsedTimeMicroseconds(int64_t start, int64_t stop); + // Updates the encoder with the target bit rate and the frame rate. void SetRates(int bit_rate, int frame_rate) override; + // Return the size of the encoded frame in bytes. size_t EncodedFrameSize() override; + // Return the encoded frame type (key or delta). FrameType EncodedFrameType() override; + // Return the number of dropped frames. int NumberDroppedFrames() override; + // Return the number of spatial resizes. int NumberSpatialResizes() override; - webrtc::VideoEncoder* encoder_; - webrtc::VideoDecoder* decoder_; - FrameReader* frame_reader_; - FrameWriter* frame_writer_; - PacketManipulator* packet_manipulator_; + webrtc::VideoEncoder* const encoder_; + webrtc::VideoDecoder* const decoder_; + const std::unique_ptr bitrate_allocator_; + + // Adapters for the codec callbacks. + const std::unique_ptr encode_callback_; + const std::unique_ptr decode_callback_; + + PacketManipulator* const packet_manipulator_; const TestConfig& config_; - Stats* stats_; - EncodedImageCallback* encode_callback_; - DecodedImageCallback* decode_callback_; - // Buffer used for reading the source video file: - uint8_t* source_buffer_; + // These (mandatory) file manipulators are used for, e.g., objective PSNR and + // SSIM calculations at the end of a test run. + FrameReader* const analysis_frame_reader_; + FrameWriter* const analysis_frame_writer_; + + // These (optional) file writers are used for persistently storing the output + // of the coding pipeline at different stages: pre encode (source), post + // encode (encoded), and post decode (decoded). The purpose is to give the + // experimenter an option to subjectively evaluate the quality of the + // encoding, given the test settings. Each frame writer is enabled by being + // non-null. + FrameWriter* const source_frame_writer_; + IvfFileWriter* const encoded_frame_writer_; + FrameWriter* const decoded_frame_writer_; + // Keep track of the last successful frame, since we need to write that - // when decoding fails: - uint8_t* last_successful_frame_buffer_; - webrtc::VideoFrame source_frame_; - // To keep track of if we have excluded the first key frame from packet loss: + // when decoding fails. + std::unique_ptr last_successful_frame_buffer_; + // To keep track of if we have excluded the first key frame from packet loss. bool first_key_frame_has_been_excluded_; - // To tell the decoder previous frame have been dropped due to packet loss: + // To tell the decoder previous frame have been dropped due to packet loss. bool last_frame_missing_; // If Init() has executed successfully. bool initialized_; size_t encoded_frame_size_; FrameType encoded_frame_type_; int prev_time_stamp_; - int num_dropped_frames_; - int num_spatial_resizes_; int last_encoder_frame_width_; int last_encoder_frame_height_; - Scaler scaler_; - // Statistics - double bit_rate_factor_; // multiply frame length with this to get bit rate + // Statistics. + Stats* stats_; + int num_dropped_frames_; + int num_spatial_resizes_; + double bit_rate_factor_; // Multiply frame length with this to get bit rate. int64_t encode_start_ns_; int64_t decode_start_ns_; - - // Callback class required to implement according to the VideoEncoder API. - class VideoProcessorEncodeCompleteCallback - : public webrtc::EncodedImageCallback { - public: - explicit VideoProcessorEncodeCompleteCallback(VideoProcessorImpl* vp) - : video_processor_(vp) {} - int32_t Encoded( - const webrtc::EncodedImage& encoded_image, - const webrtc::CodecSpecificInfo* codec_specific_info, - const webrtc::RTPFragmentationHeader* fragmentation) override; - - private: - VideoProcessorImpl* video_processor_; - }; - - // Callback class required to implement according to the VideoDecoder API. - class VideoProcessorDecodeCompleteCallback - : public webrtc::DecodedImageCallback { - public: - explicit VideoProcessorDecodeCompleteCallback(VideoProcessorImpl* vp) - : video_processor_(vp) {} - int32_t Decoded(webrtc::VideoFrame& image) override; - int32_t Decoded(webrtc::VideoFrame& image, - int64_t decode_time_ms) override { - RTC_NOTREACHED(); - return -1; - } - - private: - VideoProcessorImpl* video_processor_; - }; }; } // namespace test diff --git a/include/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h b/include/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h new file mode 100644 index 0000000..ceaf7ce --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.h @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H_ + +#include + +#include +#include +#include + +#if defined(WEBRTC_ANDROID) +#include "webrtc/modules/video_coding/codecs/test/android_test_initializer.h" +#include "webrtc/sdk/android/src/jni/androidmediadecoder_jni.h" +#include "webrtc/sdk/android/src/jni/androidmediaencoder_jni.h" +#elif defined(WEBRTC_IOS) +#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_decoder.h" +#include "webrtc/sdk/objc/Framework/Classes/h264_video_toolbox_encoder.h" +#endif + +#include "webrtc/base/checks.h" +#include "webrtc/base/file.h" +#include "webrtc/media/engine/webrtcvideodecoderfactory.h" +#include "webrtc/media/engine/webrtcvideoencoderfactory.h" +#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" +#include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h" +#include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" +#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" +#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" +#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" +#include "webrtc/modules/video_coding/include/video_codec_interface.h" +#include "webrtc/modules/video_coding/include/video_coding.h" +#include "webrtc/modules/video_coding/utility/ivf_file_writer.h" +#include "webrtc/test/gtest.h" +#include "webrtc/test/testsupport/fileutils.h" +#include "webrtc/test/testsupport/frame_reader.h" +#include "webrtc/test/testsupport/frame_writer.h" +#include "webrtc/test/testsupport/metrics/video_metrics.h" +#include "webrtc/test/testsupport/packet_reader.h" +#include "webrtc/typedefs.h" + +namespace webrtc { +namespace test { +// Maximum number of rate updates (i.e., calls to encoder to change bitrate +// and/or frame rate) for the current tests. +const int kMaxNumRateUpdates = 3; + +const int kPercTargetvsActualMismatch = 20; +const int kBaseKeyFrameInterval = 3000; + +// Default sequence is foreman (CIF): may be better to use VGA for resize test. +const int kCifWidth = 352; +const int kCifHeight = 288; +const char kFilenameForemanCif[] = "foreman_cif"; + +// Codec and network settings. +struct CodecParams { + VideoCodecType codec_type; + bool hw_codec; + bool use_single_core; + + int width; + int height; + + int num_temporal_layers; + int key_frame_interval; + bool error_concealment_on; + bool denoising_on; + bool frame_dropper_on; + bool spatial_resize_on; + + float packet_loss_probability; // [0.0, 1.0]. + + std::string filename; + bool verbose_logging; +}; + +// Thresholds for the quality metrics. +struct QualityThresholds { + double min_avg_psnr; + double min_min_psnr; + double min_avg_ssim; + double min_min_ssim; +}; + +// The sequence of bit rate and frame rate changes for the encoder, the frame +// number where the changes are made, and the total number of frames for the +// test. +struct RateProfile { + int target_bit_rate[kMaxNumRateUpdates]; + int input_frame_rate[kMaxNumRateUpdates]; + int frame_index_rate_update[kMaxNumRateUpdates + 1]; + int num_frames; +}; + +// Thresholds for the rate control metrics. The rate mismatch thresholds are +// defined as percentages. |max_time_hit_target| is defined as number of frames, +// after a rate update is made to the encoder, for the encoder to reach within +// |kPercTargetvsActualMismatch| of new target rate. The thresholds are defined +// for each rate update sequence. +struct RateControlThresholds { + int max_num_dropped_frames; + int max_key_frame_size_mismatch; + int max_delta_frame_size_mismatch; + int max_encoding_rate_mismatch; + int max_time_hit_target; + int num_spatial_resizes; + int num_key_frames; +}; + +// Should video files be saved persistently to disk for post-run visualization? +struct VisualizationParams { + bool save_source_y4m; + bool save_encoded_ivf; + bool save_decoded_y4m; +}; + +#if !defined(WEBRTC_IOS) +const int kNumFramesShort = 100; +#endif +const int kNumFramesLong = 299; + +// Parameters from VP8 wrapper, which control target size of key frames. +const float kInitialBufferSize = 0.5f; +const float kOptimalBufferSize = 0.6f; +const float kScaleKeyFrameSize = 0.5f; + +// Integration test for video processor. Encodes+decodes a clip and +// writes it to the output directory. After completion, quality metrics +// (PSNR and SSIM) and rate control metrics are computed and compared to given +// thresholds, to verify that the quality and encoder response is acceptable. +// The rate control tests allow us to verify the behavior for changing bit rate, +// changing frame rate, frame dropping/spatial resize, and temporal layers. +// The thresholds for the rate control metrics are set to be fairly +// conservative, so failure should only happen when some significant regression +// or breakdown occurs. +class VideoProcessorIntegrationTest : public testing::Test { + protected: + VideoProcessorIntegrationTest() { +#if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) && \ + defined(WEBRTC_ANDROID) + InitializeAndroidObjects(); + + external_encoder_factory_.reset( + new webrtc_jni::MediaCodecVideoEncoderFactory()); + external_decoder_factory_.reset( + new webrtc_jni::MediaCodecVideoDecoderFactory()); +#endif + } + virtual ~VideoProcessorIntegrationTest() = default; + + void SetUpCodecConfig(const CodecParams& process, + const VisualizationParams* visualization_params) { + if (process.hw_codec) { +#if defined(WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED) +#if defined(WEBRTC_ANDROID) + // In general, external codecs should be destroyed by the factories that + // allocated them. For the particular case of the Android + // MediaCodecVideo{En,De}coderFactory's, however, it turns out that it is + // fine for the std::unique_ptr to destroy the owned codec directly. + switch (process.codec_type) { + case kVideoCodecH264: + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecH264)); + break; + case kVideoCodecVP8: + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kVp8CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecVP8)); + break; + case kVideoCodecVP9: + encoder_.reset(external_encoder_factory_->CreateVideoEncoder( + cricket::VideoCodec(cricket::kVp9CodecName))); + decoder_.reset( + external_decoder_factory_->CreateVideoDecoder(kVideoCodecVP9)); + break; + default: + RTC_NOTREACHED(); + break; + } +#elif defined(WEBRTC_IOS) + ASSERT_EQ(kVideoCodecH264, process.codec_type) + << "iOS HW codecs only support H264."; + encoder_.reset(new H264VideoToolboxEncoder( + cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset(new H264VideoToolboxDecoder()); +#else + RTC_NOTREACHED() << "Only support HW codecs on Android and iOS."; +#endif +#endif // WEBRTC_VIDEOPROCESSOR_INTEGRATIONTEST_HW_CODECS_ENABLED + RTC_CHECK(encoder_) << "HW encoder not successfully created."; + RTC_CHECK(decoder_) << "HW decoder not successfully created."; + } else { + // SW codecs. + switch (process.codec_type) { + case kVideoCodecH264: + encoder_.reset(H264Encoder::Create( + cricket::VideoCodec(cricket::kH264CodecName))); + decoder_.reset(H264Decoder::Create()); + break; + case kVideoCodecVP8: + encoder_.reset(VP8Encoder::Create()); + decoder_.reset(VP8Decoder::Create()); + break; + case kVideoCodecVP9: + encoder_.reset(VP9Encoder::Create()); + decoder_.reset(VP9Decoder::Create()); + break; + default: + RTC_NOTREACHED(); + break; + } + } + + VideoCodingModule::Codec(process.codec_type, &codec_settings_); + + // Configure input filename. + config_.input_filename = test::ResourcePath(process.filename, "yuv"); + if (process.verbose_logging) + printf("Filename: %s\n", process.filename.c_str()); + // Generate an output filename in a safe way. + config_.output_filename = test::TempFilename( + test::OutputPath(), "videoprocessor_integrationtest"); + config_.frame_length_in_bytes = + CalcBufferSize(kI420, process.width, process.height); + config_.verbose = process.verbose_logging; + config_.use_single_core = process.use_single_core; + // Key frame interval and packet loss are set for each test. + config_.keyframe_interval = process.key_frame_interval; + config_.networking_config.packet_loss_probability = + packet_loss_probability_; + + // Configure codec settings. + config_.codec_settings = &codec_settings_; + config_.codec_settings->startBitrate = start_bitrate_; + config_.codec_settings->width = process.width; + config_.codec_settings->height = process.height; + + // These features may be set depending on the test. + switch (config_.codec_settings->codecType) { + case kVideoCodecH264: + config_.codec_settings->H264()->frameDroppingOn = + process.frame_dropper_on; + config_.codec_settings->H264()->keyFrameInterval = + kBaseKeyFrameInterval; + break; + case kVideoCodecVP8: + config_.codec_settings->VP8()->errorConcealmentOn = + process.error_concealment_on; + config_.codec_settings->VP8()->denoisingOn = process.denoising_on; + config_.codec_settings->VP8()->numberOfTemporalLayers = + num_temporal_layers_; + config_.codec_settings->VP8()->frameDroppingOn = + process.frame_dropper_on; + config_.codec_settings->VP8()->automaticResizeOn = + process.spatial_resize_on; + config_.codec_settings->VP8()->keyFrameInterval = kBaseKeyFrameInterval; + break; + case kVideoCodecVP9: + config_.codec_settings->VP9()->denoisingOn = process.denoising_on; + config_.codec_settings->VP9()->numberOfTemporalLayers = + num_temporal_layers_; + config_.codec_settings->VP9()->frameDroppingOn = + process.frame_dropper_on; + config_.codec_settings->VP9()->automaticResizeOn = + process.spatial_resize_on; + config_.codec_settings->VP9()->keyFrameInterval = kBaseKeyFrameInterval; + break; + default: + RTC_NOTREACHED(); + break; + } + + // Create file objects for quality analysis. + analysis_frame_reader_.reset(new test::YuvFrameReaderImpl( + config_.input_filename, config_.codec_settings->width, + config_.codec_settings->height)); + analysis_frame_writer_.reset(new test::YuvFrameWriterImpl( + config_.output_filename, config_.codec_settings->width, + config_.codec_settings->height)); + RTC_CHECK(analysis_frame_reader_->Init()); + RTC_CHECK(analysis_frame_writer_->Init()); + + if (visualization_params) { + // clang-format off + const std::string output_filename_base = + test::OutputPath() + process.filename + + "_cd-" + CodecTypeToPayloadName(process.codec_type).value_or("") + + "_hw-" + std::to_string(process.hw_codec) + + "_fr-" + std::to_string(start_frame_rate_) + + "_br-" + std::to_string(static_cast(start_bitrate_)); + // clang-format on + if (visualization_params->save_source_y4m) { + source_frame_writer_.reset(new test::Y4mFrameWriterImpl( + output_filename_base + "_source.y4m", config_.codec_settings->width, + config_.codec_settings->height, start_frame_rate_)); + RTC_CHECK(source_frame_writer_->Init()); + } + if (visualization_params->save_encoded_ivf) { + rtc::File post_encode_file = + rtc::File::Create(output_filename_base + "_encoded.ivf"); + encoded_frame_writer_ = + IvfFileWriter::Wrap(std::move(post_encode_file), 0); + } + if (visualization_params->save_decoded_y4m) { + decoded_frame_writer_.reset(new test::Y4mFrameWriterImpl( + output_filename_base + "_decoded.y4m", + config_.codec_settings->width, config_.codec_settings->height, + start_frame_rate_)); + RTC_CHECK(decoded_frame_writer_->Init()); + } + } + + packet_manipulator_.reset(new test::PacketManipulatorImpl( + &packet_reader_, config_.networking_config, config_.verbose)); + processor_.reset(new test::VideoProcessorImpl( + encoder_.get(), decoder_.get(), analysis_frame_reader_.get(), + analysis_frame_writer_.get(), packet_manipulator_.get(), config_, + &stats_, source_frame_writer_.get(), encoded_frame_writer_.get(), + decoded_frame_writer_.get())); + RTC_CHECK(processor_->Init()); + } + + // Reset quantities after each encoder update, update the target + // per-frame bandwidth. + void ResetRateControlMetrics(int num_frames) { + for (int i = 0; i < num_temporal_layers_; i++) { + num_frames_per_update_[i] = 0; + sum_frame_size_mismatch_[i] = 0.0f; + sum_encoded_frame_size_[i] = 0.0f; + encoding_bitrate_[i] = 0.0f; + // Update layer per-frame-bandwidth. + per_frame_bandwidth_[i] = static_cast(bit_rate_layer_[i]) / + static_cast(frame_rate_layer_[i]); + } + // Set maximum size of key frames, following setting in the VP8 wrapper. + float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * frame_rate_; + // We don't know exact target size of the key frames (except for first one), + // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is + // set by |max_key_size_ * per_frame_bandwidth|. Take middle point/average + // as reference for mismatch. Note key frames always correspond to base + // layer frame in this test. + target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0]; + num_frames_total_ = 0; + sum_encoded_frame_size_total_ = 0.0f; + encoding_bitrate_total_ = 0.0f; + perc_encoding_rate_mismatch_ = 0.0f; + num_frames_to_hit_target_ = num_frames; + encoding_rate_within_target_ = false; + sum_key_frame_size_mismatch_ = 0.0; + num_key_frames_ = 0; + } + + // For every encoded frame, update the rate control metrics. + void UpdateRateControlMetrics(int frame_num, FrameType frame_type) { + float encoded_size_kbits = processor_->EncodedFrameSize() * 8.0f / 1000.0f; + // Update layer data. + // Update rate mismatch relative to per-frame bandwidth for delta frames. + if (frame_type == kVideoFrameDelta) { + // TODO(marpan): Should we count dropped (zero size) frames in mismatch? + sum_frame_size_mismatch_[layer_] += + fabs(encoded_size_kbits - per_frame_bandwidth_[layer_]) / + per_frame_bandwidth_[layer_]; + } else { + float target_size = (frame_num == 1) ? target_size_key_frame_initial_ + : target_size_key_frame_; + sum_key_frame_size_mismatch_ += + fabs(encoded_size_kbits - target_size) / target_size; + num_key_frames_ += 1; + } + sum_encoded_frame_size_[layer_] += encoded_size_kbits; + // Encoding bitrate per layer: from the start of the update/run to the + // current frame. + encoding_bitrate_[layer_] = sum_encoded_frame_size_[layer_] * + frame_rate_layer_[layer_] / + num_frames_per_update_[layer_]; + // Total encoding rate: from the start of the update/run to current frame. + sum_encoded_frame_size_total_ += encoded_size_kbits; + encoding_bitrate_total_ = + sum_encoded_frame_size_total_ * frame_rate_ / num_frames_total_; + perc_encoding_rate_mismatch_ = + 100 * fabs(encoding_bitrate_total_ - bit_rate_) / bit_rate_; + if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch && + !encoding_rate_within_target_) { + num_frames_to_hit_target_ = num_frames_total_; + encoding_rate_within_target_ = true; + } + } + + // Verify expected behavior of rate control and print out data. + void VerifyRateControlMetrics(int update_index, + int max_key_frame_size_mismatch, + int max_delta_frame_size_mismatch, + int max_encoding_rate_mismatch, + int max_time_hit_target, + int max_num_dropped_frames, + int num_spatial_resizes, + int num_key_frames) { + int num_dropped_frames = processor_->NumberDroppedFrames(); + int num_resize_actions = processor_->NumberSpatialResizes(); + printf( + "For update #: %d,\n" + " Target Bitrate: %d,\n" + " Encoding bitrate: %f,\n" + " Frame rate: %d \n", + update_index, bit_rate_, encoding_bitrate_total_, frame_rate_); + printf( + " Number of frames to approach target rate: %d, \n" + " Number of dropped frames: %d, \n" + " Number of spatial resizes: %d, \n", + num_frames_to_hit_target_, num_dropped_frames, num_resize_actions); + EXPECT_LE(perc_encoding_rate_mismatch_, max_encoding_rate_mismatch); + if (num_key_frames_ > 0) { + int perc_key_frame_size_mismatch = + 100 * sum_key_frame_size_mismatch_ / num_key_frames_; + printf( + " Number of Key frames: %d \n" + " Key frame rate mismatch: %d \n", + num_key_frames_, perc_key_frame_size_mismatch); + EXPECT_LE(perc_key_frame_size_mismatch, max_key_frame_size_mismatch); + } + printf("\n"); + printf("Rates statistics for Layer data \n"); + for (int i = 0; i < num_temporal_layers_; i++) { + printf("Temporal layer #%d \n", i); + int perc_frame_size_mismatch = + 100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i]; + int perc_encoding_rate_mismatch = + 100 * fabs(encoding_bitrate_[i] - bit_rate_layer_[i]) / + bit_rate_layer_[i]; + printf( + " Target Layer Bit rate: %f \n" + " Layer frame rate: %f, \n" + " Layer per frame bandwidth: %f, \n" + " Layer Encoding bit rate: %f, \n" + " Layer Percent frame size mismatch: %d, \n" + " Layer Percent encoding rate mismatch: %d, \n" + " Number of frame processed per layer: %d \n", + bit_rate_layer_[i], frame_rate_layer_[i], per_frame_bandwidth_[i], + encoding_bitrate_[i], perc_frame_size_mismatch, + perc_encoding_rate_mismatch, num_frames_per_update_[i]); + EXPECT_LE(perc_frame_size_mismatch, max_delta_frame_size_mismatch); + EXPECT_LE(perc_encoding_rate_mismatch, max_encoding_rate_mismatch); + } + printf("\n"); + EXPECT_LE(num_frames_to_hit_target_, max_time_hit_target); + EXPECT_LE(num_dropped_frames, max_num_dropped_frames); + EXPECT_EQ(num_resize_actions, num_spatial_resizes); + EXPECT_EQ(num_key_frames_, num_key_frames); + } + + void VerifyQuality(const test::QualityMetricsResult& psnr_result, + const test::QualityMetricsResult& ssim_result, + const QualityThresholds& quality_thresholds) { + EXPECT_GT(psnr_result.average, quality_thresholds.min_avg_psnr); + EXPECT_GT(psnr_result.min, quality_thresholds.min_min_psnr); + EXPECT_GT(ssim_result.average, quality_thresholds.min_avg_ssim); + EXPECT_GT(ssim_result.min, quality_thresholds.min_min_ssim); + } + + // Layer index corresponding to frame number, for up to 3 layers. + void LayerIndexForFrame(int frame_number) { + if (num_temporal_layers_ == 1) { + layer_ = 0; + } else if (num_temporal_layers_ == 2) { + // layer 0: 0 2 4 ... + // layer 1: 1 3 + if (frame_number % 2 == 0) { + layer_ = 0; + } else { + layer_ = 1; + } + } else if (num_temporal_layers_ == 3) { + // layer 0: 0 4 8 ... + // layer 1: 2 6 + // layer 2: 1 3 5 7 + if (frame_number % 4 == 0) { + layer_ = 0; + } else if ((frame_number + 2) % 4 == 0) { + layer_ = 1; + } else if ((frame_number + 1) % 2 == 0) { + layer_ = 2; + } + } else { + RTC_NOTREACHED() << "Max 3 layers are supported."; + } + } + + // Set the bitrate and frame rate per layer, for up to 3 layers. + void SetLayerRates() { + RTC_DCHECK_LE(num_temporal_layers_, 3); + for (int i = 0; i < num_temporal_layers_; i++) { + float bit_rate_ratio = + kVp8LayerRateAlloction[num_temporal_layers_ - 1][i]; + if (i > 0) { + float bit_rate_delta_ratio = + kVp8LayerRateAlloction[num_temporal_layers_ - 1][i] - + kVp8LayerRateAlloction[num_temporal_layers_ - 1][i - 1]; + bit_rate_layer_[i] = bit_rate_ * bit_rate_delta_ratio; + } else { + bit_rate_layer_[i] = bit_rate_ * bit_rate_ratio; + } + frame_rate_layer_[i] = + frame_rate_ / static_cast(1 << (num_temporal_layers_ - 1)); + } + if (num_temporal_layers_ == 3) { + frame_rate_layer_[2] = frame_rate_ / 2.0f; + } + } + + // Processes all frames in the clip and verifies the result. + void ProcessFramesAndVerify(QualityThresholds quality_thresholds, + RateProfile rate_profile, + CodecParams process, + RateControlThresholds* rc_thresholds, + const VisualizationParams* visualization_params) { + // Codec/config settings. + start_bitrate_ = rate_profile.target_bit_rate[0]; + start_frame_rate_ = rate_profile.input_frame_rate[0]; + packet_loss_probability_ = process.packet_loss_probability; + num_temporal_layers_ = process.num_temporal_layers; + SetUpCodecConfig(process, visualization_params); + // Update the layers and the codec with the initial rates. + bit_rate_ = rate_profile.target_bit_rate[0]; + frame_rate_ = rate_profile.input_frame_rate[0]; + SetLayerRates(); + // Set the initial target size for key frame. + target_size_key_frame_initial_ = + 0.5 * kInitialBufferSize * bit_rate_layer_[0]; + processor_->SetRates(bit_rate_, frame_rate_); + + // Process each frame, up to |num_frames|. + int num_frames = rate_profile.num_frames; + int update_index = 0; + ResetRateControlMetrics( + rate_profile.frame_index_rate_update[update_index + 1]); + int frame_number = 0; + FrameType frame_type = kVideoFrameDelta; + while (processor_->ProcessFrame(frame_number) && + frame_number < num_frames) { + // Get the layer index for the frame |frame_number|. + LayerIndexForFrame(frame_number); + // Get the frame_type. + frame_type = processor_->EncodedFrameType(); + // Counter for whole sequence run. + ++frame_number; + // Counters for each rate update. + ++num_frames_per_update_[layer_]; + ++num_frames_total_; + UpdateRateControlMetrics(frame_number, frame_type); + // If we hit another/next update, verify stats for current state and + // update layers and codec with new rates. + if (frame_number == + rate_profile.frame_index_rate_update[update_index + 1]) { + VerifyRateControlMetrics( + update_index, + rc_thresholds[update_index].max_key_frame_size_mismatch, + rc_thresholds[update_index].max_delta_frame_size_mismatch, + rc_thresholds[update_index].max_encoding_rate_mismatch, + rc_thresholds[update_index].max_time_hit_target, + rc_thresholds[update_index].max_num_dropped_frames, + rc_thresholds[update_index].num_spatial_resizes, + rc_thresholds[update_index].num_key_frames); + // Update layer rates and the codec with new rates. + ++update_index; + bit_rate_ = rate_profile.target_bit_rate[update_index]; + frame_rate_ = rate_profile.input_frame_rate[update_index]; + SetLayerRates(); + ResetRateControlMetrics( + rate_profile.frame_index_rate_update[update_index + 1]); + processor_->SetRates(bit_rate_, frame_rate_); + } + } + VerifyRateControlMetrics( + update_index, rc_thresholds[update_index].max_key_frame_size_mismatch, + rc_thresholds[update_index].max_delta_frame_size_mismatch, + rc_thresholds[update_index].max_encoding_rate_mismatch, + rc_thresholds[update_index].max_time_hit_target, + rc_thresholds[update_index].max_num_dropped_frames, + rc_thresholds[update_index].num_spatial_resizes, + rc_thresholds[update_index].num_key_frames); + EXPECT_EQ(num_frames, frame_number); + EXPECT_EQ(num_frames + 1, static_cast(stats_.stats_.size())); + + // Release encoder and decoder to make sure they have finished processing: + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release()); + + // Close the analysis files before we use them for SSIM/PSNR calculations. + analysis_frame_reader_->Close(); + analysis_frame_writer_->Close(); + + // Close visualization files. + if (source_frame_writer_) { + source_frame_writer_->Close(); + } + if (encoded_frame_writer_) { + encoded_frame_writer_->Close(); + } + if (decoded_frame_writer_) { + decoded_frame_writer_->Close(); + } + + // TODO(marpan): Should compute these quality metrics per SetRates update. + test::QualityMetricsResult psnr_result, ssim_result; + EXPECT_EQ(0, test::I420MetricsFromFiles(config_.input_filename.c_str(), + config_.output_filename.c_str(), + config_.codec_settings->width, + config_.codec_settings->height, + &psnr_result, &ssim_result)); + printf("PSNR avg: %f, min: %f\nSSIM avg: %f, min: %f\n", + psnr_result.average, psnr_result.min, ssim_result.average, + ssim_result.min); + stats_.PrintSummary(); + VerifyQuality(psnr_result, ssim_result, quality_thresholds); + + // Remove analysis file. + if (remove(config_.output_filename.c_str()) < 0) { + fprintf(stderr, "Failed to remove temporary file!\n"); + } + } + + static void SetCodecParams(CodecParams* process_settings, + VideoCodecType codec_type, + bool hw_codec, + bool use_single_core, + float packet_loss_probability, + int key_frame_interval, + int num_temporal_layers, + bool error_concealment_on, + bool denoising_on, + bool frame_dropper_on, + bool spatial_resize_on, + int width, + int height, + const std::string& filename, + bool verbose_logging) { + process_settings->codec_type = codec_type; + process_settings->hw_codec = hw_codec; + process_settings->use_single_core = use_single_core; + process_settings->packet_loss_probability = packet_loss_probability; + process_settings->key_frame_interval = key_frame_interval; + process_settings->num_temporal_layers = num_temporal_layers, + process_settings->error_concealment_on = error_concealment_on; + process_settings->denoising_on = denoising_on; + process_settings->frame_dropper_on = frame_dropper_on; + process_settings->spatial_resize_on = spatial_resize_on; + process_settings->width = width; + process_settings->height = height; + process_settings->filename = filename; + process_settings->verbose_logging = verbose_logging; + } + + static void SetCodecParams(CodecParams* process_settings, + VideoCodecType codec_type, + bool hw_codec, + bool use_single_core, + float packet_loss_probability, + int key_frame_interval, + int num_temporal_layers, + bool error_concealment_on, + bool denoising_on, + bool frame_dropper_on, + bool spatial_resize_on) { + SetCodecParams(process_settings, codec_type, hw_codec, use_single_core, + packet_loss_probability, key_frame_interval, + num_temporal_layers, error_concealment_on, denoising_on, + frame_dropper_on, spatial_resize_on, kCifWidth, kCifHeight, + kFilenameForemanCif, false /* verbose_logging */); + } + + static void SetQualityThresholds(QualityThresholds* quality_thresholds, + double min_avg_psnr, + double min_min_psnr, + double min_avg_ssim, + double min_min_ssim) { + quality_thresholds->min_avg_psnr = min_avg_psnr; + quality_thresholds->min_min_psnr = min_min_psnr; + quality_thresholds->min_avg_ssim = min_avg_ssim; + quality_thresholds->min_min_ssim = min_min_ssim; + } + + static void SetRateProfile(RateProfile* rate_profile, + int update_index, + int bit_rate, + int frame_rate, + int frame_index_rate_update) { + rate_profile->target_bit_rate[update_index] = bit_rate; + rate_profile->input_frame_rate[update_index] = frame_rate; + rate_profile->frame_index_rate_update[update_index] = + frame_index_rate_update; + } + + static void SetRateControlThresholds(RateControlThresholds* rc_thresholds, + int update_index, + int max_num_dropped_frames, + int max_key_frame_size_mismatch, + int max_delta_frame_size_mismatch, + int max_encoding_rate_mismatch, + int max_time_hit_target, + int num_spatial_resizes, + int num_key_frames) { + rc_thresholds[update_index].max_num_dropped_frames = max_num_dropped_frames; + rc_thresholds[update_index].max_key_frame_size_mismatch = + max_key_frame_size_mismatch; + rc_thresholds[update_index].max_delta_frame_size_mismatch = + max_delta_frame_size_mismatch; + rc_thresholds[update_index].max_encoding_rate_mismatch = + max_encoding_rate_mismatch; + rc_thresholds[update_index].max_time_hit_target = max_time_hit_target; + rc_thresholds[update_index].num_spatial_resizes = num_spatial_resizes; + rc_thresholds[update_index].num_key_frames = num_key_frames; + } + + // Codecs. + std::unique_ptr encoder_; + std::unique_ptr external_encoder_factory_; + std::unique_ptr decoder_; + std::unique_ptr external_decoder_factory_; + VideoCodec codec_settings_; + + // Helper objects. + std::unique_ptr analysis_frame_reader_; + std::unique_ptr analysis_frame_writer_; + test::PacketReader packet_reader_; + std::unique_ptr packet_manipulator_; + test::Stats stats_; + test::TestConfig config_; + // Must be destroyed before |encoder_| and |decoder_|. + std::unique_ptr processor_; + + // Visualization objects. + std::unique_ptr source_frame_writer_; + std::unique_ptr encoded_frame_writer_; + std::unique_ptr decoded_frame_writer_; + + // Quantities defined/updated for every encoder rate update. + // Some quantities defined per temporal layer (at most 3 layers in this test). + int num_frames_per_update_[3]; + float sum_frame_size_mismatch_[3]; + float sum_encoded_frame_size_[3]; + float encoding_bitrate_[3]; + float per_frame_bandwidth_[3]; + float bit_rate_layer_[3]; + float frame_rate_layer_[3]; + int num_frames_total_; + float sum_encoded_frame_size_total_; + float encoding_bitrate_total_; + float perc_encoding_rate_mismatch_; + int num_frames_to_hit_target_; + bool encoding_rate_within_target_; + int bit_rate_; + int frame_rate_; + int layer_; + float target_size_key_frame_initial_; + float target_size_key_frame_; + float sum_key_frame_size_mismatch_; + int num_key_frames_; + float start_bitrate_; + int start_frame_rate_; + + // Codec and network settings. + float packet_loss_probability_; + int num_temporal_layers_; +}; + +} // namespace test +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_TEST_VIDEOPROCESSOR_INTEGRATIONTEST_H_ diff --git a/include/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h b/include/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h index 19846ba..0cd0b06 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h @@ -12,8 +12,12 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_DEFAULT_TEMPORAL_LAYERS_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_DEFAULT_TEMPORAL_LAYERS_H_ +#include + #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" +#include "webrtc/base/optional.h" + namespace webrtc { class DefaultTemporalLayers : public TemporalLayers { @@ -26,10 +30,13 @@ class DefaultTemporalLayers : public TemporalLayers { // and/or update the reference buffers. int EncodeFlags(uint32_t timestamp) override; - bool ConfigureBitrates(int bitrate_kbit, - int max_bitrate_kbit, - int framerate, - vpx_codec_enc_cfg_t* cfg) override; + // Update state based on new bitrate target and incoming framerate. + // Returns the bitrate allocation for the active temporal layers. + std::vector OnRatesUpdated(int bitrate_kbps, + int max_bitrate_kbps, + int framerate) override; + + bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override; void PopulateCodecSpecific(bool base_layer_sync, CodecSpecificInfoVP8* vp8_info, @@ -37,8 +44,6 @@ class DefaultTemporalLayers : public TemporalLayers { void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {} - bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override { return false; } - int CurrentLayerId() const override; private: @@ -77,7 +82,7 @@ class DefaultTemporalLayers : public TemporalLayers { }; enum { kMaxTemporalPattern = 16 }; - int number_of_temporal_layers_; + const int number_of_temporal_layers_; int temporal_ids_length_; int temporal_ids_[kMaxTemporalPattern]; int temporal_pattern_length_; @@ -86,6 +91,7 @@ class DefaultTemporalLayers : public TemporalLayers { uint8_t pattern_idx_; uint32_t timestamp_; bool last_base_layer_sync_; + rtc::Optional> new_bitrates_kbps_; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/codecs/vp8/include/vp8_globals.h b/include/webrtc/modules/video_coding/codecs/vp8/include/vp8_globals.h new file mode 100644 index 0000000..938e199 --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/vp8/include/vp8_globals.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains codec dependent definitions that are needed in +// order to compile the WebRTC codebase, even if this codec is not used. + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_GLOBALS_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_GLOBALS_H_ + +#include "webrtc/modules/video_coding/codecs/interface/common_constants.h" + +namespace webrtc { + +struct RTPVideoHeaderVP8 { + void InitRTPVideoHeaderVP8() { + nonReference = false; + pictureId = kNoPictureId; + tl0PicIdx = kNoTl0PicIdx; + temporalIdx = kNoTemporalIdx; + layerSync = false; + keyIdx = kNoKeyIdx; + partitionId = 0; + beginningOfPartition = false; + } + + bool nonReference; // Frame is discardable. + int16_t pictureId; // Picture ID index, 15 bits; + // kNoPictureId if PictureID does not exist. + int16_t tl0PicIdx; // TL0PIC_IDX, 8 bits; + // kNoTl0PicIdx means no value provided. + uint8_t temporalIdx; // Temporal layer index, or kNoTemporalIdx. + bool layerSync; // This frame is a layer sync frame. + // Disabled if temporalIdx == kNoTemporalIdx. + int keyIdx; // 5 bits; kNoKeyIdx means not used. + int partitionId; // VP8 partition ID + bool beginningOfPartition; // True if this packet is the first + // in a VP8 partition. Otherwise false +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_INCLUDE_VP8_GLOBALS_H_ diff --git a/include/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h b/include/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h index 8392bc4..53818a2 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h @@ -9,10 +9,9 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SCREENSHARE_LAYERS_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SCREENSHARE_LAYERS_H_ -#include - -#include "vpx/vpx_encoder.h" +#include +#include "webrtc/base/rate_statistics.h" #include "webrtc/base/timeutils.h" #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" #include "webrtc/modules/video_coding/utility/frame_dropper.h" @@ -41,10 +40,15 @@ class ScreenshareLayers : public TemporalLayers { // and/or update the reference buffers. int EncodeFlags(uint32_t timestamp) override; - bool ConfigureBitrates(int bitrate_kbps, - int max_bitrate_kbps, - int framerate, - vpx_codec_enc_cfg_t* cfg) override; + // Update state based on new bitrate target and incoming framerate. + // Returns the bitrate allocation for the active temporal layers. + std::vector OnRatesUpdated(int bitrate_kbps, + int max_bitrate_kbps, + int framerate) override; + + // Update the encoder configuration with target bitrates or other parameters. + // Returns true iff the configuration was actually modified. + bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override; void PopulateCodecSpecific(bool base_layer_sync, CodecSpecificInfoVP8* vp8_info, @@ -54,13 +58,9 @@ class ScreenshareLayers : public TemporalLayers { int CurrentLayerId() const override; - // Allows the layers adapter to update the encoder configuration prior to a - // frame being encoded. Return true if the configuration should be updated - // and false if now change is needed. - bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override; - private: bool TimeToSync(int64_t timestamp) const; + uint32_t GetCodecTargetBitrateKbps() const; Clock* const clock_; @@ -75,9 +75,16 @@ class ScreenshareLayers : public TemporalLayers { int min_qp_; int max_qp_; uint32_t max_debt_bytes_; - int frame_rate_; - static const int kMaxNumTemporalLayers = 2; + // Configured max framerate. + rtc::Optional target_framerate_; + // Incoming framerate from capturer. + rtc::Optional capture_framerate_; + // Tracks what framerate we actually encode, and drops frames on overshoot. + RateStatistics encode_framerate_; + bool bitrate_updated_; + + static constexpr int kMaxNumTemporalLayers = 2; struct TemporalLayer { TemporalLayer() : state(State::kNormal), diff --git a/include/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h b/include/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h index fca16df..2be8779 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h @@ -20,6 +20,8 @@ namespace webrtc { +class SimulcastRateAllocator; + class VideoEncoderFactory { public: virtual VideoEncoder* Create() = 0; @@ -46,17 +48,19 @@ class SimulcastEncoderAdapter : public VP8Encoder { const std::vector* frame_types) override; int RegisterEncodeCompleteCallback(EncodedImageCallback* callback) override; int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; - int SetRates(uint32_t new_bitrate_kbit, uint32_t new_framerate) override; + int SetRateAllocation(const BitrateAllocation& bitrate, + uint32_t new_framerate) override; // Eventual handler for the contained encoders' EncodedImageCallbacks, but // called from an internal helper that also knows the correct stream // index. - int32_t Encoded(size_t stream_idx, - const EncodedImage& encodedImage, - const CodecSpecificInfo* codecSpecificInfo = NULL, - const RTPFragmentationHeader* fragmentation = NULL); + EncodedImageCallback::Result OnEncodedImage( + size_t stream_idx, + const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info, + const RTPFragmentationHeader* fragmentation); - void OnDroppedFrame() override; + VideoEncoder::ScalingSettings GetScalingSettings() const override; bool SupportsNativeHandle() const override; const char* ImplementationName() const override; @@ -90,27 +94,16 @@ class SimulcastEncoderAdapter : public VP8Encoder { bool send_stream; }; - // Get the stream bitrate, for the stream |stream_idx|, given the bitrate - // |new_bitrate_kbit| and the actual configured stream count in - // |total_number_of_streams|. The function also returns whether there's enough - // bandwidth to send this stream via |send_stream|. - uint32_t GetStreamBitrate(int stream_idx, - size_t total_number_of_streams, - uint32_t new_bitrate_kbit, - bool* send_stream) const; - // Populate the codec settings for each stream. void PopulateStreamCodec(const webrtc::VideoCodec* inst, int stream_index, - size_t total_number_of_streams, + uint32_t start_bitrate_kbps, bool highest_resolution_stream, - webrtc::VideoCodec* stream_codec, - bool* send_stream); + webrtc::VideoCodec* stream_codec); bool Initialized() const; std::unique_ptr factory_; - std::unique_ptr screensharing_tl_factory_; VideoCodec codec_; std::vector streaminfos_; EncodedImageCallback* encoded_complete_callback_; diff --git a/include/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h b/include/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h index b277ad2..fb59646 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/simulcast_unittest.h @@ -12,15 +12,19 @@ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_UNITTEST_H_ #include +#include #include #include -#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/api/video/i420_buffer.h" +#include "webrtc/api/video/video_frame.h" #include "webrtc/base/checks.h" #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h" #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" +#include "webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h" +#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" +#include "webrtc/test/gtest.h" #include "webrtc/video_frame.h" using ::testing::_; @@ -49,6 +53,13 @@ void SetExpectedValues3(T value0, T value1, T value2, T* expected_values) { expected_values[2] = value2; } +enum PlaneType { + kYPlane = 0, + kUPlane = 1, + kVPlane = 2, + kNumOfPlanes = 3, +}; + class Vp8TestEncodedImageCallback : public EncodedImageCallback { public: Vp8TestEncodedImageCallback() : picture_id_(-1) { @@ -61,9 +72,9 @@ class Vp8TestEncodedImageCallback : public EncodedImageCallback { delete[] encoded_frame_._buffer; } - virtual int32_t Encoded(const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific_info, - const RTPFragmentationHeader* fragmentation) { + virtual Result OnEncodedImage(const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info, + const RTPFragmentationHeader* fragmentation) { // Only store the base layer. if (codec_specific_info->codecSpecific.VP8.simulcastIdx == 0) { if (encoded_image._frameType == kVideoFrameKey) { @@ -89,7 +100,7 @@ class Vp8TestEncodedImageCallback : public EncodedImageCallback { codec_specific_info->codecSpecific.VP8.layerSync; temporal_layer_[codec_specific_info->codecSpecific.VP8.simulcastIdx] = codec_specific_info->codecSpecific.VP8.temporalIdx; - return 0; + return Result(Result::OK, encoded_image._timeStamp); } void GetLastEncodedFrameInfo(int* picture_id, int* temporal_layer, @@ -134,89 +145,17 @@ class Vp8TestDecodedImageCallback : public DecodedImageCallback { RTC_NOTREACHED(); return -1; } + void Decoded(VideoFrame& decoded_image, + rtc::Optional decode_time_ms, + rtc::Optional qp) override { + Decoded(decoded_image); + } int DecodedFrames() { return decoded_frames_; } private: int decoded_frames_; }; -class SkipEncodingUnusedStreamsTest { - public: - std::vector RunTest(VP8Encoder* encoder, - VideoCodec* settings, - uint32_t target_bitrate) { - SpyingTemporalLayersFactory spy_factory; - settings->codecSpecific.VP8.tl_factory = &spy_factory; - EXPECT_EQ(0, encoder->InitEncode(settings, 1, 1200)); - - encoder->SetRates(target_bitrate, 30); - - std::vector configured_bitrates; - for (std::vector::const_iterator it = - spy_factory.spying_layers_.begin(); - it != spy_factory.spying_layers_.end(); ++it) { - configured_bitrates.push_back( - static_cast(*it)->configured_bitrate_); - } - return configured_bitrates; - } - - class SpyingTemporalLayers : public TemporalLayers { - public: - explicit SpyingTemporalLayers(TemporalLayers* layers) - : configured_bitrate_(0), layers_(layers) {} - - virtual ~SpyingTemporalLayers() { delete layers_; } - - int EncodeFlags(uint32_t timestamp) override { - return layers_->EncodeFlags(timestamp); - } - - bool ConfigureBitrates(int bitrate_kbit, - int max_bitrate_kbit, - int framerate, - vpx_codec_enc_cfg_t* cfg) override { - configured_bitrate_ = bitrate_kbit; - return layers_->ConfigureBitrates(bitrate_kbit, max_bitrate_kbit, - framerate, cfg); - } - - void PopulateCodecSpecific(bool base_layer_sync, - CodecSpecificInfoVP8* vp8_info, - uint32_t timestamp) override { - layers_->PopulateCodecSpecific(base_layer_sync, vp8_info, timestamp); - } - - void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override { - layers_->FrameEncoded(size, timestamp, qp); - } - - int CurrentLayerId() const override { return layers_->CurrentLayerId(); } - - bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override { - return false; - } - - int configured_bitrate_; - TemporalLayers* layers_; - }; - - class SpyingTemporalLayersFactory : public TemporalLayersFactory { - public: - virtual ~SpyingTemporalLayersFactory() {} - TemporalLayers* Create(int temporal_layers, - uint8_t initial_tl0_pic_idx) const override { - SpyingTemporalLayers* layers = - new SpyingTemporalLayers(TemporalLayersFactory::Create( - temporal_layers, initial_tl0_pic_idx)); - spying_layers_.push_back(layers); - return layers; - } - - mutable std::vector spying_layers_; - }; -}; - class TestVp8Simulcast : public ::testing::Test { public: TestVp8Simulcast(VP8Encoder* encoder, VP8Decoder* decoder) @@ -236,8 +175,8 @@ class TestVp8Simulcast : public ::testing::Test { } } - // Fills in an VideoFrameBuffer from |plane_colors|. - static void CreateImage(const rtc::scoped_refptr& buffer, + // Fills in an I420Buffer from |plane_colors|. + static void CreateImage(const rtc::scoped_refptr& buffer, int plane_colors[kNumOfPlanes]) { int width = buffer->width(); int height = buffer->height(); @@ -258,7 +197,7 @@ class TestVp8Simulcast : public ::testing::Test { static void DefaultSettings(VideoCodec* settings, const int* temporal_layer_profile) { - assert(settings); + RTC_CHECK(settings); memset(settings, 0, sizeof(VideoCodec)); strncpy(settings->plName, "VP8", 4); settings->codecType = kVideoCodecVP8; @@ -281,13 +220,13 @@ class TestVp8Simulcast : public ::testing::Test { ConfigureStream(kDefaultWidth, kDefaultHeight, kMaxBitrates[2], kMinBitrates[2], kTargetBitrates[2], &settings->simulcastStream[2], temporal_layer_profile[2]); - settings->codecSpecific.VP8.resilience = kResilientStream; - settings->codecSpecific.VP8.denoisingOn = true; - settings->codecSpecific.VP8.errorConcealmentOn = false; - settings->codecSpecific.VP8.automaticResizeOn = false; - settings->codecSpecific.VP8.feedbackModeOn = false; - settings->codecSpecific.VP8.frameDroppingOn = true; - settings->codecSpecific.VP8.keyFrameInterval = 3000; + settings->VP8()->resilience = kResilientStream; + settings->VP8()->denoisingOn = true; + settings->VP8()->errorConcealmentOn = false; + settings->VP8()->automaticResizeOn = false; + settings->VP8()->feedbackModeOn = false; + settings->VP8()->frameDroppingOn = true; + settings->VP8()->keyFrameInterval = 3000; } static void ConfigureStream(int width, @@ -308,28 +247,38 @@ class TestVp8Simulcast : public ::testing::Test { } protected: - virtual void SetUp() { SetUpCodec(kDefaultTemporalLayerProfile); } + void SetUp() override { SetUpCodec(kDefaultTemporalLayerProfile); } - virtual void SetUpCodec(const int* temporal_layer_profile) { + void TearDown() override { + encoder_->Release(); + decoder_->Release(); + } + + void SetUpCodec(const int* temporal_layer_profile) { encoder_->RegisterEncodeCompleteCallback(&encoder_callback_); decoder_->RegisterDecodeCompleteCallback(&decoder_callback_); DefaultSettings(&settings_, temporal_layer_profile); + SetUpRateAllocator(); EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1)); int half_width = (kDefaultWidth + 1) / 2; - input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, kDefaultWidth, - half_width, half_width); - memset(input_frame_.video_frame_buffer()->MutableDataY(), 0, - input_frame_.allocated_size(kYPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataU(), 0, - input_frame_.allocated_size(kUPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataV(), 0, - input_frame_.allocated_size(kVPlane)); + input_buffer_ = I420Buffer::Create(kDefaultWidth, kDefaultHeight, + kDefaultWidth, half_width, half_width); + input_buffer_->InitializeData(); + input_frame_.reset( + new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0)); } - virtual void TearDown() { - encoder_->Release(); - decoder_->Release(); + void SetUpRateAllocator() { + TemporalLayersFactory* tl_factory = new TemporalLayersFactory(); + rate_allocator_.reset(new SimulcastRateAllocator( + settings_, std::unique_ptr(tl_factory))); + settings_.VP8()->tl_factory = tl_factory; + } + + void SetRates(uint32_t bitrate_kbps, uint32_t fps) { + encoder_->SetRateAllocation( + rate_allocator_->GetAllocation(bitrate_kbps * 1000, fps), fps); } void ExpectStreams(FrameType frame_type, int expected_video_streams) { @@ -338,34 +287,38 @@ class TestVp8Simulcast : public ::testing::Test { if (expected_video_streams >= 1) { EXPECT_CALL( encoder_callback_, - Encoded( + OnEncodedImage( AllOf(Field(&EncodedImage::_frameType, frame_type), Field(&EncodedImage::_encodedWidth, kDefaultWidth / 4), Field(&EncodedImage::_encodedHeight, kDefaultHeight / 4)), _, _)) .Times(1) - .WillRepeatedly(Return(0)); + .WillRepeatedly(Return(EncodedImageCallback::Result( + EncodedImageCallback::Result::OK, 0))); } if (expected_video_streams >= 2) { EXPECT_CALL( encoder_callback_, - Encoded( + OnEncodedImage( AllOf(Field(&EncodedImage::_frameType, frame_type), Field(&EncodedImage::_encodedWidth, kDefaultWidth / 2), Field(&EncodedImage::_encodedHeight, kDefaultHeight / 2)), _, _)) .Times(1) - .WillRepeatedly(Return(0)); + .WillRepeatedly(Return(EncodedImageCallback::Result( + EncodedImageCallback::Result::OK, 0))); } if (expected_video_streams >= 3) { EXPECT_CALL( encoder_callback_, - Encoded(AllOf(Field(&EncodedImage::_frameType, frame_type), - Field(&EncodedImage::_encodedWidth, kDefaultWidth), - Field(&EncodedImage::_encodedHeight, kDefaultHeight)), - _, _)) + OnEncodedImage( + AllOf(Field(&EncodedImage::_frameType, frame_type), + Field(&EncodedImage::_encodedWidth, kDefaultWidth), + Field(&EncodedImage::_encodedHeight, kDefaultHeight)), + _, _)) .Times(1) - .WillRepeatedly(Return(0)); + .WillRepeatedly(Return(EncodedImageCallback::Result( + EncodedImageCallback::Result::OK, 0))); } } @@ -388,174 +341,169 @@ class TestVp8Simulcast : public ::testing::Test { // We currently expect all active streams to generate a key frame even though // a key frame was only requested for some of them. void TestKeyFrameRequestsOnAllStreams() { - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, kNumberOfSimulcastStreams); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); frame_types[0] = kVideoFrameKey; ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); std::fill(frame_types.begin(), frame_types.end(), kVideoFrameDelta); frame_types[1] = kVideoFrameKey; ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); std::fill(frame_types.begin(), frame_types.end(), kVideoFrameDelta); frame_types[2] = kVideoFrameKey; ExpectStreams(kVideoFrameKey, kNumberOfSimulcastStreams); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); std::fill(frame_types.begin(), frame_types.end(), kVideoFrameDelta); ExpectStreams(kVideoFrameDelta, kNumberOfSimulcastStreams); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestPaddingAllStreams() { // We should always encode the base layer. - encoder_->SetRates(kMinBitrates[0] - 1, 30); + SetRates(kMinBitrates[0] - 1, 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 1); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 1); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestPaddingTwoStreams() { // We have just enough to get only the first stream and padding for two. - encoder_->SetRates(kMinBitrates[0], 30); + SetRates(kMinBitrates[0], 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 1); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 1); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestPaddingTwoStreamsOneMaxedOut() { // We are just below limit of sending second stream, so we should get // the first stream maxed out (at |maxBitrate|), and padding for two. - encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30); + SetRates(kTargetBitrates[0] + kMinBitrates[1] - 1, 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 1); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 1); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestPaddingOneStream() { // We have just enough to send two streams, so padding for one stream. - encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1], 30); + SetRates(kTargetBitrates[0] + kMinBitrates[1], 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 2); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 2); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestPaddingOneStreamTwoMaxedOut() { // We are just below limit of sending third stream, so we should get // first stream's rate maxed out at |targetBitrate|, second at |maxBitrate|. - encoder_->SetRates( - kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30); + SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 2); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 2); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestSendAllStreams() { // We have just enough to send all streams. - encoder_->SetRates( - kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30); + SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 3); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 3); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestDisablingStreams() { // We should get three media streams. - encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30); + SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); ExpectStreams(kVideoFrameKey, 3); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); ExpectStreams(kVideoFrameDelta, 3); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // We should only get two streams and padding for one. - encoder_->SetRates( - kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); + SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); ExpectStreams(kVideoFrameDelta, 2); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // We should only get the first stream and padding for two. - encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); + SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); ExpectStreams(kVideoFrameDelta, 1); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // We don't have enough bitrate for the thumbnail stream, but we should get // it anyway with current configuration. - encoder_->SetRates(kTargetBitrates[0] - 1, 30); + SetRates(kTargetBitrates[0] - 1, 30); ExpectStreams(kVideoFrameDelta, 1); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // We should only get two streams and padding for one. - encoder_->SetRates( - kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); + SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); // We get a key frame because a new stream is being enabled. ExpectStreams(kVideoFrameKey, 2); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // We should get all three streams. - encoder_->SetRates( - kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30); + SetRates(kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30); // We get a key frame because a new stream is being enabled. ExpectStreams(kVideoFrameKey, 3); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void SwitchingToOneStream(int width, int height) { // Disable all streams except the last and set the bitrate of the last to // 100 kbps. This verifies the way GTP switches to screenshare mode. - settings_.codecSpecific.VP8.numberOfTemporalLayers = 1; + settings_.VP8()->numberOfTemporalLayers = 1; settings_.maxBitrate = 100; settings_.startBitrate = 100; settings_.width = width; @@ -567,14 +515,12 @@ class TestVp8Simulcast : public ::testing::Test { } // Setting input image to new resolution. int half_width = (settings_.width + 1) / 2; - input_frame_.CreateEmptyFrame(settings_.width, settings_.height, - settings_.width, half_width, half_width); - memset(input_frame_.video_frame_buffer()->MutableDataY(), 0, - input_frame_.allocated_size(kYPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataU(), 0, - input_frame_.allocated_size(kUPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataV(), 0, - input_frame_.allocated_size(kVPlane)); + input_buffer_ = I420Buffer::Create(settings_.width, settings_.height, + settings_.width, half_width, half_width); + input_buffer_->InitializeData(); + + input_frame_.reset( + new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0)); // The for loop above did not set the bitrate of the highest layer. settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1] @@ -584,39 +530,40 @@ class TestVp8Simulcast : public ::testing::Test { settings_.width; settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].height = settings_.height; + SetUpRateAllocator(); EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); // Encode one frame and verify. - encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); + SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); std::vector frame_types(kNumberOfSimulcastStreams, kVideoFrameDelta); - EXPECT_CALL(encoder_callback_, - Encoded(AllOf(Field(&EncodedImage::_frameType, kVideoFrameKey), - Field(&EncodedImage::_encodedWidth, width), - Field(&EncodedImage::_encodedHeight, height)), - _, _)) + EXPECT_CALL( + encoder_callback_, + OnEncodedImage(AllOf(Field(&EncodedImage::_frameType, kVideoFrameKey), + Field(&EncodedImage::_encodedWidth, width), + Field(&EncodedImage::_encodedHeight, height)), + _, _)) .Times(1) - .WillRepeatedly(Return(0)); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + .WillRepeatedly(Return( + EncodedImageCallback::Result(EncodedImageCallback::Result::OK, 0))); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); // Switch back. DefaultSettings(&settings_, kDefaultTemporalLayerProfile); // Start at the lowest bitrate for enabling base stream. settings_.startBitrate = kMinBitrates[0]; + SetUpRateAllocator(); EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); - encoder_->SetRates(settings_.startBitrate, 30); + SetRates(settings_.startBitrate, 30); ExpectStreams(kVideoFrameKey, 1); // Resize |input_frame_| to the new resolution. half_width = (settings_.width + 1) / 2; - input_frame_.CreateEmptyFrame(settings_.width, settings_.height, - settings_.width, half_width, half_width); - memset(input_frame_.video_frame_buffer()->MutableDataY(), 0, - input_frame_.allocated_size(kYPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataU(), 0, - input_frame_.allocated_size(kUPlane)); - memset(input_frame_.video_frame_buffer()->MutableDataV(), 0, - input_frame_.allocated_size(kVPlane)); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); + input_buffer_ = I420Buffer::Create(settings_.width, settings_.height, + settings_.width, half_width, half_width); + input_buffer_->InitializeData(); + input_frame_.reset( + new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, &frame_types)); } void TestSwitchingToOneStream() { SwitchingToOneStream(1024, 768); } @@ -629,9 +576,9 @@ class TestVp8Simulcast : public ::testing::Test { Vp8TestEncodedImageCallback encoder_callback; encoder_->RegisterEncodeCompleteCallback(&encoder_callback); - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); int picture_id = -1; int temporal_layer = -1; bool layer_sync = false; @@ -641,22 +588,22 @@ class TestVp8Simulcast : public ::testing::Test { EXPECT_TRUE(layer_sync); int key_frame_picture_id = picture_id; - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); encoder_callback.GetLastEncodedFrameInfo(&picture_id, &temporal_layer, &layer_sync, 0); EXPECT_EQ(2, temporal_layer); EXPECT_TRUE(layer_sync); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); encoder_callback.GetLastEncodedFrameInfo(&picture_id, &temporal_layer, &layer_sync, 0); EXPECT_EQ(1, temporal_layer); EXPECT_TRUE(layer_sync); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); encoder_callback.GetLastEncodedFrameInfo(&picture_id, &temporal_layer, &layer_sync, 0); EXPECT_EQ(2, temporal_layer); @@ -669,8 +616,8 @@ class TestVp8Simulcast : public ::testing::Test { // Must match last key frame to trigger. codec_specific.codecSpecific.VP8.pictureIdRPSI = key_frame_picture_id; - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, &codec_specific, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, &codec_specific, NULL)); encoder_callback.GetLastEncodedFrameInfo(&picture_id, &temporal_layer, &layer_sync, 0); @@ -680,8 +627,8 @@ class TestVp8Simulcast : public ::testing::Test { // Must match last key frame to trigger, test bad id. codec_specific.codecSpecific.VP8.pictureIdRPSI = key_frame_picture_id + 17; - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, &codec_specific, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, &codec_specific, NULL)); encoder_callback.GetLastEncodedFrameInfo(&picture_id, &temporal_layer, &layer_sync, 0); @@ -698,16 +645,16 @@ class TestVp8Simulcast : public ::testing::Test { encoder_->RegisterEncodeCompleteCallback(&encoder_callback); decoder_->RegisterDecodeCompleteCallback(&decoder_callback); - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. // Set color. int plane_offset[kNumOfPlanes]; plane_offset[kYPlane] = kColorY; plane_offset[kUPlane] = kColorU; plane_offset[kVPlane] = kColorV; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); + CreateImage(input_buffer_, plane_offset); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); int picture_id = -1; int temporal_layer = -1; bool layer_sync = false; @@ -721,27 +668,27 @@ class TestVp8Simulcast : public ::testing::Test { plane_offset[kYPlane] += 1; plane_offset[kUPlane] += 1; plane_offset[kVPlane] += 1; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + CreateImage(input_buffer_, plane_offset); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); // Change color. plane_offset[kYPlane] += 1; plane_offset[kUPlane] += 1; plane_offset[kVPlane] += 1; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); + CreateImage(input_buffer_, plane_offset); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); // Change color. plane_offset[kYPlane] += 1; plane_offset[kUPlane] += 1; plane_offset[kVPlane] += 1; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); + CreateImage(input_buffer_, plane_offset); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); CodecSpecificInfo codec_specific; codec_specific.codecType = kVideoCodecVP8; @@ -753,10 +700,10 @@ class TestVp8Simulcast : public ::testing::Test { plane_offset[kYPlane] = kColorY; plane_offset[kUPlane] = kColorU; plane_offset[kVPlane] = kColorV; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); + CreateImage(input_buffer_, plane_offset); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, &codec_specific, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, &codec_specific, NULL)); EncodedImage encoded_frame; encoder_callback.GetLastEncodedKeyFrame(&encoded_frame); @@ -772,53 +719,53 @@ class TestVp8Simulcast : public ::testing::Test { void TestSaptioTemporalLayers333PatternEncoder() { Vp8TestEncodedImageCallback encoder_callback; encoder_->RegisterEncodeCompleteCallback(&encoder_callback); - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. int expected_temporal_idx[3] = {-1, -1, -1}; bool expected_layer_sync[3] = {false, false, false}; // First frame: #0. - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(0, 0, 0, expected_temporal_idx); SetExpectedValues3(true, true, true, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #1. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 2, 2, expected_temporal_idx); SetExpectedValues3(true, true, true, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #2. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(1, 1, 1, expected_temporal_idx); SetExpectedValues3(true, true, true, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #3. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 2, 2, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #4. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(0, 0, 0, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #5. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 2, 2, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( @@ -841,53 +788,53 @@ class TestVp8Simulcast : public ::testing::Test { SetUpCodec(temporal_layer_profile); Vp8TestEncodedImageCallback encoder_callback; encoder_->RegisterEncodeCompleteCallback(&encoder_callback); - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. int expected_temporal_idx[3] = {-1, -1, -1}; bool expected_layer_sync[3] = {false, false, false}; // First frame: #0. - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(0, 0, 255, expected_temporal_idx); SetExpectedValues3(true, true, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #1. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 1, 255, expected_temporal_idx); SetExpectedValues3(true, true, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #2. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(1, 0, 255, expected_temporal_idx); SetExpectedValues3(true, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #3. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 1, 255, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #4. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(0, 0, 255, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); // Next frame: #5. - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); SetExpectedValues3(2, 1, 255, expected_temporal_idx); SetExpectedValues3(false, false, false, expected_layer_sync); VerifyTemporalIdxAndSyncForAllSpatialLayers( @@ -900,29 +847,32 @@ class TestVp8Simulcast : public ::testing::Test { encoder_->RegisterEncodeCompleteCallback(&encoder_callback); decoder_->RegisterDecodeCompleteCallback(&decoder_callback); - encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. + SetRates(kMaxBitrates[2], 30); // To get all three streams. // Setting two (possibly) problematic use cases for stride: // 1. stride > width 2. stride_y != stride_uv/2 int stride_y = kDefaultWidth + 20; int stride_uv = ((kDefaultWidth + 1) / 2) + 5; - input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, stride_y, - stride_uv, stride_uv); + input_buffer_ = I420Buffer::Create(kDefaultWidth, kDefaultHeight, stride_y, + stride_uv, stride_uv); + input_frame_.reset( + new VideoFrame(input_buffer_, 0, 0, webrtc::kVideoRotation_0)); + // Set color. int plane_offset[kNumOfPlanes]; plane_offset[kYPlane] = kColorY; plane_offset[kUPlane] = kColorU; plane_offset[kVPlane] = kColorV; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); + CreateImage(input_buffer_, plane_offset); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); // Change color. plane_offset[kYPlane] += 1; plane_offset[kUPlane] += 1; plane_offset[kVPlane] += 1; - CreateImage(input_frame_.video_frame_buffer(), plane_offset); - input_frame_.set_timestamp(input_frame_.timestamp() + 3000); - EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); + CreateImage(input_buffer_, plane_offset); + input_frame_->set_timestamp(input_frame_->timestamp() + 3000); + EXPECT_EQ(0, encoder_->Encode(*input_frame_, NULL, NULL)); EncodedImage encoded_frame; // Only encoding one frame - so will be a key frame. @@ -933,36 +883,14 @@ class TestVp8Simulcast : public ::testing::Test { EXPECT_EQ(2, decoder_callback.DecodedFrames()); } - void TestSkipEncodingUnusedStreams() { - SkipEncodingUnusedStreamsTest test; - std::vector configured_bitrate = - test.RunTest(encoder_.get(), &settings_, - 1); // Target bit rate 1, to force all streams but the - // base one to be exceeding bandwidth constraints. - EXPECT_EQ(static_cast(kNumberOfSimulcastStreams), - configured_bitrate.size()); - - unsigned int min_bitrate = - std::max(settings_.simulcastStream[0].minBitrate, settings_.minBitrate); - int stream = 0; - for (std::vector::const_iterator it = - configured_bitrate.begin(); - it != configured_bitrate.end(); ++it) { - if (stream == 0) { - EXPECT_EQ(min_bitrate, *it); - } else { - EXPECT_EQ(0u, *it); - } - ++stream; - } - } - std::unique_ptr encoder_; MockEncodedImageCallback encoder_callback_; std::unique_ptr decoder_; MockDecodedImageCallback decoder_callback_; VideoCodec settings_; - VideoFrame input_frame_; + rtc::scoped_refptr input_buffer_; + std::unique_ptr input_frame_; + std::unique_ptr rate_allocator_; }; } // namespace testing diff --git a/include/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h b/include/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h index 0d09839..ad3a205 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/temporal_layers.h @@ -12,18 +12,21 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_ -#include "vpx/vpx_encoder.h" +#include #include "webrtc/common_video/include/video_image.h" #include "webrtc/typedefs.h" +struct vpx_codec_enc_cfg; +typedef struct vpx_codec_enc_cfg vpx_codec_enc_cfg_t; + namespace webrtc { struct CodecSpecificInfoVP8; class TemporalLayers { public: - // Factory for TemporalLayer strategy. Default behaviour is a fixed pattern + // Factory for TemporalLayer strategy. Default behavior is a fixed pattern // of temporal layers. See default_temporal_layers.cc virtual ~TemporalLayers() {} @@ -31,10 +34,15 @@ class TemporalLayers { // and/or update the reference buffers. virtual int EncodeFlags(uint32_t timestamp) = 0; - virtual bool ConfigureBitrates(int bitrate_kbit, - int max_bitrate_kbit, - int framerate, - vpx_codec_enc_cfg_t* cfg) = 0; + // Update state based on new bitrate target and incoming framerate. + // Returns the bitrate allocation for the active temporal layers. + virtual std::vector OnRatesUpdated(int bitrate_kbps, + int max_bitrate_kbps, + int framerate) = 0; + + // Update the encoder configuration with target bitrates or other parameters. + // Returns true iff the configuration was actually modified. + virtual bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) = 0; virtual void PopulateCodecSpecific(bool base_layer_sync, CodecSpecificInfoVP8* vp8_info, @@ -43,26 +51,52 @@ class TemporalLayers { virtual void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) = 0; virtual int CurrentLayerId() const = 0; - - virtual bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) = 0; }; +class TemporalLayersListener; class TemporalLayersFactory { public: + TemporalLayersFactory() : listener_(nullptr) {} virtual ~TemporalLayersFactory() {} - virtual TemporalLayers* Create(int temporal_layers, + virtual TemporalLayers* Create(int simulcast_id, + int temporal_layers, uint8_t initial_tl0_pic_idx) const; + void SetListener(TemporalLayersListener* listener); + + protected: + TemporalLayersListener* listener_; +}; + +class ScreenshareTemporalLayersFactory : public webrtc::TemporalLayersFactory { + public: + ScreenshareTemporalLayersFactory() {} + virtual ~ScreenshareTemporalLayersFactory() {} + + webrtc::TemporalLayers* Create(int simulcast_id, + int num_temporal_layers, + uint8_t initial_tl0_pic_idx) const override; }; // Factory for a temporal layers strategy that adaptively changes the number of -// layers based on input framerate so that the base layer has an acceptable -// framerate. See realtime_temporal_layers.cc +// layers based on input frame rate so that the base layer has an acceptable +// frame rate. See realtime_temporal_layers.cc class RealTimeTemporalLayersFactory : public TemporalLayersFactory { public: + RealTimeTemporalLayersFactory() {} ~RealTimeTemporalLayersFactory() override {} - TemporalLayers* Create(int num_temporal_layers, + TemporalLayers* Create(int simulcast_id, + int num_temporal_layers, uint8_t initial_tl0_pic_idx) const override; }; +class TemporalLayersListener { + public: + TemporalLayersListener() {} + virtual ~TemporalLayersListener() {} + + virtual void OnTemporalLayersCreated(int simulcast_id, + TemporalLayers* layers) = 0; +}; + } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_TEMPORAL_LAYERS_H_ diff --git a/include/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h b/include/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h index f8af642..77e1dc4 100644 --- a/include/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h +++ b/include/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h @@ -13,6 +13,7 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_VP8_IMPL_H_ #define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_VP8_IMPL_H_ +#include #include // NOTE: This include order must remain to avoid compile errors, even though @@ -22,11 +23,11 @@ #include "vpx/vp8cx.h" #include "vpx/vp8dx.h" +#include "webrtc/api/video/video_frame.h" #include "webrtc/common_video/include/i420_buffer_pool.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" #include "webrtc/modules/video_coding/codecs/vp8/reference_picture_selection.h" -#include "webrtc/modules/video_coding/utility/frame_dropper.h" #include "webrtc/modules/video_coding/utility/quality_scaler.h" #include "webrtc/video_frame.h" @@ -54,9 +55,10 @@ class VP8EncoderImpl : public VP8Encoder { int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; - int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) override; + int SetRateAllocation(const BitrateAllocation& bitrate, + uint32_t new_framerate) override; - void OnDroppedFrame() override {} + ScalingSettings GetScalingSettings() const override; const char* ImplementationName() const override; @@ -75,7 +77,7 @@ class VP8EncoderImpl : public VP8Encoder { int InitAndSetControlSettings(); // Update frame size for codec. - int UpdateCodecFrameSize(const VideoFrame& input_image); + int UpdateCodecFrameSize(int width, int height); void PopulateCodecSpecific(CodecSpecificInfo* codec_specific, const vpx_codec_cx_pkt& pkt, @@ -98,14 +100,13 @@ class VP8EncoderImpl : public VP8Encoder { bool feedback_mode_; int qp_max_; int cpu_speed_default_; + int number_of_cores_; uint32_t rc_max_intra_target_; int token_partitions_; ReferencePictureSelection rps_; std::vector temporal_layers_; bool down_scale_requested_; uint32_t down_scale_bitrate_; - FrameDropper tl0_frame_dropper_; - FrameDropper tl1_frame_dropper_; std::vector picture_id_; std::vector last_key_frame_picture_id_; std::vector key_frame_request_; @@ -116,8 +117,6 @@ class VP8EncoderImpl : public VP8Encoder { std::vector encoders_; std::vector configurations_; std::vector downsampling_factors_; - QualityScaler quality_scaler_; - bool quality_scaler_enabled_; }; // end of VP8EncoderImpl class class VP8DecoderImpl : public VP8Decoder { @@ -150,7 +149,8 @@ class VP8DecoderImpl : public VP8Decoder { int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp, - int64_t ntp_time_ms); + int64_t ntp_time_ms, + int qp); I420BufferPool buffer_pool_; DecodedImageCallback* decode_complete_callback_; @@ -158,7 +158,6 @@ class VP8DecoderImpl : public VP8Decoder { bool feedback_mode_; vpx_codec_ctx_t* decoder_; VideoCodec codec_; - EncodedImage last_keyframe_; int image_format_; vpx_ref_frame_t* ref_frame_; int propagation_cnt_; diff --git a/include/webrtc/modules/video_coding/codecs/vp9/include/vp9_globals.h b/include/webrtc/modules/video_coding/codecs/vp9/include/vp9_globals.h new file mode 100644 index 0000000..f429bda --- /dev/null +++ b/include/webrtc/modules/video_coding/codecs/vp9/include/vp9_globals.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains codec dependent definitions that are needed in +// order to compile the WebRTC codebase, even if this codec is not used. + +#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_GLOBALS_H_ +#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_GLOBALS_H_ + +#include "webrtc/modules/video_coding/codecs/interface/common_constants.h" + +namespace webrtc { + +const int16_t kMaxOneBytePictureId = 0x7F; // 7 bits +const int16_t kMaxTwoBytePictureId = 0x7FFF; // 15 bits +const uint8_t kNoSpatialIdx = 0xFF; +const uint8_t kNoGofIdx = 0xFF; +const uint8_t kNumVp9Buffers = 8; +const size_t kMaxVp9RefPics = 3; +const size_t kMaxVp9FramesInGof = 0xFF; // 8 bits +const size_t kMaxVp9NumberOfSpatialLayers = 8; + +enum TemporalStructureMode { + kTemporalStructureMode1, // 1 temporal layer structure - i.e., IPPP... + kTemporalStructureMode2, // 2 temporal layers 01... + kTemporalStructureMode3, // 3 temporal layers 0212... + kTemporalStructureMode4 // 3 temporal layers 02120212... +}; + +struct GofInfoVP9 { + void SetGofInfoVP9(TemporalStructureMode tm) { + switch (tm) { + case kTemporalStructureMode1: + num_frames_in_gof = 1; + temporal_idx[0] = 0; + temporal_up_switch[0] = false; + num_ref_pics[0] = 1; + pid_diff[0][0] = 1; + break; + case kTemporalStructureMode2: + num_frames_in_gof = 2; + temporal_idx[0] = 0; + temporal_up_switch[0] = false; + num_ref_pics[0] = 1; + pid_diff[0][0] = 2; + + temporal_idx[1] = 1; + temporal_up_switch[1] = true; + num_ref_pics[1] = 1; + pid_diff[1][0] = 1; + break; + case kTemporalStructureMode3: + num_frames_in_gof = 4; + temporal_idx[0] = 0; + temporal_up_switch[0] = false; + num_ref_pics[0] = 1; + pid_diff[0][0] = 4; + + temporal_idx[1] = 2; + temporal_up_switch[1] = true; + num_ref_pics[1] = 1; + pid_diff[1][0] = 1; + + temporal_idx[2] = 1; + temporal_up_switch[2] = true; + num_ref_pics[2] = 1; + pid_diff[2][0] = 2; + + temporal_idx[3] = 2; + temporal_up_switch[3] = false; + num_ref_pics[3] = 2; + pid_diff[3][0] = 1; + pid_diff[3][1] = 2; + break; + case kTemporalStructureMode4: + num_frames_in_gof = 8; + temporal_idx[0] = 0; + temporal_up_switch[0] = false; + num_ref_pics[0] = 1; + pid_diff[0][0] = 4; + + temporal_idx[1] = 2; + temporal_up_switch[1] = true; + num_ref_pics[1] = 1; + pid_diff[1][0] = 1; + + temporal_idx[2] = 1; + temporal_up_switch[2] = true; + num_ref_pics[2] = 1; + pid_diff[2][0] = 2; + + temporal_idx[3] = 2; + temporal_up_switch[3] = false; + num_ref_pics[3] = 2; + pid_diff[3][0] = 1; + pid_diff[3][1] = 2; + + temporal_idx[4] = 0; + temporal_up_switch[0] = false; + num_ref_pics[4] = 1; + pid_diff[4][0] = 4; + + temporal_idx[5] = 2; + temporal_up_switch[1] = false; + num_ref_pics[5] = 2; + pid_diff[5][0] = 1; + pid_diff[5][1] = 2; + + temporal_idx[6] = 1; + temporal_up_switch[2] = false; + num_ref_pics[6] = 2; + pid_diff[6][0] = 2; + pid_diff[6][1] = 4; + + temporal_idx[7] = 2; + temporal_up_switch[3] = false; + num_ref_pics[7] = 2; + pid_diff[7][0] = 1; + pid_diff[7][1] = 2; + break; + default: + assert(false); + } + } + + void CopyGofInfoVP9(const GofInfoVP9& src) { + num_frames_in_gof = src.num_frames_in_gof; + for (size_t i = 0; i < num_frames_in_gof; ++i) { + temporal_idx[i] = src.temporal_idx[i]; + temporal_up_switch[i] = src.temporal_up_switch[i]; + num_ref_pics[i] = src.num_ref_pics[i]; + for (uint8_t r = 0; r < num_ref_pics[i]; ++r) { + pid_diff[i][r] = src.pid_diff[i][r]; + } + } + } + + size_t num_frames_in_gof; + uint8_t temporal_idx[kMaxVp9FramesInGof]; + bool temporal_up_switch[kMaxVp9FramesInGof]; + uint8_t num_ref_pics[kMaxVp9FramesInGof]; + uint8_t pid_diff[kMaxVp9FramesInGof][kMaxVp9RefPics]; + uint16_t pid_start; +}; + +struct RTPVideoHeaderVP9 { + void InitRTPVideoHeaderVP9() { + inter_pic_predicted = false; + flexible_mode = false; + beginning_of_frame = false; + end_of_frame = false; + ss_data_available = false; + picture_id = kNoPictureId; + max_picture_id = kMaxTwoBytePictureId; + tl0_pic_idx = kNoTl0PicIdx; + temporal_idx = kNoTemporalIdx; + spatial_idx = kNoSpatialIdx; + temporal_up_switch = false; + inter_layer_predicted = false; + gof_idx = kNoGofIdx; + num_ref_pics = 0; + num_spatial_layers = 1; + } + + bool inter_pic_predicted; // This layer frame is dependent on previously + // coded frame(s). + bool flexible_mode; // This frame is in flexible mode. + bool beginning_of_frame; // True if this packet is the first in a VP9 layer + // frame. + bool end_of_frame; // True if this packet is the last in a VP9 layer frame. + bool ss_data_available; // True if SS data is available in this payload + // descriptor. + int16_t picture_id; // PictureID index, 15 bits; + // kNoPictureId if PictureID does not exist. + int16_t max_picture_id; // Maximum picture ID index; either 0x7F or 0x7FFF; + int16_t tl0_pic_idx; // TL0PIC_IDX, 8 bits; + // kNoTl0PicIdx means no value provided. + uint8_t temporal_idx; // Temporal layer index, or kNoTemporalIdx. + uint8_t spatial_idx; // Spatial layer index, or kNoSpatialIdx. + bool temporal_up_switch; // True if upswitch to higher frame rate is possible + // starting from this frame. + bool inter_layer_predicted; // Frame is dependent on directly lower spatial + // layer frame. + + uint8_t gof_idx; // Index to predefined temporal frame info in SS data. + + uint8_t num_ref_pics; // Number of reference pictures used by this layer + // frame. + uint8_t pid_diff[kMaxVp9RefPics]; // P_DIFF signaled to derive the PictureID + // of the reference pictures. + int16_t ref_picture_id[kMaxVp9RefPics]; // PictureID of reference pictures. + + // SS data. + size_t num_spatial_layers; // Always populated. + bool spatial_layer_resolution_present; + uint16_t width[kMaxVp9NumberOfSpatialLayers]; + uint16_t height[kMaxVp9NumberOfSpatialLayers]; + GofInfoVP9 gof; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_GLOBALS_H_ diff --git a/include/webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h b/include/webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h index 8551689..af91c8c 100644 --- a/include/webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h +++ b/include/webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h @@ -107,9 +107,16 @@ class Vp9FrameBufferPool { // All buffers, in use or ready to be recycled. std::vector> allocated_buffers_ GUARDED_BY(buffers_lock_); - // If more buffers than this are allocated we print warnings, and crash if - // in debug mode. - static const size_t max_num_buffers_ = 10; + // If more buffers than this are allocated we print warnings and crash if in + // debug mode. VP9 is defined to have 8 reference buffers, of which 3 can be + // referenced by any frame, see + // https://tools.ietf.org/html/draft-grange-vp9-bitstream-00#section-2.2.2. + // Assuming VP9 holds on to at most 8 buffers, any more buffers than that + // would have to be by application code. Decoded frames should not be + // referenced for longer than necessary. If we allow ~60 additional buffers + // then the application has ~1 second to e.g. render each frame of a 60 fps + // video. + static const size_t max_num_buffers_ = 68; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h b/include/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h index 3ff2d1f..8b92b06 100644 --- a/include/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h +++ b/include/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h @@ -18,7 +18,7 @@ #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" #include "webrtc/modules/video_coding/codecs/vp9/vp9_frame_buffer_pool.h" -#include "vpx/svc_context.h" +#include "vpx/vp8cx.h" #include "vpx/vpx_decoder.h" #include "vpx/vpx_encoder.h" @@ -46,9 +46,8 @@ class VP9EncoderImpl : public VP9Encoder { int SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; - int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) override; - - void OnDroppedFrame() override {} + int SetRateAllocation(const BitrateAllocation& bitrate_allocation, + uint32_t frame_rate) override; const char* ImplementationName() const override; @@ -114,7 +113,7 @@ class VP9EncoderImpl : public VP9Encoder { vpx_codec_ctx_t* encoder_; vpx_codec_enc_cfg_t* config_; vpx_image_t* raw_; - SvcInternal_t svc_internal_; + vpx_svc_extra_cfg_t svc_params_; const VideoFrame* input_image_; GofInfoVP9 gof_; // Contains each frame's temporal information for // non-flexible mode. @@ -153,7 +152,10 @@ class VP9DecoderImpl : public VP9Decoder { const char* ImplementationName() const override; private: - int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp); + int ReturnFrame(const vpx_image_t* img, + uint32_t timestamp, + int64_t ntp_time_ms, + int qp); // Memory pool used to share buffers between libvpx and webrtc. Vp9FrameBufferPool frame_buffer_pool_; diff --git a/include/webrtc/modules/video_coding/decoding_state.h b/include/webrtc/modules/video_coding/decoding_state.h index f4ea8ae..c734080 100644 --- a/include/webrtc/modules/video_coding/decoding_state.h +++ b/include/webrtc/modules/video_coding/decoding_state.h @@ -11,11 +11,16 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_DECODING_STATE_H_ #define WEBRTC_MODULES_VIDEO_CODING_DECODING_STATE_H_ +#include +#include +#include + #include "webrtc/typedefs.h" namespace webrtc { // Forward declarations +struct NaluInfo; class VCMFrameBuffer; class VCMPacket; @@ -61,6 +66,7 @@ class VCMDecodingState { bool UsingPictureId(const VCMFrameBuffer* frame) const; bool UsingFlexibleMode(const VCMFrameBuffer* frame) const; bool AheadOfFramesDecodedClearedTo(uint16_t index) const; + bool HaveSpsAndPps(const std::vector& nalus) const; // Keep state of last decoded frame. // TODO(mikhal/stefan): create designated classes to handle these types. @@ -75,6 +81,8 @@ class VCMDecodingState { // Used to check references in flexible mode. bool frame_decoded_[kFrameDecodedLength]; uint16_t frame_decoded_cleared_to_; + std::set received_sps_; + std::map received_pps_; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/encoded_frame.h b/include/webrtc/modules/video_coding/encoded_frame.h index 9034200..840cd20 100644 --- a/include/webrtc/modules/video_coding/encoded_frame.h +++ b/include/webrtc/modules/video_coding/encoded_frame.h @@ -75,7 +75,7 @@ class VCMEncodedFrame : protected EncodedImage { /** * Get frame rotation */ - VideoRotation rotation() const { return _rotation; } + VideoRotation rotation() const { return rotation_; } /** * True if this frame is complete, false otherwise */ @@ -96,8 +96,6 @@ class VCMEncodedFrame : protected EncodedImage { */ const CodecSpecificInfo* CodecSpecific() const { return &_codecSpecificInfo; } - const RTPFragmentationHeader* FragmentationHeader() const; - protected: /** * Verifies that current allocated buffer size is larger than or equal to the @@ -118,8 +116,6 @@ class VCMEncodedFrame : protected EncodedImage { bool _missingFrame; CodecSpecificInfo _codecSpecificInfo; webrtc::VideoCodecType _codec; - RTPFragmentationHeader _fragmentation; - VideoRotation _rotation; // Video rotation is only set along with the last packet for each frame // (same as marker bit). This |_rotation_set| is only for debugging purpose diff --git a/include/webrtc/modules/video_coding/fec_tables_xor.h b/include/webrtc/modules/video_coding/fec_rate_table.h similarity index 98% rename from include/webrtc/modules/video_coding/fec_tables_xor.h rename to include/webrtc/modules/video_coding/fec_rate_table.h index fa5bd7b..18f10e0 100644 --- a/include/webrtc/modules/video_coding/fec_tables_xor.h +++ b/include/webrtc/modules/video_coding/fec_rate_table.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_MODULES_VIDEO_CODING_FEC_TABLES_XOR_H_ -#define WEBRTC_MODULES_VIDEO_CODING_FEC_TABLES_XOR_H_ +#ifndef WEBRTC_MODULES_VIDEO_CODING_FEC_RATE_TABLE_H_ +#define WEBRTC_MODULES_VIDEO_CODING_FEC_RATE_TABLE_H_ // This is a private header for media_opt_util.cc. // It should not be included by other files. @@ -18,10 +18,12 @@ namespace webrtc { // Table for Protection factor (code rate) of delta frames, for the XOR FEC. // Input is the packet loss and an effective rate (bits/frame). -// Output is array kCodeRateXORTable[k], where k = rate_i*129 + loss_j; +// Output is array kFecRateTable[k], where k = rate_i*129 + loss_j; // loss_j = 0,1,..128, and rate_i varies over some range. -static const int kSizeCodeRateXORTable = 6450; -static const unsigned char kCodeRateXORTable[kSizeCodeRateXORTable] = { +// TODO(brandtr): Consider replacing this big static table with a closed-form +// expression instead. +static const int kFecRateTableSize = 6450; +static const unsigned char kFecRateTable[kFecRateTableSize] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, @@ -456,4 +458,4 @@ static const unsigned char kCodeRateXORTable[kSizeCodeRateXORTable] = { } // namespace webrtc -#endif // WEBRTC_MODULES_VIDEO_CODING_FEC_TABLES_XOR_H_ +#endif // WEBRTC_MODULES_VIDEO_CODING_FEC_RATE_TABLE_H_ diff --git a/include/webrtc/modules/video_coding/frame_buffer.h b/include/webrtc/modules/video_coding/frame_buffer.h index f5a707e..95c5985 100644 --- a/include/webrtc/modules/video_coding/frame_buffer.h +++ b/include/webrtc/modules/video_coding/frame_buffer.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_FRAME_BUFFER_H_ #define WEBRTC_MODULES_VIDEO_CODING_FRAME_BUFFER_H_ +#include + #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/include/video_coding.h" #include "webrtc/modules/video_coding/encoded_frame.h" @@ -61,6 +63,8 @@ class VCMFrameBuffer : public VCMEncodedFrame { int Tl0PicId() const; bool NonReference() const; + std::vector GetNaluInfos() const; + void SetGofInfo(const GofInfoVP9& gof_info, size_t idx); // Increments a counter to keep track of the number of packets of this frame diff --git a/include/webrtc/modules/video_coding/frame_buffer2.h b/include/webrtc/modules/video_coding/frame_buffer2.h index 10cae42..b554f5b 100644 --- a/include/webrtc/modules/video_coding/frame_buffer2.h +++ b/include/webrtc/modules/video_coding/frame_buffer2.h @@ -14,65 +14,154 @@ #include #include #include -#include #include #include "webrtc/base/constructormagic.h" #include "webrtc/base/criticalsection.h" #include "webrtc/base/event.h" #include "webrtc/base/thread_annotations.h" +#include "webrtc/modules/video_coding/frame_object.h" +#include "webrtc/modules/video_coding/include/video_coding_defines.h" +#include "webrtc/modules/video_coding/inter_frame_delay.h" +#include "webrtc/modules/video_coding/sequence_number_util.h" namespace webrtc { class Clock; +class VCMReceiveStatisticsCallback; class VCMJitterEstimator; class VCMTiming; namespace video_coding { -class FrameObject; - class FrameBuffer { public: + enum ReturnReason { kFrameFound, kTimeout, kStopped }; + FrameBuffer(Clock* clock, VCMJitterEstimator* jitter_estimator, - const VCMTiming* timing); + VCMTiming* timing, + VCMReceiveStatisticsCallback* stats_proxy); + + virtual ~FrameBuffer(); - // Insert a frame into the frame buffer. - void InsertFrame(std::unique_ptr frame); + // Insert a frame into the frame buffer. Returns the picture id + // of the last continuous frame or -1 if there is no continuous frame. + int InsertFrame(std::unique_ptr frame); // Get the next frame for decoding. Will return at latest after - // |max_wait_time_ms|, with either a managed FrameObject or an empty - // unique ptr if there is no available frame for decoding. - std::unique_ptr NextFrame(int64_t max_wait_time_ms); + // |max_wait_time_ms|. + // - If a frame is available within |max_wait_time_ms| it will return + // kFrameFound and set |frame_out| to the resulting frame. + // - If no frame is available after |max_wait_time_ms| it will return + // kTimeout. + // - If the FrameBuffer is stopped then it will return kStopped. + ReturnReason NextFrame(int64_t max_wait_time_ms, + std::unique_ptr* frame_out); + + // Tells the FrameBuffer which protection mode that is in use. Affects + // the frame timing. + // TODO(philipel): Remove this when new timing calculations has been + // implemented. + void SetProtectionMode(VCMVideoProtection mode); + + // Start the frame buffer, has no effect if the frame buffer is started. + // The frame buffer is started upon construction. + void Start(); + + // Stop the frame buffer, causing any sleeping thread in NextFrame to + // return immediately. + void Stop(); private: - // FrameKey is a pair of (picture id, spatial layer). - using FrameKey = std::pair; + struct FrameKey { + FrameKey() : picture_id(0), spatial_layer(0) {} + FrameKey(uint16_t picture_id, uint8_t spatial_layer) + : picture_id(picture_id), spatial_layer(spatial_layer) {} + + bool operator<(const FrameKey& rhs) const { + if (picture_id == rhs.picture_id) + return spatial_layer < rhs.spatial_layer; + return AheadOf(rhs.picture_id, picture_id); + } + + bool operator<=(const FrameKey& rhs) const { return !(rhs < *this); } + + uint16_t picture_id; + uint8_t spatial_layer; + }; + + struct FrameInfo { + // The maximum number of frames that can depend on this frame. + static constexpr size_t kMaxNumDependentFrames = 8; + + // Which other frames that have direct unfulfilled dependencies + // on this frame. + FrameKey dependent_frames[kMaxNumDependentFrames]; + size_t num_dependent_frames = 0; + + // A frame is continiuous if it has all its referenced/indirectly + // referenced frames. + // + // How many unfulfilled frames this frame have until it becomes continuous. + size_t num_missing_continuous = 0; - // Comparator used to sort frames, first on their picture id, and second - // on their spatial layer. - struct FrameComp { - bool operator()(const FrameKey& f1, const FrameKey& f2) const; + // A frame is decodable if all its referenced frames have been decoded. + // + // How many unfulfilled frames this frame have until it becomes decodable. + size_t num_missing_decodable = 0; + + // If this frame is continuous or not. + bool continuous = false; + + // The actual FrameObject. + std::unique_ptr frame; }; - // Determines whether a frame is continuous. - bool IsContinuous(const FrameObject& frame) const + using FrameMap = std::map; + + // Update all directly dependent and indirectly dependent frames and mark + // them as continuous if all their references has been fulfilled. + void PropagateContinuity(FrameMap::iterator start) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // Marks the frame as decoded and updates all directly dependent frames. + void PropagateDecodability(const FrameInfo& info) EXCLUSIVE_LOCKS_REQUIRED(crit_); - // Keep track of decoded frames. - std::set decoded_frames_ GUARDED_BY(crit_); + // Advances |last_decoded_frame_it_| to |decoded| and removes old + // frame info. + void AdvanceLastDecodedFrame(FrameMap::iterator decoded) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // Update the corresponding FrameInfo of |frame| and all FrameInfos that + // |frame| references. + // Return false if |frame| will never be decodable, true otherwise. + bool UpdateFrameInfoWithIncomingFrame(const FrameObject& frame, + FrameMap::iterator info) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + + void UpdateJitterDelay() EXCLUSIVE_LOCKS_REQUIRED(crit_); + + void ClearFramesAndHistory() EXCLUSIVE_LOCKS_REQUIRED(crit_); - // The actual buffer that holds the FrameObjects. - std::map, FrameComp> frames_ - GUARDED_BY(crit_); + FrameMap frames_ GUARDED_BY(crit_); rtc::CriticalSection crit_; Clock* const clock_; - rtc::Event frame_inserted_event_; - VCMJitterEstimator* const jitter_estimator_; - const VCMTiming* const timing_; - int newest_picture_id_ GUARDED_BY(crit_); + rtc::Event new_countinuous_frame_event_; + VCMJitterEstimator* const jitter_estimator_ GUARDED_BY(crit_); + VCMTiming* const timing_ GUARDED_BY(crit_); + VCMInterFrameDelay inter_frame_delay_ GUARDED_BY(crit_); + uint32_t last_decoded_frame_timestamp_ GUARDED_BY(crit_); + FrameMap::iterator last_decoded_frame_it_ GUARDED_BY(crit_); + FrameMap::iterator last_continuous_frame_it_ GUARDED_BY(crit_); + FrameMap::iterator next_frame_it_ GUARDED_BY(crit_); + int num_frames_history_ GUARDED_BY(crit_); + int num_frames_buffered_ GUARDED_BY(crit_); + bool stopped_ GUARDED_BY(crit_); + VCMVideoProtection protection_mode_ GUARDED_BY(crit_); + VCMReceiveStatisticsCallback* const stats_callback_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameBuffer); }; diff --git a/include/webrtc/modules/video_coding/frame_object.h b/include/webrtc/modules/video_coding/frame_object.h index e8bb481..413cc33 100644 --- a/include/webrtc/modules/video_coding/frame_object.h +++ b/include/webrtc/modules/video_coding/frame_object.h @@ -11,20 +11,38 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_FRAME_OBJECT_H_ #define WEBRTC_MODULES_VIDEO_CODING_FRAME_OBJECT_H_ +#include "webrtc/base/optional.h" #include "webrtc/common_types.h" #include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/video_coding/encoded_frame.h" namespace webrtc { namespace video_coding { -class FrameObject { +class FrameObject : public webrtc::VCMEncodedFrame { public: static const uint8_t kMaxFrameReferences = 5; FrameObject(); + virtual ~FrameObject() {} virtual bool GetBitstream(uint8_t* destination) const = 0; - virtual ~FrameObject() {} + + // The capture timestamp of this frame. + virtual uint32_t Timestamp() const = 0; + + // When this frame was received. + virtual int64_t ReceivedTime() const = 0; + + // When this frame should be rendered. + virtual int64_t RenderTime() const = 0; + + // This information is currently needed by the timing calculation class. + // TODO(philipel): Remove this function when a new timing class has + // been implemented. + virtual bool delayed_by_retransmission() const { return 0; } + + size_t size() { return _length; } // The tuple (|picture_id|, |spatial_layer|) uniquely identifies a frame // object. For codec types that don't necessarily have picture ids they @@ -44,22 +62,36 @@ class RtpFrameObject : public FrameObject { public: RtpFrameObject(PacketBuffer* packet_buffer, uint16_t first_seq_num, - uint16_t last_seq_num); + uint16_t last_seq_num, + size_t frame_size, + int times_nacked, + int64_t received_time); ~RtpFrameObject(); uint16_t first_seq_num() const; uint16_t last_seq_num() const; - FrameType frame_type() const; + int times_nacked() const; + enum FrameType frame_type() const; VideoCodecType codec_type() const; bool GetBitstream(uint8_t* destination) const override; - RTPVideoTypeHeader* GetCodecHeader() const; + uint32_t Timestamp() const override; + int64_t ReceivedTime() const override; + int64_t RenderTime() const override; + bool delayed_by_retransmission() const override; + rtc::Optional GetCodecHeader() const; private: - PacketBuffer* packet_buffer_; - FrameType frame_type_; + rtc::scoped_refptr packet_buffer_; + enum FrameType frame_type_; VideoCodecType codec_type_; uint16_t first_seq_num_; uint16_t last_seq_num_; + uint32_t timestamp_; + int64_t received_time_; + + // Equal to times nacked of the packet with the highet times nacked + // belonging to this frame. + int times_nacked_; }; } // namespace video_coding diff --git a/include/webrtc/modules/video_coding/generic_decoder.h b/include/webrtc/modules/video_coding/generic_decoder.h index 2d0007b..48e2519 100644 --- a/include/webrtc/modules/video_coding/generic_decoder.h +++ b/include/webrtc/modules/video_coding/generic_decoder.h @@ -37,11 +37,13 @@ class VCMDecodedFrameCallback : public DecodedImageCallback { void SetUserReceiveCallback(VCMReceiveCallback* receiveCallback); VCMReceiveCallback* UserReceiveCallback(); - virtual int32_t Decoded(VideoFrame& decodedImage); // NOLINT - virtual int32_t Decoded(VideoFrame& decodedImage, // NOLINT - int64_t decode_time_ms); - virtual int32_t ReceivedDecodedReferenceFrame(const uint64_t pictureId); - virtual int32_t ReceivedDecodedFrame(const uint64_t pictureId); + int32_t Decoded(VideoFrame& decodedImage) override; + int32_t Decoded(VideoFrame& decodedImage, int64_t decode_time_ms) override; + void Decoded(VideoFrame& decodedImage, + rtc::Optional decode_time_ms, + rtc::Optional qp) override; + int32_t ReceivedDecodedReferenceFrame(const uint64_t pictureId) override; + int32_t ReceivedDecodedFrame(const uint64_t pictureId) override; uint64_t LastReceivedPictureID() const; void OnDecoderImplementationName(const char* implementation_name); diff --git a/include/webrtc/modules/video_coding/generic_encoder.h b/include/webrtc/modules/video_coding/generic_encoder.h index 469f04d..4d2ea2f 100644 --- a/include/webrtc/modules/video_coding/generic_encoder.h +++ b/include/webrtc/modules/video_coding/generic_encoder.h @@ -18,6 +18,7 @@ #include "webrtc/modules/video_coding/include/video_coding_defines.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/base/race_checker.h" namespace webrtc { class CriticalSectionWrapper; @@ -27,7 +28,7 @@ class MediaOptimization; } // namespace media_optimization struct EncoderParameters { - uint32_t target_bitrate; + BitrateAllocation target_bitrate; uint8_t loss_rate; int64_t rtt; uint32_t input_frame_rate; @@ -40,9 +41,10 @@ class VCMEncodedFrameCallback : public EncodedImageCallback { virtual ~VCMEncodedFrameCallback(); // Implements EncodedImageCallback. - int32_t Encoded(const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific, - const RTPFragmentationHeader* fragmentation_header) override; + EncodedImageCallback::Result OnEncodedImage( + const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info, + const RTPFragmentationHeader* fragmentation) override; void SetInternalSource(bool internal_source) { internal_source_ = internal_source; } @@ -58,7 +60,6 @@ class VCMGenericEncoder { public: VCMGenericEncoder(VideoEncoder* encoder, - VideoEncoderRateObserver* rate_observer, VCMEncodedFrameCallback* encoded_frame_callback, bool internal_source); ~VCMGenericEncoder(); @@ -70,8 +71,6 @@ class VCMGenericEncoder { const CodecSpecificInfo* codec_specific, const std::vector& frame_types); - const char* ImplementationName() const; - void SetEncoderParameters(const EncoderParameters& params); EncoderParameters GetEncoderParameters() const; @@ -82,8 +81,9 @@ class VCMGenericEncoder { bool SupportsNativeHandle() const; private: - VideoEncoder* const encoder_; - VideoEncoderRateObserver* const rate_observer_; + rtc::RaceChecker race_checker_; + + VideoEncoder* const encoder_ GUARDED_BY(race_checker_); VCMEncodedFrameCallback* const vcm_encoded_frame_callback_; const bool internal_source_; rtc::CriticalSection params_lock_; diff --git a/include/webrtc/modules/video_coding/h264_sprop_parameter_sets.h b/include/webrtc/modules/video_coding/h264_sprop_parameter_sets.h new file mode 100644 index 0000000..97ddcc5 --- /dev/null +++ b/include/webrtc/modules/video_coding/h264_sprop_parameter_sets.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_H264_SPROP_PARAMETER_SETS_H_ +#define WEBRTC_MODULES_VIDEO_CODING_H264_SPROP_PARAMETER_SETS_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" + +namespace webrtc { + +class H264SpropParameterSets { + public: + H264SpropParameterSets() {} + bool DecodeSprop(const std::string& sprop); + const std::vector& sps_nalu() { return sps_; } + const std::vector& pps_nalu() { return pps_; } + + private: + std::vector sps_; + std::vector pps_; + RTC_DISALLOW_COPY_AND_ASSIGN(H264SpropParameterSets); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_H264_SPROP_PARAMETER_SETS_H_ diff --git a/include/webrtc/modules/video_coding/h264_sps_pps_tracker.h b/include/webrtc/modules/video_coding/h264_sps_pps_tracker.h new file mode 100644 index 0000000..e769268 --- /dev/null +++ b/include/webrtc/modules/video_coding/h264_sps_pps_tracker.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ +#define WEBRTC_MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ + +#include +#include +#include +#include + +#include "webrtc/modules/include/module_common_types.h" + +namespace webrtc { + +class VCMPacket; + +namespace video_coding { + +class H264SpsPpsTracker { + public: + enum PacketAction { kInsert, kDrop, kRequestKeyframe }; + + PacketAction CopyAndFixBitstream(VCMPacket* packet); + + void InsertSpsPpsNalus(const std::vector& sps, + const std::vector& pps); + + private: + struct PpsInfo { + int sps_id = -1; + size_t size = 0; + std::unique_ptr data; + }; + + struct SpsInfo { + size_t size = 0; + std::unique_ptr data; + }; + + std::map pps_data_; + std::map sps_data_; +}; + +} // namespace video_coding +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_H264_SPS_PPS_TRACKER_H_ diff --git a/include/webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h b/include/webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h index 0185dae..35362b9 100644 --- a/include/webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h +++ b/include/webrtc/modules/video_coding/include/mock/mock_vcm_callbacks.h @@ -11,8 +11,8 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_INCLUDE_MOCK_MOCK_VCM_CALLBACKS_H_ #define WEBRTC_MODULES_VIDEO_CODING_INCLUDE_MOCK_MOCK_VCM_CALLBACKS_H_ -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/video_coding/include/video_coding_defines.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h b/include/webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h index 382eeb3..bbf3098 100644 --- a/include/webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h +++ b/include/webrtc/modules/video_coding/include/mock/mock_video_codec_interface.h @@ -14,18 +14,18 @@ #include #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" namespace webrtc { class MockEncodedImageCallback : public EncodedImageCallback { public: - MOCK_METHOD3(Encoded, - int32_t(const EncodedImage& encodedImage, - const CodecSpecificInfo* codecSpecificInfo, - const RTPFragmentationHeader* fragmentation)); + MOCK_METHOD3(OnEncodedImage, + Result(const EncodedImage& encodedImage, + const CodecSpecificInfo* codecSpecificInfo, + const RTPFragmentationHeader* fragmentation)); }; class MockVideoEncoder : public VideoEncoder { @@ -45,6 +45,9 @@ class MockVideoEncoder : public VideoEncoder { MOCK_METHOD0(Reset, int32_t()); MOCK_METHOD2(SetChannelParameters, int32_t(uint32_t packetLoss, int64_t rtt)); MOCK_METHOD2(SetRates, int32_t(uint32_t newBitRate, uint32_t frameRate)); + MOCK_METHOD2(SetRateAllocation, + int32_t(const BitrateAllocation& newBitRate, + uint32_t frameRate)); MOCK_METHOD1(SetPeriodicKeyFrames, int32_t(bool enable)); }; @@ -54,6 +57,10 @@ class MockDecodedImageCallback : public DecodedImageCallback { MOCK_METHOD2(Decoded, int32_t(VideoFrame& decodedImage, // NOLINT int64_t decode_time_ms)); + MOCK_METHOD3(Decoded, + void(VideoFrame& decodedImage, // NOLINT + rtc::Optional decode_time_ms, + rtc::Optional qp)); MOCK_METHOD1(ReceivedDecodedReferenceFrame, int32_t(const uint64_t pictureId)); MOCK_METHOD1(ReceivedDecodedFrame, int32_t(const uint64_t pictureId)); diff --git a/include/webrtc/modules/video_coding/include/video_codec_initializer.h b/include/webrtc/modules/video_coding/include/video_codec_initializer.h new file mode 100644 index 0000000..159218d --- /dev/null +++ b/include/webrtc/modules/video_coding/include/video_codec_initializer.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_INCLUDE_VIDEO_CODEC_INITIALIZER_H_ +#define WEBRTC_MODULES_VIDEO_CODING_INCLUDE_VIDEO_CODEC_INITIALIZER_H_ + +#include +#include +#include + +#include "webrtc/video_send_stream.h" + +namespace webrtc { + +class TemporalLayersFactory; +class VideoBitrateAllocator; +class VideoCodec; +class VideoEncoderConfig; + +class VideoCodecInitializer { + public: + // Takes an EncoderSettings, a VideoEncoderConfig and the VideoStream + // configuration and translated them into the old school VideoCodec type. + // It also creates a VideoBitrateAllocator instance, suitable for the codec + // type used. For instance, VP8 will create an allocator than can handle + // simulcast and temporal layering. + // GetBitrateAllocator is called implicitly from here, no need to call again. + static bool SetupCodec( + const VideoEncoderConfig& config, + const VideoSendStream::Config::EncoderSettings settings, + const std::vector& streams, + bool nack_enabled, + VideoCodec* codec, + std::unique_ptr* bitrate_allocator); + + // Create a bitrate allocator for the specified codec. |tl_factory| is + // optional, if it is populated, ownership of that instance will be + // transferred to the VideoBitrateAllocator instance. + static std::unique_ptr CreateBitrateAllocator( + const VideoCodec& codec, + std::unique_ptr tl_factory); + + private: + static VideoCodec VideoEncoderConfigToVideoCodec( + const VideoEncoderConfig& config, + const std::vector& streams, + const std::string& payload_name, + int payload_type, + bool nack_enabled); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_INCLUDE_VIDEO_CODEC_INITIALIZER_H_ diff --git a/include/webrtc/modules/video_coding/include/video_codec_interface.h b/include/webrtc/modules/video_coding/include/video_codec_interface.h index 19303c0..306fbef 100644 --- a/include/webrtc/modules/video_coding/include/video_codec_interface.h +++ b/include/webrtc/modules/video_coding/include/video_codec_interface.h @@ -13,13 +13,13 @@ #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/common_types.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/include/video_error_codes.h" #include "webrtc/typedefs.h" #include "webrtc/video_decoder.h" #include "webrtc/video_encoder.h" -#include "webrtc/video_frame.h" namespace webrtc { @@ -77,7 +77,9 @@ struct CodecSpecificInfoGeneric { uint8_t simulcast_idx; }; -struct CodecSpecificInfoH264 {}; +struct CodecSpecificInfoH264 { + H264PacketizationMode packetization_mode; +}; union CodecSpecificInfoUnion { CodecSpecificInfoGeneric generic; @@ -90,7 +92,9 @@ union CodecSpecificInfoUnion { // must be fitted with a copy-constructor. This is because it is copied // in the copy-constructor of VCMEncodedFrame. struct CodecSpecificInfo { + CodecSpecificInfo() : codecType(kVideoCodecUnknown), codec_name(nullptr) {} VideoCodecType codecType; + const char* codec_name; CodecSpecificInfoUnion codecSpecific; }; diff --git a/include/webrtc/modules/video_coding/include/video_coding.h b/include/webrtc/modules/video_coding/include/video_coding.h index 0f85679..f7f66a7 100644 --- a/include/webrtc/modules/video_coding/include/video_coding.h +++ b/include/webrtc/modules/video_coding/include/video_coding.h @@ -21,11 +21,11 @@ #include #endif +#include "webrtc/api/video/video_frame.h" #include "webrtc/modules/include/module.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/include/video_coding_defines.h" #include "webrtc/system_wrappers/include/event_wrapper.h" -#include "webrtc/video_frame.h" namespace webrtc { @@ -35,6 +35,7 @@ class EncodedImageCallback; // removing the VCM and use VideoSender/VideoReceiver as a public interface // directly. class VCMQMSettingsCallback; +class VideoBitrateAllocator; class VideoEncoder; class VideoDecoder; struct CodecSpecificInfo; @@ -72,21 +73,15 @@ class VideoCodingModule : public Module { enum ReceiverRobustness { kNone, kHardNack, kSoftNack, kReferenceSelection }; - static VideoCodingModule* Create( - Clock* clock, - VideoEncoderRateObserver* encoder_rate_observer, - VCMQMSettingsCallback* qm_settings_callback); + static VideoCodingModule* Create(Clock* clock, EventFactory* event_factory); static VideoCodingModule* Create( Clock* clock, - VideoEncoderRateObserver* encoder_rate_observer, VCMQMSettingsCallback* qm_settings_callback, NackSender* nack_sender, KeyFrameRequestSender* keyframe_request_sender, EncodedImageCallback* pre_decode_image_callback); - static VideoCodingModule* Create(Clock* clock, EventFactory* event_factory); - static VideoCodingModule* Create( Clock* clock, EventFactory* event_factory, @@ -188,14 +183,10 @@ class VideoCodingModule : public Module { // < 0, on error. virtual int32_t SetReceiveChannelParameters(int64_t rtt) = 0; + // Deprecated: This method currently does not have any effect. // Register a video protection callback which will be called to deliver // the requested FEC rate and NACK status (on/off). - // - // Input: - // - protection : The callback object to register. - // - // Return value : VCM_OK, on success. - // < 0, on error. + // TODO(perkj): Remove once no projects use it. virtual int32_t RegisterProtectionCallback( VCMProtectionCallback* protection) = 0; @@ -476,15 +467,6 @@ class VideoCodingModule : public Module { // delayed by at least desired_delay_ms. virtual int SetMinReceiverDelay(int desired_delay_ms) = 0; - // Lets the sender suspend video when the rate drops below - // |threshold_bps|, and turns back on when the rate goes back up above - // |threshold_bps| + |window_bps|. - virtual void SuspendBelowMinBitrate() = 0; - - // Returns true if SuspendBelowMinBitrate is engaged and the video has been - // suspended due to bandwidth limitations; otherwise false. - virtual bool VideoSuspended() const = 0; - virtual void RegisterPostEncodeImageCallback( EncodedImageCallback* post_encode_callback) = 0; // Releases pending decode calls, permitting faster thread shutdown. diff --git a/include/webrtc/modules/video_coding/include/video_coding_defines.h b/include/webrtc/modules/video_coding/include/video_coding_defines.h index ba71803..00ad5b6 100644 --- a/include/webrtc/modules/video_coding/include/video_coding_defines.h +++ b/include/webrtc/modules/video_coding/include/video_coding_defines.h @@ -14,8 +14,10 @@ #include #include +#include "webrtc/api/video/video_frame.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" +// For EncodedImage #include "webrtc/video_frame.h" namespace webrtc { @@ -61,7 +63,8 @@ struct VCMFrameCount { // rendered. class VCMReceiveCallback { public: - virtual int32_t FrameToRender(VideoFrame& videoFrame) = 0; // NOLINT + virtual int32_t FrameToRender(VideoFrame& videoFrame, // NOLINT + rtc::Optional qp) = 0; virtual int32_t ReceivedDecodedReferenceFrame(const uint64_t pictureId) { return -1; } @@ -77,9 +80,7 @@ class VCMReceiveCallback { // and the name of the encoder. class VCMSendStatisticsCallback { public: - virtual void SendStatistics(uint32_t bitRate, - uint32_t frameRate, - const std::string& encoder_name) = 0; + virtual void SendStatistics(uint32_t bitRate, uint32_t frameRate) = 0; protected: virtual ~VCMSendStatisticsCallback() {} @@ -90,8 +91,16 @@ class VCMSendStatisticsCallback { class VCMReceiveStatisticsCallback { public: virtual void OnReceiveRatesUpdated(uint32_t bitRate, uint32_t frameRate) = 0; + virtual void OnCompleteFrame(bool is_keyframe, size_t size_bytes) = 0; virtual void OnDiscardedPacketsUpdated(int discarded_packets) = 0; virtual void OnFrameCountsUpdated(const FrameCounts& frame_counts) = 0; + virtual void OnFrameBufferTimingsUpdated(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) = 0; protected: virtual ~VCMReceiveStatisticsCallback() {} @@ -126,12 +135,6 @@ class VCMProtectionCallback { virtual ~VCMProtectionCallback() {} }; -class VideoEncoderRateObserver { - public: - virtual ~VideoEncoderRateObserver() {} - virtual void OnSetRates(uint32_t bitrate_bps, int framerate) = 0; -}; - // Callback class used for telling the user about what frame type needed to // continue decoding. // Typically a key frame when the stream has been corrupted in some way. diff --git a/include/webrtc/modules/video_coding/jitter_buffer.h b/include/webrtc/modules/video_coding/jitter_buffer.h index e36f2cd..62017da 100644 --- a/include/webrtc/modules/video_coding/jitter_buffer.h +++ b/include/webrtc/modules/video_coding/jitter_buffer.h @@ -129,10 +129,6 @@ class VCMJitterBuffer { // was started. FrameCounts FrameStatistics() const; - // The number of packets discarded by the jitter buffer because the decoder - // won't be able to decode them. - int num_not_decodable_packets() const; - // Gets number of packets received. int num_packets() const; @@ -145,16 +141,9 @@ class VCMJitterBuffer { // Statistics, Calculate frame and bit rates. void IncomingRateStatistics(unsigned int* framerate, unsigned int* bitrate); - // Checks if the packet sequence will be complete if the next frame would be - // grabbed for decoding. That is, if a frame has been lost between the - // last decoded frame and the next, or if the next frame is missing one - // or more packets. - bool CompleteSequenceWithNextFrame(); - // Wait |max_wait_time_ms| for a complete frame to arrive. - // The function returns true once such a frame is found, its corresponding - // timestamp is returned. Otherwise, returns false. - bool NextCompleteTimestamp(uint32_t max_wait_time_ms, uint32_t* timestamp); + // If found, a pointer to the frame is returned. Returns nullptr otherwise. + VCMEncodedFrame* NextCompleteFrame(uint32_t max_wait_time_ms); // Locates a frame for decoding (even an incomplete) without delay. // The function returns true once such a frame is found, its corresponding @@ -209,14 +198,10 @@ class VCMJitterBuffer { // Set decode error mode - Should not be changed in the middle of the // session. Changes will not influence frames already in the buffer. void SetDecodeErrorMode(VCMDecodeErrorMode error_mode); - int64_t LastDecodedTimestamp() const; VCMDecodeErrorMode decode_error_mode() const { return decode_error_mode_; } void RegisterStatsCallback(VCMReceiveStatisticsCallback* callback); - int64_t TimeUntilNextProcess(); - void Process(); - private: class SequenceNumberLessThan { public: @@ -276,8 +261,6 @@ class VCMJitterBuffer { // Drops all packets in the NACK list up until |last_decoded_sequence_number|. void DropPacketsFromNackList(uint16_t last_decoded_sequence_number); - void ReleaseFrameIfNotDecoding(VCMFrameBuffer* frame); - // Gets an empty frame, creating a new frame if necessary (i.e. increases // jitter buffer size). VCMFrameBuffer* GetEmptyFrame() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); @@ -325,6 +308,10 @@ class VCMJitterBuffer { void UpdateHistograms() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + // Reset frame buffer and return it to free_frames_. + void RecycleFrameBuffer(VCMFrameBuffer* frame) + EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + Clock* clock_; // If we are running (have started) or not. bool running_; @@ -349,8 +336,6 @@ class VCMJitterBuffer { int64_t time_last_incoming_frame_count_; unsigned int incoming_bit_count_; unsigned int incoming_bit_rate_; - // Number of frames in a row that have been too old. - int num_consecutive_old_frames_; // Number of packets in a row that have been too old. int num_consecutive_old_packets_; // Number of packets received. @@ -388,8 +373,6 @@ class VCMJitterBuffer { // frames. int frame_counter_; - std::unique_ptr nack_module_; - RTC_DISALLOW_COPY_AND_ASSIGN(VCMJitterBuffer); }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/jitter_estimator.h b/include/webrtc/modules/video_coding/jitter_estimator.h index a7b4b3e..7ef050f 100644 --- a/include/webrtc/modules/video_coding/jitter_estimator.h +++ b/include/webrtc/modules/video_coding/jitter_estimator.h @@ -50,7 +50,7 @@ class VCMJitterEstimator { // - rttMultiplier : RTT param multiplier (when applicable). // // Return value : Jitter estimate in milliseconds - int GetJitterEstimate(double rttMultiplier); + virtual int GetJitterEstimate(double rttMultiplier); // Updates the nack counter. void FrameNacked(); diff --git a/include/webrtc/modules/video_coding/media_opt_util.h b/include/webrtc/modules/video_coding/media_opt_util.h index ad314ac..7cb8ed2 100644 --- a/include/webrtc/modules/video_coding/media_opt_util.h +++ b/include/webrtc/modules/video_coding/media_opt_util.h @@ -16,7 +16,7 @@ #include -#include "webrtc/base/exp_filter.h" +#include "webrtc/base/numerics/exp_filter.h" #include "webrtc/modules/video_coding/internal_defines.h" #include "webrtc/system_wrappers/include/trace.h" #include "webrtc/typedefs.h" @@ -282,7 +282,7 @@ class VCMLossProtectionLogic { // Input: // - width : The codec frame width. // - height : The codec frame height. - void UpdateFrameSize(uint16_t width, uint16_t height); + void UpdateFrameSize(size_t width, size_t height); // Update the number of active layers // @@ -350,8 +350,8 @@ class VCMLossProtectionLogic { uint8_t _shortMaxLossPr255; rtc::ExpFilter _packetsPerFrame; rtc::ExpFilter _packetsPerFrameKey; - uint16_t _codecWidth; - uint16_t _codecHeight; + size_t _codecWidth; + size_t _codecHeight; int _numLayers; }; diff --git a/include/webrtc/modules/video_coding/media_optimization.h b/include/webrtc/modules/video_coding/media_optimization.h index 081b2a9..290636f 100644 --- a/include/webrtc/modules/video_coding/media_optimization.h +++ b/include/webrtc/modules/video_coding/media_optimization.h @@ -38,8 +38,9 @@ class MediaOptimization { void Reset(); // Informs media optimization of initial encoding state. - void SetEncodingData(VideoCodecType send_codec_type, - int32_t max_bit_rate, + // TODO(perkj): Deprecate SetEncodingData once its not used for stats in + // VieEncoder. + void SetEncodingData(int32_t max_bit_rate, uint32_t bit_rate, uint16_t width, uint16_t height, @@ -48,30 +49,15 @@ class MediaOptimization { int32_t mtu); // Sets target rates for the encoder given the channel parameters. - // Inputs: target bitrate - the encoder target bitrate in bits/s. - // fraction_lost - packet loss rate in % in the network. - // round_trip_time_ms - round trip time in milliseconds. - // min_bit_rate - the bit rate of the end-point with lowest rate. - // max_bit_rate - the bit rate of the end-point with highest rate. - // TODO(andresp): Find if the callbacks can be triggered only after releasing - // an internal critical section. - uint32_t SetTargetRates(uint32_t target_bitrate, - uint8_t fraction_lost, - int64_t round_trip_time_ms, - VCMProtectionCallback* protection_callback); - - void SetProtectionMethod(VCMProtectionMethodEnum method); - void EnableFrameDropper(bool enable); - - // Lets the sender suspend video when the rate drops below - // |threshold_bps|, and turns back on when the rate goes back up above - // |threshold_bps| + |window_bps|. - void SuspendBelowMinBitrate(int threshold_bps, int window_bps); - bool IsVideoSuspended() const; + // Input: target bitrate - the encoder target bitrate in bits/s. + uint32_t SetTargetRates(uint32_t target_bitrate); + void EnableFrameDropper(bool enable); bool DropFrame(); // Informs Media Optimization of encoded output. + // TODO(perkj): Deprecate SetEncodingData once its not used for stats in + // VieEncoder. int32_t UpdateWithEncodedData(const EncodedImage& encoded_image); // InputFrameRate 0 = no frame rate estimate available. @@ -101,8 +87,7 @@ class MediaOptimization { // changes the state of |video_suspended_| accordingly. void CheckSuspendConditions() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); - void SetEncodingDataInternal(VideoCodecType send_codec_type, - int32_t max_bit_rate, + void SetEncodingDataInternal(int32_t max_bit_rate, uint32_t frame_rate, uint32_t bit_rate, uint16_t width, @@ -120,14 +105,10 @@ class MediaOptimization { Clock* clock_ GUARDED_BY(crit_sect_); int32_t max_bit_rate_ GUARDED_BY(crit_sect_); - VideoCodecType send_codec_type_ GUARDED_BY(crit_sect_); uint16_t codec_width_ GUARDED_BY(crit_sect_); uint16_t codec_height_ GUARDED_BY(crit_sect_); float user_frame_rate_ GUARDED_BY(crit_sect_); std::unique_ptr frame_dropper_ GUARDED_BY(crit_sect_); - std::unique_ptr loss_prot_logic_ - GUARDED_BY(crit_sect_); - uint8_t fraction_lost_ GUARDED_BY(crit_sect_); uint32_t send_statistics_[4] GUARDED_BY(crit_sect_); uint32_t send_statistics_zero_encode_ GUARDED_BY(crit_sect_); int32_t max_payload_size_ GUARDED_BY(crit_sect_); @@ -137,13 +118,7 @@ class MediaOptimization { std::list encoded_frame_samples_ GUARDED_BY(crit_sect_); uint32_t avg_sent_bit_rate_bps_ GUARDED_BY(crit_sect_); uint32_t avg_sent_framerate_ GUARDED_BY(crit_sect_); - uint32_t key_frame_cnt_ GUARDED_BY(crit_sect_); - uint32_t delta_frame_cnt_ GUARDED_BY(crit_sect_); int num_layers_ GUARDED_BY(crit_sect_); - bool suspension_enabled_ GUARDED_BY(crit_sect_); - bool video_suspended_ GUARDED_BY(crit_sect_); - int suspension_threshold_bps_ GUARDED_BY(crit_sect_); - int suspension_window_bps_ GUARDED_BY(crit_sect_); }; } // namespace media_optimization } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/nack_module.h b/include/webrtc/modules/video_coding/nack_module.h index 58d6cfa..6cdd047 100644 --- a/include/webrtc/modules/video_coding/nack_module.h +++ b/include/webrtc/modules/video_coding/nack_module.h @@ -36,7 +36,6 @@ class NackModule : public Module { void ClearUpTo(uint16_t seq_num); void UpdateRtt(int64_t rtt_ms); void Clear(); - void Stop(); // Module implementation int64_t TimeUntilNextProcess() override; @@ -82,16 +81,20 @@ class NackModule : public Module { NackSender* const nack_sender_; KeyFrameRequestSender* const keyframe_request_sender_; + // TODO(philipel): Some of the variables below are consistently used on a + // known thread (e.g. see |initialized_|). Those probably do not need + // synchronized access. std::map> nack_list_ GUARDED_BY(crit_); std::set> keyframe_list_ GUARDED_BY(crit_); video_coding::Histogram reordering_histogram_ GUARDED_BY(crit_); - bool running_ GUARDED_BY(crit_); bool initialized_ GUARDED_BY(crit_); int64_t rtt_ms_ GUARDED_BY(crit_); uint16_t newest_seq_num_ GUARDED_BY(crit_); - int64_t next_process_time_ms_ GUARDED_BY(crit_); + + // Only touched on the process thread. + int64_t next_process_time_ms_; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_coding/packet.h b/include/webrtc/modules/video_coding/packet.h index b77c1df..488c058 100644 --- a/include/webrtc/modules/video_coding/packet.h +++ b/include/webrtc/modules/video_coding/packet.h @@ -11,6 +11,7 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_PACKET_H_ #define WEBRTC_MODULES_VIDEO_CODING_PACKET_H_ +#include "webrtc/base/deprecation.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/jitter_buffer_common.h" #include "webrtc/typedefs.h" @@ -23,11 +24,6 @@ class VCMPacket { VCMPacket(const uint8_t* ptr, const size_t size, const WebRtcRTPHeader& rtpHeader); - VCMPacket(const uint8_t* ptr, - size_t size, - uint16_t seqNum, - uint32_t timestamp, - bool markerBit); void Reset(); @@ -39,17 +35,21 @@ class VCMPacket { const uint8_t* dataPtr; size_t sizeBytes; bool markerBit; + int timesNacked; FrameType frameType; VideoCodecType codec; - bool isFirstPacket; // Is this first packet in a frame. + union { + RTC_DEPRECATED bool isFirstPacket; // Is this first packet in a frame. + bool is_first_packet_in_frame; + }; VCMNaluCompleteness completeNALU; // Default is kNaluIncomplete. bool insertStartCode; // True if a start code should be inserted before this // packet. int width; int height; - RTPVideoHeader codecSpecificHeader; + RTPVideoHeader video_header; protected: void CopyCodecSpecifics(const RTPVideoHeader& videoHeader); diff --git a/include/webrtc/modules/video_coding/packet_buffer.h b/include/webrtc/modules/video_coding/packet_buffer.h index ae0916a..001f8bd 100644 --- a/include/webrtc/modules/video_coding/packet_buffer.h +++ b/include/webrtc/modules/video_coding/packet_buffer.h @@ -12,8 +12,10 @@ #define WEBRTC_MODULES_VIDEO_CODING_PACKET_BUFFER_H_ #include +#include #include "webrtc/base/criticalsection.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/packet.h" @@ -21,28 +23,48 @@ #include "webrtc/modules/video_coding/sequence_number_util.h" namespace webrtc { + +class Clock; + namespace video_coding { class FrameObject; class RtpFrameObject; -class OnCompleteFrameCallback { +// A received frame is a frame which has received all its packets. +class OnReceivedFrameCallback { public: - virtual ~OnCompleteFrameCallback() {} - virtual void OnCompleteFrame(std::unique_ptr frame) = 0; + virtual ~OnReceivedFrameCallback() {} + virtual void OnReceivedFrame(std::unique_ptr frame) = 0; }; class PacketBuffer { public: - // Both |start_buffer_size| and |max_buffer_size| must be a power of 2. - PacketBuffer(size_t start_buffer_size, - size_t max_buffer_size, - OnCompleteFrameCallback* frame_callback); - - bool InsertPacket(const VCMPacket& packet); + static rtc::scoped_refptr Create( + Clock* clock, + size_t start_buffer_size, + size_t max_buffer_size, + OnReceivedFrameCallback* frame_callback); + + virtual ~PacketBuffer(); + + // Returns true if |packet| is inserted into the packet buffer, false + // otherwise. The PacketBuffer will always take ownership of the + // |packet.dataPtr| when this function is called. Made virtual for testing. + virtual bool InsertPacket(VCMPacket* packet); void ClearTo(uint16_t seq_num); void Clear(); + int AddRef() const; + int Release() const; + + protected: + // Both |start_buffer_size| and |max_buffer_size| must be a power of 2. + PacketBuffer(Clock* clock, + size_t start_buffer_size, + size_t max_buffer_size, + OnReceivedFrameCallback* frame_callback); + private: friend RtpFrameObject; // Since we want the packet buffer to be as packet type agnostic @@ -68,24 +90,32 @@ class PacketBuffer { bool frame_created = false; }; + Clock* const clock_; + // Tries to expand the buffer. bool ExpandBufferSize() EXCLUSIVE_LOCKS_REQUIRED(crit_); // Test if all previous packets has arrived for the given sequence number. - bool IsContinuous(uint16_t seq_num) const EXCLUSIVE_LOCKS_REQUIRED(crit_); + bool PotentialNewFrame(uint16_t seq_num) const + EXCLUSIVE_LOCKS_REQUIRED(crit_); // Test if all packets of a frame has arrived, and if so, creates a frame. - // May create multiple frames per invocation. - void FindFrames(uint16_t seq_num) EXCLUSIVE_LOCKS_REQUIRED(crit_); + // Returns a vector of received frames. + std::vector> FindFrames(uint16_t seq_num) + EXCLUSIVE_LOCKS_REQUIRED(crit_); // Copy the bitstream for |frame| to |destination|. - bool GetBitstream(const RtpFrameObject& frame, uint8_t* destination); + // Virtual for testing. + virtual bool GetBitstream(const RtpFrameObject& frame, uint8_t* destination); // Get the packet with sequence number |seq_num|. - VCMPacket* GetPacket(uint16_t seq_num); + // Virtual for testing. + virtual VCMPacket* GetPacket(uint16_t seq_num) + EXCLUSIVE_LOCKS_REQUIRED(crit_); // Mark all slots used by |frame| as not used. - void ReturnFrame(RtpFrameObject* frame); + // Virtual for testing. + virtual void ReturnFrame(RtpFrameObject* frame); rtc::CriticalSection crit_; @@ -96,12 +126,12 @@ class PacketBuffer { // The fist sequence number currently in the buffer. uint16_t first_seq_num_ GUARDED_BY(crit_); - // The last sequence number currently in the buffer. - uint16_t last_seq_num_ GUARDED_BY(crit_); - // If the packet buffer has received its first packet. bool first_packet_received_ GUARDED_BY(crit_); + // If the buffer is cleared to |first_seq_num_|. + bool is_cleared_to_first_seq_num_ GUARDED_BY(crit_); + // Buffer that holds the inserted packets. std::vector data_buffer_ GUARDED_BY(crit_); @@ -109,9 +139,10 @@ class PacketBuffer { // and information needed to determine the continuity between packets. std::vector sequence_buffer_ GUARDED_BY(crit_); - // Frames that have received all their packets are handed off to the - // |reference_finder_| which finds the dependencies between the frames. - RtpFrameReferenceFinder reference_finder_; + // Called when a received frame is found. + OnReceivedFrameCallback* const received_frame_callback_; + + mutable volatile int ref_count_ = 0; }; } // namespace video_coding diff --git a/include/webrtc/modules/video_coding/percentile_filter.h b/include/webrtc/modules/video_coding/percentile_filter.h deleted file mode 100644 index 125a244..0000000 --- a/include/webrtc/modules/video_coding/percentile_filter.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_PERCENTILE_FILTER_H_ -#define WEBRTC_MODULES_VIDEO_CODING_PERCENTILE_FILTER_H_ - -#include - -#include - -namespace webrtc { - -// Class to efficiently get the percentile value from a group of observations. -// The percentile is the value below which a given percentage of the -// observations fall. -class PercentileFilter { - public: - // Construct filter. |percentile| should be between 0 and 1. - explicit PercentileFilter(float percentile); - - // Insert one observation. The complexity of this operation is logarithmic in - // the size of the container. - void Insert(const int64_t& value); - // Remove one observation. The complexity of this operation is logarithmic in - // the size of the container. - void Erase(const int64_t& value); - // Get the percentile value. The complexity of this operation is constant. - int64_t GetPercentileValue() const; - - private: - // Update iterator and index to point at target percentile value. - void UpdatePercentileIterator(); - - const float percentile_; - std::multiset set_; - // Maintain iterator and index of current target percentile value. - std::multiset::iterator percentile_it_; - int64_t percentile_index_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_CODING_PERCENTILE_FILTER_H_ diff --git a/include/webrtc/modules/video_coding/protection_bitrate_calculator.h b/include/webrtc/modules/video_coding/protection_bitrate_calculator.h new file mode 100644 index 0000000..a12dcfc --- /dev/null +++ b/include/webrtc/modules/video_coding/protection_bitrate_calculator.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_PROTECTION_BITRATE_CALCULATOR_H_ +#define WEBRTC_MODULES_VIDEO_CODING_PROTECTION_BITRATE_CALCULATOR_H_ + +#include +#include + +#include "webrtc/base/criticalsection.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/video_coding/include/video_coding.h" +#include "webrtc/modules/video_coding/media_opt_util.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { + +// ProtectionBitrateCalculator calculates how much of the allocated network +// capacity that can be used by an encoder and how much that +// is needed for redundant packets such as FEC and NACK. It uses an +// implementation of |VCMProtectionCallback| to set new FEC parameters and get +// the bitrate currently used for FEC and NACK. +// Usage: +// Setup by calling SetProtectionMethod and SetEncodingData. +// For each encoded image, call UpdateWithEncodedData. +// Each time the bandwidth estimate change, call SetTargetRates. SetTargetRates +// will return the bitrate that can be used by an encoder. +// A lock is used to protect internal states, so methods can be called on an +// arbitrary thread. +class ProtectionBitrateCalculator { + public: + ProtectionBitrateCalculator(Clock* clock, + VCMProtectionCallback* protection_callback); + ~ProtectionBitrateCalculator(); + + void SetProtectionMethod(bool enable_fec, bool enable_nack); + + // Informs media optimization of initial encoding state. + void SetEncodingData(size_t width, + size_t height, + size_t num_temporal_layers, + size_t max_payload_size); + + // Returns target rate for the encoder given the channel parameters. + // Inputs: estimated_bitrate_bps - the estimated network bitrate in bits/s. + // actual_framerate - encoder frame rate. + // fraction_lost - packet loss rate in % in the network. + // round_trip_time_ms - round trip time in milliseconds. + uint32_t SetTargetRates(uint32_t estimated_bitrate_bps, + int actual_framerate, + uint8_t fraction_lost, + int64_t round_trip_time_ms); + // Informs of encoded output. + void UpdateWithEncodedData(const EncodedImage& encoded_image); + + private: + struct EncodedFrameSample; + enum { kBitrateAverageWinMs = 1000 }; + + Clock* const clock_; + VCMProtectionCallback* const protection_callback_; + + rtc::CriticalSection crit_sect_; + std::unique_ptr loss_prot_logic_ + GUARDED_BY(crit_sect_); + size_t max_payload_size_ GUARDED_BY(crit_sect_); + + RTC_DISALLOW_COPY_AND_ASSIGN(ProtectionBitrateCalculator); +}; + +} // namespace webrtc +#endif // WEBRTC_MODULES_VIDEO_CODING_PROTECTION_BITRATE_CALCULATOR_H_ diff --git a/include/webrtc/modules/video_coding/receiver.h b/include/webrtc/modules/video_coding/receiver.h index dbef62a..3d9e445 100644 --- a/include/webrtc/modules/video_coding/receiver.h +++ b/include/webrtc/modules/video_coding/receiver.h @@ -63,11 +63,8 @@ class VCMReceiver { void Reset(); void UpdateRtt(int64_t rtt); - int32_t InsertPacket(const VCMPacket& packet, - uint16_t frame_width, - uint16_t frame_height); + int32_t InsertPacket(const VCMPacket& packet); VCMEncodedFrame* FrameForDecoding(uint16_t max_wait_time_ms, - int64_t* next_render_time_ms, bool prefer_late_decoding); void ReleaseFrame(VCMEncodedFrame* frame); void ReceiveStatistics(uint32_t* bitrate, uint32_t* framerate); @@ -94,9 +91,6 @@ class VCMReceiver { void TriggerDecoderShutdown(); - int64_t TimeUntilNextProcess(); - void Process(); - private: CriticalSectionWrapper* crit_sect_; Clock* const clock_; diff --git a/include/webrtc/modules/video_coding/rtp_frame_reference_finder.h b/include/webrtc/modules/video_coding/rtp_frame_reference_finder.h index 7289b80..db1ddf8 100644 --- a/include/webrtc/modules/video_coding/rtp_frame_reference_finder.h +++ b/include/webrtc/modules/video_coding/rtp_frame_reference_finder.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -26,31 +26,69 @@ namespace webrtc { namespace video_coding { +class FrameObject; class RtpFrameObject; -class OnCompleteFrameCallback; + +// A complete frame is a frame which has received all its packets and all its +// references are known. +class OnCompleteFrameCallback { + public: + virtual ~OnCompleteFrameCallback() {} + virtual void OnCompleteFrame(std::unique_ptr frame) = 0; +}; class RtpFrameReferenceFinder { public: explicit RtpFrameReferenceFinder(OnCompleteFrameCallback* frame_callback); + + // Manage this frame until: + // - We have all information needed to determine its references, after + // which |frame_callback_| is called with the completed frame, or + // - We have too many stashed frames (determined by |kMaxStashedFrames) + // so we drop this frame, or + // - It gets cleared by ClearTo, which also means we drop it. void ManageFrame(std::unique_ptr frame); + // Notifies that padding has been received, which the reference finder + // might need to calculate the references of a frame. + void PaddingReceived(uint16_t seq_num); + + // Clear all stashed frames that include packets older than |seq_num|. + void ClearTo(uint16_t seq_num); + private: - static const uint16_t kPicIdLength = 1 << 7; + static const uint16_t kPicIdLength = 1 << 15; static const uint8_t kMaxTemporalLayers = 5; - static const int kMaxLayerInfo = 10; - static const int kMaxStashedFrames = 10; - static const int kMaxNotYetReceivedFrames = 20; - static const int kMaxGofSaved = 15; + static const int kMaxLayerInfo = 50; + static const int kMaxStashedFrames = 50; + static const int kMaxNotYetReceivedFrames = 100; + static const int kMaxGofSaved = 50; + static const int kMaxPaddingAge = 100; + + + struct GofInfo { + GofInfo(GofInfoVP9* gof, uint16_t last_picture_id) + : gof(gof), last_picture_id(last_picture_id) {} + GofInfoVP9* gof; + uint16_t last_picture_id; + }; rtc::CriticalSection crit_; + // Find the relevant group of pictures and update its "last-picture-id-with + // padding" sequence number. + void UpdateLastPictureIdWithPadding(uint16_t seq_num) + EXCLUSIVE_LOCKS_REQUIRED(crit_); + // Retry finding references for all frames that previously didn't have // all information needed. void RetryStashedFrames() EXCLUSIVE_LOCKS_REQUIRED(crit_); - // Find references for generic frames. - void ManageFrameGeneric(std::unique_ptr frame) - EXCLUSIVE_LOCKS_REQUIRED(crit_); + // Find references for generic frames. If |picture_id| is unspecified + // then packet sequence numbers will be used to determine the references + // of the frames. + void ManageFrameGeneric(std::unique_ptr frame, + int picture_id) EXCLUSIVE_LOCKS_REQUIRED(crit_); // Find references for Vp8 frames void ManageFrameVp8(std::unique_ptr frame) @@ -73,13 +111,13 @@ class RtpFrameReferenceFinder { // Check if we are missing a frame necessary to determine the references // for this frame. - bool MissingRequiredFrameVp9(uint16_t picture_id, const GofInfoVP9& gof) + bool MissingRequiredFrameVp9(uint16_t picture_id, const GofInfo& info) EXCLUSIVE_LOCKS_REQUIRED(crit_); // Updates which frames that have been received. If there is a gap, // missing frames will be added to |missing_frames_for_layer_| or // if this is an already missing frame then it will be removed. - void FrameReceivedVp9(uint16_t picture_id, const GofInfoVP9& gof) + void FrameReceivedVp9(uint16_t picture_id, GofInfo* info) EXCLUSIVE_LOCKS_REQUIRED(crit_); // Check if there is a frame with the up-switch flag set in the interval @@ -91,15 +129,43 @@ class RtpFrameReferenceFinder { // All picture ids are unwrapped to 16 bits. uint16_t UnwrapPictureId(uint16_t picture_id) EXCLUSIVE_LOCKS_REQUIRED(crit_); - // Holds the last sequence number of the last frame that has been created - // given the last sequence number of a given keyframe. - std::map> last_seq_num_gop_ - GUARDED_BY(crit_); + // Returns true if the frame is old and should be dropped. + // TODO(philipel): Remove when VP9 PID/TL0 does not jump mid-stream (should be + // around M59). + bool Vp9PidTl0Fix(const RtpFrameObject& frame, + int16_t* picture_id, + int16_t* tl0_pic_idx) EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // TODO(philipel): Remove when VP9 PID/TL0 does not jump mid-stream (should be + // around M59). + bool DetectVp9PicIdJump(int fixed_pid, + int fixed_tl0, + uint32_t timestamp) const + EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // TODO(philipel): Remove when VP9 PID/TL0 does not jump mid-stream (should be + // around M59). + bool DetectVp9Tl0PicIdxJump(int fixed_tl0, uint32_t timestamp) const + EXCLUSIVE_LOCKS_REQUIRED(crit_); + + // For every group of pictures, hold two sequence numbers. The first being + // the sequence number of the last packet of the last completed frame, and + // the second being the sequence number of the last packet of the last + // completed frame advanced by any potential continuous packets of padding. + std::map, + DescendingSeqNumComp> + last_seq_num_gop_ GUARDED_BY(crit_); // Save the last picture id in order to detect when there is a gap in frames // that have not yet been fully received. int last_picture_id_ GUARDED_BY(crit_); + // Padding packets that have been received but that are not yet continuous + // with any group of pictures. + std::set> stashed_padding_ + GUARDED_BY(crit_); + // The last unwrapped picture id. Used to unwrap the picture id from a length // of |kPicIdLength| to 16 bits. int last_unwrap_ GUARDED_BY(crit_); @@ -111,7 +177,7 @@ class RtpFrameReferenceFinder { // Frames that have been fully received but didn't have all the information // needed to determine their references. - std::queue> stashed_frames_ GUARDED_BY(crit_); + std::deque> stashed_frames_ GUARDED_BY(crit_); // Holds the information about the last completed frame for a given temporal // layer given a Tl0 picture index. @@ -128,22 +194,35 @@ class RtpFrameReferenceFinder { std::array scalability_structures_ GUARDED_BY(crit_); - // Holds the picture id and the Gof information for a given TL0 picture index. - std::map, - DescendingSeqNumComp> - gof_info_ GUARDED_BY(crit_); + // Holds the the Gof information for a given TL0 picture index. + std::map> gof_info_ + GUARDED_BY(crit_); // Keep track of which picture id and which temporal layer that had the // up switch flag set. - std::map up_switch_ GUARDED_BY(crit_); + std::map> + up_switch_ GUARDED_BY(crit_); // For every temporal layer, keep a set of which frames that are missing. std::array>, kMaxTemporalLayers> missing_frames_for_layer_ GUARDED_BY(crit_); + // How far frames have been cleared by sequence number. A frame will be + // cleared if it contains a packet with a sequence number older than + // |cleared_to_seq_num_|. + int cleared_to_seq_num_ GUARDED_BY(crit_); + OnCompleteFrameCallback* frame_callback_; + + // Vp9PidFix variables + // TODO(philipel): Remove when VP9 PID does not jump mid-stream. + int vp9_fix_last_timestamp_ = -1; + int vp9_fix_jump_timestamp_ = -1; + int vp9_fix_last_picture_id_ = -1; + int vp9_fix_pid_offset_ = 0; + int vp9_fix_last_tl0_pic_idx_ = -1; + int vp9_fix_tl0_pic_idx_offset_ = 0; }; } // namespace video_coding diff --git a/include/webrtc/modules/video_coding/session_info.h b/include/webrtc/modules/video_coding/session_info.h index e9ff251..a4eb405 100644 --- a/include/webrtc/modules/video_coding/session_info.h +++ b/include/webrtc/modules/video_coding/session_info.h @@ -12,6 +12,7 @@ #define WEBRTC_MODULES_VIDEO_CODING_SESSION_INFO_H_ #include +#include #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/include/video_coding.h" @@ -53,13 +54,6 @@ class VCMSessionInfo { bool complete() const; bool decodable() const; - // Builds fragmentation headers for VP8, each fragment being a decodable - // VP8 partition. Returns the total number of bytes which are decodable. Is - // used instead of MakeDecodable for VP8. - size_t BuildVP8FragmentationHeader(uint8_t* frame_buffer, - size_t frame_buffer_length, - RTPFragmentationHeader* fragmentation); - // Makes the frame decodable. I.e., only contain decodable NALUs. All // non-decodable NALUs will be deleted and packets will be moved to in // memory to remove any empty space. @@ -88,6 +82,8 @@ class VCMSessionInfo { int Tl0PicId() const; bool NonReference() const; + std::vector GetNaluInfos() const; + void SetGofInfo(const GofInfoVP9& gof_info, size_t idx); // The number of packets discarded because the decoder can't make use of diff --git a/include/webrtc/modules/video_coding/test/receiver_tests.h b/include/webrtc/modules/video_coding/test/receiver_tests.h index d6bac07..e2429e7 100644 --- a/include/webrtc/modules/video_coding/test/receiver_tests.h +++ b/include/webrtc/modules/video_coding/test/receiver_tests.h @@ -19,7 +19,6 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" #include "webrtc/modules/video_coding/include/video_coding.h" #include "webrtc/modules/video_coding/test/test_util.h" -#include "webrtc/modules/video_coding/test/video_source.h" #include "webrtc/typedefs.h" class RtpDataCallback : public webrtc::NullRtpData { @@ -29,7 +28,7 @@ class RtpDataCallback : public webrtc::NullRtpData { int32_t OnReceivedPayloadData( const uint8_t* payload_data, - const size_t payload_size, + size_t payload_size, const webrtc::WebRtcRTPHeader* rtp_header) override { return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header); } diff --git a/include/webrtc/modules/video_coding/test/release_test.h b/include/webrtc/modules/video_coding/test/release_test.h deleted file mode 100644 index ab9b215..0000000 --- a/include/webrtc/modules/video_coding/test/release_test.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_TEST_RELEASE_TEST_H_ -#define WEBRTC_MODULES_VIDEO_CODING_TEST_RELEASE_TEST_H_ - -int ReleaseTest(); -int ReleaseTestPart2(); - -#endif // WEBRTC_MODULES_VIDEO_CODING_TEST_RELEASE_TEST_H_ diff --git a/include/webrtc/modules/video_coding/test/test_util.h b/include/webrtc/modules/video_coding/test/test_util.h index 45b88b9..86d3ecf 100644 --- a/include/webrtc/modules/video_coding/test/test_util.h +++ b/include/webrtc/modules/video_coding/test/test_util.h @@ -29,26 +29,18 @@ class NullEvent : public webrtc::EventWrapper { public: virtual ~NullEvent() {} - virtual bool Set() { return true; } + bool Set() override { return true; } - virtual bool Reset() { return true; } - - virtual webrtc::EventTypeWrapper Wait(unsigned long max_time) { // NOLINT + webrtc::EventTypeWrapper Wait(unsigned long max_time) override { // NOLINT return webrtc::kEventTimeout; } - - virtual bool StartTimer(bool periodic, unsigned long time) { // NOLINT - return true; - } - - virtual bool StopTimer() { return true; } }; class NullEventFactory : public webrtc::EventFactory { public: virtual ~NullEventFactory() {} - virtual webrtc::EventWrapper* CreateEvent() { return new NullEvent; } + webrtc::EventWrapper* CreateEvent() override { return new NullEvent; } }; class FileOutputFrameReceiver : public webrtc::VCMReceiveCallback { @@ -57,7 +49,8 @@ class FileOutputFrameReceiver : public webrtc::VCMReceiveCallback { virtual ~FileOutputFrameReceiver(); // VCMReceiveCallback - virtual int32_t FrameToRender(webrtc::VideoFrame& video_frame); // NOLINT + int32_t FrameToRender(webrtc::VideoFrame& video_frame, + rtc::Optional qp) override; private: std::string out_filename_; diff --git a/include/webrtc/modules/video_coding/test/video_source.h b/include/webrtc/modules/video_coding/test/video_source.h deleted file mode 100644 index 19d7f50..0000000 --- a/include/webrtc/modules/video_coding/test/video_source.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_CODING_TEST_VIDEO_SOURCE_H_ -#define WEBRTC_MODULES_VIDEO_CODING_TEST_VIDEO_SOURCE_H_ - -#include - -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" -#include "webrtc/typedefs.h" - -enum VideoSize { - kUndefined, - kSQCIF, // 128*96 = 12 288 - kQQVGA, // 160*120 = 19 200 - kQCIF, // 176*144 = 25 344 - kCGA, // 320*200 = 64 000 - kQVGA, // 320*240 = 76 800 - kSIF, // 352*240 = 84 480 - kWQVGA, // 400*240 = 96 000 - kCIF, // 352*288 = 101 376 - kW288p, // 512*288 = 147 456 (WCIF) - k448p, // 576*448 = 281 088 - kVGA, // 640*480 = 307 200 - k432p, // 720*432 = 311 040 - kW432p, // 768*432 = 331 776 - k4SIF, // 704*480 = 337 920 - kW448p, // 768*448 = 344 064 - kNTSC, // 720*480 = 345 600 - kFW448p, // 800*448 = 358 400 - kWVGA, // 800*480 = 384 000 - k4CIF, // 704*576 = 405 504 - kSVGA, // 800*600 = 480 000 - kW544p, // 960*544 = 522 240 - kW576p, // 1024*576 = 589 824 (W4CIF) - kHD, // 960*720 = 691 200 - kXGA, // 1024*768 = 786 432 - kWHD, // 1280*720 = 921 600 - kFullHD, // 1440*1080 = 1 555 200 - kWFullHD, // 1920*1080 = 2 073 600 - - kNumberOfVideoSizes -}; - -class VideoSource { - public: - VideoSource(); - VideoSource(std::string fileName, - VideoSize size, - float frameRate, - webrtc::VideoType type = webrtc::kI420); - VideoSource(std::string fileName, - uint16_t width, - uint16_t height, - float frameRate = 30, - webrtc::VideoType type = webrtc::kI420); - - std::string GetFileName() const { return _fileName; } - uint16_t GetWidth() const { return _width; } - uint16_t GetHeight() const { return _height; } - webrtc::VideoType GetType() const { return _type; } - float GetFrameRate() const { return _frameRate; } - int GetWidthHeight(VideoSize size); - - // Returns the filename with the path (including the leading slash) removed. - std::string GetName() const; - - size_t GetFrameLength() const; - - private: - std::string _fileName; - uint16_t _width; - uint16_t _height; - webrtc::VideoType _type; - float _frameRate; -}; - -#endif // WEBRTC_MODULES_VIDEO_CODING_TEST_VIDEO_SOURCE_H_ diff --git a/include/webrtc/modules/video_coding/timing.h b/include/webrtc/modules/video_coding/timing.h index e593c9a..429c282 100644 --- a/include/webrtc/modules/video_coding/timing.h +++ b/include/webrtc/modules/video_coding/timing.h @@ -35,14 +35,23 @@ class VCMTiming { void ResetDecodeTime(); // Set the amount of time needed to render an image. Defaults to 10 ms. - void set_render_delay(uint32_t render_delay_ms); + void set_render_delay(int render_delay_ms); // Set the minimum time the video must be delayed on the receiver to // get the desired jitter buffer level. - void SetJitterDelay(uint32_t required_delay_ms); + void SetJitterDelay(int required_delay_ms); - // Set the minimum playout delay required to sync video with audio. - void set_min_playout_delay(uint32_t min_playout_delay); + // Set the minimum playout delay from capture to render in ms. + void set_min_playout_delay(int min_playout_delay_ms); + + // Returns the minimum playout delay from capture to render in ms. + int min_playout_delay(); + + // Set the maximum playout delay from capture to render in ms. + void set_max_playout_delay(int max_playout_delay_ms); + + // Returns the maximum playout delay from capture to render in ms. + int max_playout_delay(); // Increases or decreases the current delay to get closer to the target delay. // Calculates how long it has been since the previous call to this function, @@ -77,30 +86,30 @@ class VCMTiming { // Returns the current target delay which is required delay + decode time + // render delay. - uint32_t TargetVideoDelay() const; + int TargetVideoDelay() const; // Calculates whether or not there is enough time to decode a frame given a // certain amount of processing time. bool EnoughTimeToDecode(uint32_t available_processing_time_ms) const; - // Return current timing information. - void GetTimings(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) const; + // Return current timing information. Returns true if the first frame has been + // decoded, false otherwise. + virtual bool GetTimings(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) const; enum { kDefaultRenderDelayMs = 10 }; enum { kDelayMaxChangeMsPerS = 100 }; protected: - int64_t RequiredDecodeTimeMs() const - EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + int RequiredDecodeTimeMs() const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); int64_t RenderTimeMsInternal(uint32_t frame_timestamp, int64_t now_ms) const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); - uint32_t TargetDelayInternal() const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + int TargetDelayInternal() const EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); private: void UpdateHistograms() const; @@ -110,10 +119,16 @@ class VCMTiming { bool master_ GUARDED_BY(crit_sect_); TimestampExtrapolator* ts_extrapolator_ GUARDED_BY(crit_sect_); std::unique_ptr codec_timer_ GUARDED_BY(crit_sect_); - uint32_t render_delay_ms_ GUARDED_BY(crit_sect_); - uint32_t min_playout_delay_ms_ GUARDED_BY(crit_sect_); - uint32_t jitter_delay_ms_ GUARDED_BY(crit_sect_); - uint32_t current_delay_ms_ GUARDED_BY(crit_sect_); + int render_delay_ms_ GUARDED_BY(crit_sect_); + // Best-effort playout delay range for frames from capture to render. + // The receiver tries to keep the delay between |min_playout_delay_ms_| + // and |max_playout_delay_ms_| taking the network jitter into account. + // A special case is where min_playout_delay_ms_ = max_playout_delay_ms_ = 0, + // in which case the receiver tries to play the frames as they arrive. + int min_playout_delay_ms_ GUARDED_BY(crit_sect_); + int max_playout_delay_ms_ GUARDED_BY(crit_sect_); + int jitter_delay_ms_ GUARDED_BY(crit_sect_); + int current_delay_ms_ GUARDED_BY(crit_sect_); int last_decode_ms_ GUARDED_BY(crit_sect_); uint32_t prev_frame_timestamp_ GUARDED_BY(crit_sect_); diff --git a/include/webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h b/include/webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h new file mode 100644 index 0000000..f254e8d --- /dev/null +++ b/include/webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_DEFAULT_VIDEO_BITRATE_ALLOCATOR_H_ +#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_DEFAULT_VIDEO_BITRATE_ALLOCATOR_H_ + +#include "webrtc/common_video/include/video_bitrate_allocator.h" + +namespace webrtc { + +class DefaultVideoBitrateAllocator : public VideoBitrateAllocator { + public: + explicit DefaultVideoBitrateAllocator(const VideoCodec& codec); + ~DefaultVideoBitrateAllocator() override; + + BitrateAllocation GetAllocation(uint32_t total_bitrate, + uint32_t framerate) override; + uint32_t GetPreferredBitrateBps(uint32_t framerate) override; + + private: + const VideoCodec codec_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_DEFAULT_VIDEO_BITRATE_ALLOCATOR_H_ diff --git a/include/webrtc/modules/video_coding/utility/frame_dropper.h b/include/webrtc/modules/video_coding/utility/frame_dropper.h index 20ff3d7..71ff93d 100644 --- a/include/webrtc/modules/video_coding/utility/frame_dropper.h +++ b/include/webrtc/modules/video_coding/utility/frame_dropper.h @@ -13,7 +13,7 @@ #include -#include "webrtc/base/exp_filter.h" +#include "webrtc/base/numerics/exp_filter.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/video_coding/utility/ivf_file_writer.h b/include/webrtc/modules/video_coding/utility/ivf_file_writer.h index 25d68a2..b556111 100644 --- a/include/webrtc/modules/video_coding/utility/ivf_file_writer.h +++ b/include/webrtc/modules/video_coding/utility/ivf_file_writer.h @@ -15,38 +15,42 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/base/file.h" #include "webrtc/base/timeutils.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/video_frame.h" -#include "webrtc/system_wrappers/include/file_wrapper.h" namespace webrtc { class IvfFileWriter { public: + // Takes ownership of the file, which will be closed either through + // Close or ~IvfFileWriter. If writing a frame would take the file above the + // |byte_limit| the file will be closed, the write (and all future writes) + // will fail. A |byte_limit| of 0 is equivalent to no limit. + static std::unique_ptr Wrap(rtc::File file, size_t byte_limit); ~IvfFileWriter(); - static std::unique_ptr Open(const std::string& file_name, - VideoCodecType codec_type); - bool WriteFrame(const EncodedImage& encoded_image); + bool WriteFrame(const EncodedImage& encoded_image, VideoCodecType codec_type); bool Close(); private: - IvfFileWriter(const std::string& path_name, - std::unique_ptr file, - VideoCodecType codec_type); + explicit IvfFileWriter(rtc::File file, size_t byte_limit); + bool WriteHeader(); - bool InitFromFirstFrame(const EncodedImage& encoded_image); + bool InitFromFirstFrame(const EncodedImage& encoded_image, + VideoCodecType codec_type); - const VideoCodecType codec_type_; + VideoCodecType codec_type_; + size_t bytes_written_; + size_t byte_limit_; size_t num_frames_; uint16_t width_; uint16_t height_; int64_t last_timestamp_; bool using_capture_timestamps_; rtc::TimestampWrapAroundHandler wrap_handler_; - const std::string file_name_; - std::unique_ptr file_; + rtc::File file_; RTC_DISALLOW_COPY_AND_ASSIGN(IvfFileWriter); }; diff --git a/include/webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h b/include/webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h index b68a4b8..c5521b8 100644 --- a/include/webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h +++ b/include/webrtc/modules/video_coding/utility/mock/mock_frame_dropper.h @@ -12,8 +12,8 @@ #include -#include "testing/gmock/include/gmock/gmock.h" #include "webrtc/modules/video_coding/utility/frame_dropper.h" +#include "webrtc/test/gmock.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/include/webrtc/modules/video_coding/utility/moving_average.h b/include/webrtc/modules/video_coding/utility/moving_average.h index 494bfd5..dd42385 100644 --- a/include/webrtc/modules/video_coding/utility/moving_average.h +++ b/include/webrtc/modules/video_coding/utility/moving_average.h @@ -11,61 +11,25 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_MOVING_AVERAGE_H_ #define WEBRTC_MODULES_VIDEO_CODING_UTILITY_MOVING_AVERAGE_H_ -#include +#include -#include "webrtc/typedefs.h" +#include "webrtc/base/optional.h" namespace webrtc { -template class MovingAverage { public: - MovingAverage(); - void AddSample(T sample); - bool GetAverage(size_t num_samples, T* average); + explicit MovingAverage(size_t s); + void AddSample(int sample); + rtc::Optional GetAverage() const; + rtc::Optional GetAverage(size_t num_samples) const; void Reset(); - int size(); + size_t size() const; private: - T sum_; - std::list samples_; + size_t count_ = 0; + int sum_ = 0; + std::vector sum_history_; }; - -template -MovingAverage::MovingAverage() - : sum_(static_cast(0)) {} - -template -void MovingAverage::AddSample(T sample) { - samples_.push_back(sample); - sum_ += sample; -} - -template -bool MovingAverage::GetAverage(size_t num_samples, T* avg) { - if (num_samples > samples_.size()) - return false; - - // Remove old samples. - while (num_samples < samples_.size()) { - sum_ -= samples_.front(); - samples_.pop_front(); - } - - *avg = sum_ / static_cast(num_samples); - return true; -} - -template -void MovingAverage::Reset() { - sum_ = static_cast(0); - samples_.clear(); -} - -template -int MovingAverage::size() { - return samples_.size(); -} - } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_MOVING_AVERAGE_H_ diff --git a/include/webrtc/modules/video_coding/utility/quality_scaler.h b/include/webrtc/modules/video_coding/utility/quality_scaler.h index fe70393..bf81e76 100644 --- a/include/webrtc/modules/video_coding/utility/quality_scaler.h +++ b/include/webrtc/modules/video_coding/utility/quality_scaler.h @@ -11,65 +11,77 @@ #ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_ #define WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_ -#include "webrtc/common_video/libyuv/include/scaler.h" +#include + +#include "webrtc/common_types.h" +#include "webrtc/video_encoder.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/sequenced_task_checker.h" #include "webrtc/modules/video_coding/utility/moving_average.h" namespace webrtc { -class QualityScaler { + +// An interface for signaling requests to limit or increase the resolution or +// framerate of the captured video stream. +class AdaptationObserverInterface { public: - struct Resolution { - int width; - int height; - }; + // Indicates if the adaptation is due to overuse of the CPU resources, or if + // the quality of the encoded frames have dropped too low. + enum AdaptReason : size_t { kQuality = 0, kCpu = 1 }; + static const size_t kScaleReasonSize = 2; + // Called to signal that we can handle larger or more frequent frames. + virtual void AdaptUp(AdaptReason reason) = 0; + // Called to signal that the source should reduce the resolution or framerate. + virtual void AdaptDown(AdaptReason reason) = 0; - QualityScaler(); - void Init(int low_qp_threshold, - int high_qp_threshold, - int initial_bitrate_kbps, - int width, - int height, - int fps); - void ReportFramerate(int framerate); - void ReportQP(int qp); - void ReportDroppedFrame(); - void OnEncodeFrame(const VideoFrame& frame); - Resolution GetScaledResolution() const; - const VideoFrame& GetScaledFrame(const VideoFrame& frame); - int downscale_shift() const { return downscale_shift_; } + protected: + virtual ~AdaptationObserverInterface() {} +}; - // QP is obtained from VP8-bitstream for HW, so the QP corresponds to the - // bitstream range of [0, 127] and not the user-level range of [0,63]. - static const int kLowVp8QpThreshold; - static const int kBadVp8QpThreshold; +// QualityScaler runs asynchronously and monitors QP values of encoded frames. +// It holds a reference to a ScalingObserverInterface implementation to signal +// an intent to scale up or down. +class QualityScaler { + public: + // Construct a QualityScaler with a given |observer|. + // This starts the quality scaler periodically checking what the average QP + // has been recently. + QualityScaler(AdaptationObserverInterface* observer, + VideoCodecType codec_type); + // If specific thresholds are desired these can be supplied as |thresholds|. + QualityScaler(AdaptationObserverInterface* observer, + VideoEncoder::QpThresholds thresholds); + virtual ~QualityScaler(); + // Should be called each time the encoder drops a frame + void ReportDroppedFrame(); + // Inform the QualityScaler of the last seen QP. + void ReportQP(int qp); - // H264 QP is in the range [0, 51]. - static const int kLowH264QpThreshold; - static const int kBadH264QpThreshold; + // The following members declared protected for testing purposes + protected: + QualityScaler(AdaptationObserverInterface* observer, + VideoEncoder::QpThresholds thresholds, + int64_t sampling_period); private: - void AdjustScale(bool up); - void UpdateTargetResolution(int frame_width, int frame_height); + class CheckQPTask; + void CheckQP(); void ClearSamples(); - void UpdateSampleCounts(); - - Scaler scaler_; - VideoFrame scaled_frame_; + void ReportQPLow(); + void ReportQPHigh(); + int64_t GetSamplingPeriodMs() const; - size_t num_samples_downscale_; - size_t num_samples_upscale_; - int measure_seconds_upscale_; - MovingAverage average_qp_upscale_; - MovingAverage average_qp_downscale_; + CheckQPTask* check_qp_task_ GUARDED_BY(&task_checker_); + AdaptationObserverInterface* const observer_ GUARDED_BY(&task_checker_); + rtc::SequencedTaskChecker task_checker_; - int framerate_; - int low_qp_threshold_; - int high_qp_threshold_; - MovingAverage framedrop_percent_; - Resolution res_; + const int64_t sampling_period_ms_; + bool fast_rampup_ GUARDED_BY(&task_checker_); + MovingAverage average_qp_ GUARDED_BY(&task_checker_); + MovingAverage framedrop_percent_ GUARDED_BY(&task_checker_); - int downscale_shift_; + VideoEncoder::QpThresholds thresholds_ GUARDED_BY(&task_checker_); }; - } // namespace webrtc #endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_QUALITY_SCALER_H_ diff --git a/include/webrtc/modules/video_coding/utility/simulcast_rate_allocator.h b/include/webrtc/modules/video_coding/utility/simulcast_rate_allocator.h new file mode 100644 index 0000000..7f54f5c --- /dev/null +++ b/include/webrtc/modules/video_coding/utility/simulcast_rate_allocator.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_VIDEO_CODING_UTILITY_SIMULCAST_RATE_ALLOCATOR_H_ +#define WEBRTC_MODULES_VIDEO_CODING_UTILITY_SIMULCAST_RATE_ALLOCATOR_H_ + +#include + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/common_video/include/video_bitrate_allocator.h" +#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" +#include "webrtc/video_encoder.h" + +namespace webrtc { + +class SimulcastRateAllocator : public VideoBitrateAllocator, + public TemporalLayersListener { + public: + explicit SimulcastRateAllocator( + const VideoCodec& codec, + std::unique_ptr tl_factory); + + void OnTemporalLayersCreated(int simulcast_id, + TemporalLayers* layers) override; + + BitrateAllocation GetAllocation(uint32_t total_bitrate_bps, + uint32_t framerate) override; + uint32_t GetPreferredBitrateBps(uint32_t framerate) override; + const VideoCodec& GetCodec() const; + + private: + const VideoCodec codec_; + std::map temporal_layers_; + std::unique_ptr tl_factory_; + + RTC_DISALLOW_COPY_AND_ASSIGN(SimulcastRateAllocator); +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_VIDEO_CODING_UTILITY_SIMULCAST_RATE_ALLOCATOR_H_ diff --git a/include/webrtc/modules/video_coding/video_coding_impl.h b/include/webrtc/modules/video_coding/video_coding_impl.h index c9992b7..e4fff1e 100644 --- a/include/webrtc/modules/video_coding/video_coding_impl.h +++ b/include/webrtc/modules/video_coding/video_coding_impl.h @@ -19,7 +19,7 @@ #include "webrtc/base/onetimeevent.h" #include "webrtc/base/thread_annotations.h" -#include "webrtc/base/thread_checker.h" +#include "webrtc/base/sequenced_task_checker.h" #include "webrtc/common_video/include/frame_callback.h" #include "webrtc/modules/video_coding/codec_database.h" #include "webrtc/modules/video_coding/frame_buffer.h" @@ -34,10 +34,15 @@ namespace webrtc { +class VideoBitrateAllocator; +class VideoBitrateAllocationObserver; + namespace vcm { class VCMProcessTimer { public: + static const int64_t kDefaultProcessIntervalMs = 1000; + VCMProcessTimer(int64_t periodMs, Clock* clock) : _clock(clock), _periodMs(periodMs), @@ -58,7 +63,6 @@ class VideoSender : public Module { VideoSender(Clock* clock, EncodedImageCallback* post_encode_callback, - VideoEncoderRateObserver* encoder_rate_observer, VCMSendStatisticsCallback* send_stats_callback); ~VideoSender(); @@ -76,12 +80,27 @@ class VideoSender : public Module { int Bitrate(unsigned int* bitrate) const; int FrameRate(unsigned int* framerate) const; - int32_t SetChannelParameters(uint32_t target_bitrate, // bits/s. - uint8_t lossRate, - int64_t rtt); - + // Update the channel parameters based on new rates and rtt. This will also + // cause an immediate call to VideoEncoder::SetRateAllocation(). + int32_t SetChannelParameters( + uint32_t target_bitrate_bps, + uint8_t loss_rate, + int64_t rtt, + VideoBitrateAllocator* bitrate_allocator, + VideoBitrateAllocationObserver* bitrate_updated_callback); + + // Updates the channel parameters with a new bitrate allocation, but using the + // current targit_bitrate, loss rate and rtt. That is, the distribution or + // caps may be updated to a change to a new VideoCodec or allocation mode. + // The new parameters will be stored as pending EncoderParameters, and the + // encoder will only be updated on the next frame. + void UpdateChannelParemeters( + VideoBitrateAllocator* bitrate_allocator, + VideoBitrateAllocationObserver* bitrate_updated_callback); + + // Deprecated: + // TODO(perkj): Remove once no projects use it. int32_t RegisterProtectionCallback(VCMProtectionCallback* protection); - void SetVideoProtection(VCMVideoProtection videoProtection); int32_t AddVideoFrame(const VideoFrame& videoFrame, const CodecSpecificInfo* codecSpecificInfo); @@ -89,14 +108,15 @@ class VideoSender : public Module { int32_t IntraFrameRequest(size_t stream_index); int32_t EnableFrameDropper(bool enable); - void SuspendBelowMinBitrate(); - bool VideoSuspended() const; - int64_t TimeUntilNextProcess() override; void Process() override; private: - void SetEncoderParameters(EncoderParameters params) + EncoderParameters UpdateEncoderParameters( + const EncoderParameters& params, + VideoBitrateAllocator* bitrate_allocator, + uint32_t target_bitrate_bps); + void SetEncoderParameters(EncoderParameters params, bool has_internal_source) EXCLUSIVE_LOCKS_REQUIRED(encoder_crit_); Clock* const clock_; @@ -105,6 +125,7 @@ class VideoSender : public Module { VCMGenericEncoder* _encoder; media_optimization::MediaOptimization _mediaOpt; VCMEncodedFrameCallback _encodedFrameCallback GUARDED_BY(encoder_crit_); + EncodedImageCallback* const post_encode_callback_; VCMSendStatisticsCallback* const send_stats_callback_; VCMCodecDataBase _codecDataBase GUARDED_BY(encoder_crit_); bool frame_dropper_enabled_ GUARDED_BY(encoder_crit_); @@ -112,14 +133,11 @@ class VideoSender : public Module { // Must be accessed on the construction thread of VideoSender. VideoCodec current_codec_; - rtc::ThreadChecker main_thread_; - - VCMProtectionCallback* protection_callback_; + rtc::SequencedTaskChecker sequenced_checker_; rtc::CriticalSection params_crit_; EncoderParameters encoder_params_ GUARDED_BY(params_crit_); bool encoder_has_internal_source_ GUARDED_BY(params_crit_); - std::string encoder_name_ GUARDED_BY(params_crit_); std::vector next_frame_types_ GUARDED_BY(params_crit_); }; @@ -130,6 +148,7 @@ class VideoReceiver : public Module { VideoReceiver(Clock* clock, EventFactory* event_factory, EncodedImageCallback* pre_decode_image_callback, + VCMTiming* timing, NackSender* nack_sender = nullptr, KeyFrameRequestSender* keyframe_request_sender = nullptr); ~VideoReceiver(); @@ -150,6 +169,8 @@ class VideoReceiver : public Module { int32_t Decode(uint16_t maxWaitTimeMs); + int32_t Decode(const webrtc::VCMEncodedFrame* frame); + int32_t ReceiveCodec(VideoCodec* currentReceiveCodec) const; VideoCodecType ReceiveCodec() const; @@ -188,7 +209,7 @@ class VideoReceiver : public Module { Clock* const clock_; rtc::CriticalSection process_crit_; rtc::CriticalSection receive_crit_; - VCMTiming _timing; + VCMTiming* _timing; VCMReceiver _receiver; VCMDecodedFrameCallback _decodedFrameCallback; VCMFrameTypeCallback* _frameTypeCallback GUARDED_BY(process_crit_); diff --git a/include/webrtc/modules/video_processing/frame_preprocessor.h b/include/webrtc/modules/video_processing/frame_preprocessor.h deleted file mode 100644 index 4ac6b76..0000000 --- a/include/webrtc/modules/video_processing/frame_preprocessor.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_ - -#include - -#include "webrtc/modules/video_processing/include/video_processing.h" -#include "webrtc/modules/video_processing/spatial_resampler.h" -#include "webrtc/modules/video_processing/video_decimator.h" -#include "webrtc/typedefs.h" -#include "webrtc/video_frame.h" - -namespace webrtc { - -class VideoDenoiser; - -// All pointers/members in this class are assumed to be protected by the class -// owner. -class VPMFramePreprocessor { - public: - VPMFramePreprocessor(); - ~VPMFramePreprocessor(); - - void Reset(); - - // Enable temporal decimation. - void EnableTemporalDecimation(bool enable); - - void SetInputFrameResampleMode(VideoFrameResampling resampling_mode); - - // Set target resolution: frame rate and dimension. - int32_t SetTargetResolution(uint32_t width, - uint32_t height, - uint32_t frame_rate); - - // Update incoming frame rate/dimension. - void UpdateIncomingframe_rate(); - - int32_t updateIncomingFrameSize(uint32_t width, uint32_t height); - - // Set decimated values: frame rate/dimension. - uint32_t GetDecimatedFrameRate(); - uint32_t GetDecimatedWidth() const; - uint32_t GetDecimatedHeight() const; - - // Preprocess output: - void EnableDenoising(bool enable); - const VideoFrame* PreprocessFrame(const VideoFrame& frame); - - private: - // The content does not change so much every frame, so to reduce complexity - // we can compute new content metrics every |kSkipFrameCA| frames. - enum { kSkipFrameCA = 2 }; - - VideoFrame denoised_frame_[2]; - VideoFrame resampled_frame_; - VPMSpatialResampler* spatial_resampler_; - VPMVideoDecimator* vd_; - std::unique_ptr denoiser_; - uint8_t denoised_frame_toggle_; - uint32_t frame_cnt_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_ diff --git a/include/webrtc/modules/video_processing/include/video_processing.h b/include/webrtc/modules/video_processing/include/video_processing.h deleted file mode 100644 index e2069dd..0000000 --- a/include/webrtc/modules/video_processing/include/video_processing.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_H_ - -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/video_processing/include/video_processing_defines.h" -#include "webrtc/video_frame.h" - -// The module is largely intended to process video streams, except functionality -// provided by static functions which operate independent of previous frames. It -// is recommended, but not required that a unique instance be used for each -// concurrently processed stream. Similarly, it is recommended to call Reset() -// before switching to a new stream, but this is not absolutely required. -// -// The module provides basic thread safety by permitting only a single function -// to execute concurrently. - -namespace webrtc { - -class VideoProcessing { - public: - static VideoProcessing* Create(); - virtual ~VideoProcessing() {} - - // The following functions refer to the pre-processor unit within VPM. The - // pre-processor perfoms spatial/temporal decimation and content analysis on - // the frames prior to encoding. - - // Enable/disable temporal decimation - virtual void EnableTemporalDecimation(bool enable) = 0; - - virtual int32_t SetTargetResolution(uint32_t width, - uint32_t height, - uint32_t frame_rate) = 0; - - virtual uint32_t GetDecimatedFrameRate() = 0; - virtual uint32_t GetDecimatedWidth() const = 0; - virtual uint32_t GetDecimatedHeight() const = 0; - - // Set the spatial resampling settings of the VPM according to - // VideoFrameResampling. - virtual void SetInputFrameResampleMode( - VideoFrameResampling resampling_mode) = 0; - - virtual void EnableDenoising(bool enable) = 0; - virtual const VideoFrame* PreprocessFrame(const VideoFrame& frame) = 0; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_H_ diff --git a/include/webrtc/modules/video_processing/include/video_processing_defines.h b/include/webrtc/modules/video_processing/include/video_processing_defines.h deleted file mode 100644 index 9cc71bd..0000000 --- a/include/webrtc/modules/video_processing/include/video_processing_defines.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -/* - * video_processing_defines.h - * This header file includes the definitions used in the video processor module - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_DEFINES_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_DEFINES_H_ - -#include "webrtc/typedefs.h" - -namespace webrtc { - -// Error codes -#define VPM_OK 0 -#define VPM_GENERAL_ERROR -1 -#define VPM_MEMORY -2 -#define VPM_PARAMETER_ERROR -3 -#define VPM_SCALE_ERROR -4 -#define VPM_UNINITIALIZED -5 -#define VPM_UNIMPLEMENTED -6 - -enum VideoFrameResampling { - kNoRescaling, // Disables rescaling. - kFastRescaling, // Point filter. - kBiLinear, // Bi-linear interpolation. - kBox, // Box inteprolation. -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_DEFINES_H_ diff --git a/include/webrtc/modules/video_processing/spatial_resampler.h b/include/webrtc/modules/video_processing/spatial_resampler.h deleted file mode 100644 index 51820e2..0000000 --- a/include/webrtc/modules/video_processing/spatial_resampler.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_SPATIAL_RESAMPLER_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_SPATIAL_RESAMPLER_H_ - -#include "webrtc/typedefs.h" - -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/video_processing/include/video_processing_defines.h" - -#include "webrtc/common_video/libyuv/include/scaler.h" -#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" - -namespace webrtc { - -class VPMSpatialResampler { - public: - virtual ~VPMSpatialResampler() {} - virtual int32_t SetTargetFrameSize(int32_t width, int32_t height) = 0; - virtual void SetInputFrameResampleMode( - VideoFrameResampling resampling_mode) = 0; - virtual void Reset() = 0; - virtual int32_t ResampleFrame(const VideoFrame& inFrame, - VideoFrame* outFrame) = 0; - virtual int32_t TargetWidth() = 0; - virtual int32_t TargetHeight() = 0; - virtual bool ApplyResample(int32_t width, int32_t height) = 0; -}; - -class VPMSimpleSpatialResampler : public VPMSpatialResampler { - public: - VPMSimpleSpatialResampler(); - ~VPMSimpleSpatialResampler(); - virtual int32_t SetTargetFrameSize(int32_t width, int32_t height); - virtual void SetInputFrameResampleMode(VideoFrameResampling resampling_mode); - virtual void Reset(); - virtual int32_t ResampleFrame(const VideoFrame& inFrame, - VideoFrame* outFrame); - virtual int32_t TargetWidth(); - virtual int32_t TargetHeight(); - virtual bool ApplyResample(int32_t width, int32_t height); - - private: - VideoFrameResampling resampling_mode_; - int32_t target_width_; - int32_t target_height_; - Scaler scaler_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_SPATIAL_RESAMPLER_H_ diff --git a/include/webrtc/modules/video_processing/test/video_processing_unittest.h b/include/webrtc/modules/video_processing/test/video_processing_unittest.h deleted file mode 100644 index 3433c6c..0000000 --- a/include/webrtc/modules/video_processing/test/video_processing_unittest.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_TEST_VIDEO_PROCESSING_UNITTEST_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_TEST_VIDEO_PROCESSING_UNITTEST_H_ - -#include - -#include "testing/gtest/include/gtest/gtest.h" -#include "webrtc/modules/video_processing/include/video_processing.h" -#include "webrtc/system_wrappers/include/trace.h" -#include "webrtc/test/testsupport/fileutils.h" - -namespace webrtc { - -class VideoProcessingTest : public ::testing::Test { - protected: - VideoProcessingTest(); - virtual void SetUp(); - virtual void TearDown(); - static void SetUpTestCase() { - Trace::CreateTrace(); - std::string trace_file = webrtc::test::OutputPath() + "VPMTrace.txt"; - ASSERT_EQ(0, Trace::SetTraceFile(trace_file.c_str())); - } - static void TearDownTestCase() { Trace::ReturnTrace(); } - VideoProcessing* vp_; - FILE* source_file_; - VideoFrame video_frame_; - const int width_; - const int half_width_; - const int height_; - const int size_y_; - const int size_uv_; - const size_t frame_length_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_TEST_VIDEO_PROCESSING_UNITTEST_H_ diff --git a/include/webrtc/modules/video_processing/util/denoiser_filter.h b/include/webrtc/modules/video_processing/util/denoiser_filter.h index 1254a88..2fdcca0 100644 --- a/include/webrtc/modules/video_processing/util/denoiser_filter.h +++ b/include/webrtc/modules/video_processing/util/denoiser_filter.h @@ -15,7 +15,6 @@ #include #include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/video_processing/include/video_processing_defines.h" namespace webrtc { @@ -42,7 +41,7 @@ class DenoiserFilter { const uint8_t* b, int b_stride, unsigned int* sse) = 0; - virtual DenoiserDecision MbDenoise(uint8_t* mc_running_avg_y, + virtual DenoiserDecision MbDenoise(const uint8_t* mc_running_avg_y, int mc_avg_y_stride, uint8_t* running_avg_y, int avg_y_stride, diff --git a/include/webrtc/modules/video_processing/util/denoiser_filter_c.h b/include/webrtc/modules/video_processing/util/denoiser_filter_c.h index d8b6c5e..859c6f4 100644 --- a/include/webrtc/modules/video_processing/util/denoiser_filter_c.h +++ b/include/webrtc/modules/video_processing/util/denoiser_filter_c.h @@ -27,7 +27,7 @@ class DenoiserFilterC : public DenoiserFilter { const uint8_t* b, int b_stride, unsigned int* sse) override; - DenoiserDecision MbDenoise(uint8_t* mc_running_avg_y, + DenoiserDecision MbDenoise(const uint8_t* mc_running_avg_y, int mc_avg_y_stride, uint8_t* running_avg_y, int avg_y_stride, diff --git a/include/webrtc/modules/video_processing/util/denoiser_filter_neon.h b/include/webrtc/modules/video_processing/util/denoiser_filter_neon.h index 55850bd..076cb79 100644 --- a/include/webrtc/modules/video_processing/util/denoiser_filter_neon.h +++ b/include/webrtc/modules/video_processing/util/denoiser_filter_neon.h @@ -27,7 +27,7 @@ class DenoiserFilterNEON : public DenoiserFilter { const uint8_t* b, int b_stride, unsigned int* sse) override; - DenoiserDecision MbDenoise(uint8_t* mc_running_avg_y, + DenoiserDecision MbDenoise(const uint8_t* mc_running_avg_y, int mc_avg_y_stride, uint8_t* running_avg_y, int avg_y_stride, diff --git a/include/webrtc/modules/video_processing/util/denoiser_filter_sse2.h b/include/webrtc/modules/video_processing/util/denoiser_filter_sse2.h index 731344c..5b2d957 100644 --- a/include/webrtc/modules/video_processing/util/denoiser_filter_sse2.h +++ b/include/webrtc/modules/video_processing/util/denoiser_filter_sse2.h @@ -27,7 +27,7 @@ class DenoiserFilterSSE2 : public DenoiserFilter { const uint8_t* b, int b_stride, unsigned int* sse) override; - DenoiserDecision MbDenoise(uint8_t* mc_running_avg_y, + DenoiserDecision MbDenoise(const uint8_t* mc_running_avg_y, int mc_avg_y_stride, uint8_t* running_avg_y, int avg_y_stride, diff --git a/include/webrtc/modules/video_processing/util/noise_estimation.h b/include/webrtc/modules/video_processing/util/noise_estimation.h index 294bfb3..f414a47 100644 --- a/include/webrtc/modules/video_processing/util/noise_estimation.h +++ b/include/webrtc/modules/video_processing/util/noise_estimation.h @@ -14,7 +14,6 @@ #include #include "webrtc/modules/include/module_common_types.h" -#include "webrtc/modules/video_processing/include/video_processing_defines.h" #include "webrtc/modules/video_processing/util/denoiser_filter.h" namespace webrtc { diff --git a/include/webrtc/modules/video_processing/video_decimator.h b/include/webrtc/modules/video_processing/video_decimator.h deleted file mode 100644 index 1b871df..0000000 --- a/include/webrtc/modules/video_processing/video_decimator.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_DECIMATOR_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_DECIMATOR_H_ - -#include "webrtc/modules/include/module_common_types.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class VPMVideoDecimator { - public: - VPMVideoDecimator(); - ~VPMVideoDecimator(); - - void Reset(); - - void EnableTemporalDecimation(bool enable); - - void SetTargetFramerate(int frame_rate); - - bool DropFrame(); - - void UpdateIncomingframe_rate(); - - // Get Decimated Frame Rate/Dimensions. - uint32_t GetDecimatedFrameRate(); - - // Get input frame rate. - uint32_t Inputframe_rate(); - - private: - void ProcessIncomingframe_rate(int64_t now); - - enum { kFrameCountHistory_size = 90 }; - enum { kFrameHistoryWindowMs = 2000 }; - - // Temporal decimation. - int32_t overshoot_modifier_; - uint32_t drop_count_; - uint32_t keep_count_; - uint32_t target_frame_rate_; - float incoming_frame_rate_; - int64_t incoming_frame_times_[kFrameCountHistory_size]; - bool enable_temporal_decimation_; -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_DECIMATOR_H_ diff --git a/include/webrtc/modules/video_processing/video_denoiser.h b/include/webrtc/modules/video_processing/video_denoiser.h index 114f663..e67bd59 100644 --- a/include/webrtc/modules/video_processing/video_denoiser.h +++ b/include/webrtc/modules/video_processing/video_denoiser.h @@ -13,6 +13,7 @@ #include +#include "webrtc/common_video/include/i420_buffer_pool.h" #include "webrtc/modules/video_processing/util/denoiser_filter.h" #include "webrtc/modules/video_processing/util/noise_estimation.h" #include "webrtc/modules/video_processing/util/skin_detection.h" @@ -23,15 +24,12 @@ class VideoDenoiser { public: explicit VideoDenoiser(bool runtime_cpu_detection); - void DenoiseFrame(const VideoFrame& frame, - VideoFrame* denoised_frame, - VideoFrame* denoised_frame_prev, - bool noise_estimation_enabled); + rtc::scoped_refptr DenoiseFrame( + rtc::scoped_refptr frame, + bool noise_estimation_enabled); private: - void DenoiserReset(const VideoFrame& frame, - VideoFrame* denoised_frame, - VideoFrame* denoised_frame_prev); + void DenoiserReset(rtc::scoped_refptr frame); // Check the mb position, return 1: close to the frame center (between 1/8 // and 7/8 of width/height), 3: close to the border (out of 1/16 and 15/16 @@ -50,18 +48,21 @@ class VideoDenoiser { int mb_col); // Copy input blocks to dst buffer on moving object blocks (MOB). - void CopySrcOnMOB(const uint8_t* y_src, uint8_t* y_dst); + void CopySrcOnMOB(const uint8_t* y_src, + int stride_src, + uint8_t* y_dst, + int stride_dst); // Copy luma margin blocks when frame width/height not divisible by 16. - void CopyLumaOnMargin(const uint8_t* y_src, uint8_t* y_dst); + void CopyLumaOnMargin(const uint8_t* y_src, + int stride_src, + uint8_t* y_dst, + int stride_dst); int width_; int height_; int mb_rows_; int mb_cols_; - int stride_y_; - int stride_u_; - int stride_v_; CpuType cpu_type_; std::unique_ptr filter_; std::unique_ptr ne_; @@ -74,6 +75,8 @@ class VideoDenoiser { std::unique_ptr y_density_; // Save the return values by MbDenoise for each block. std::unique_ptr mb_filter_decision_; + I420BufferPool buffer_pool_; + rtc::scoped_refptr prev_buffer_; }; } // namespace webrtc diff --git a/include/webrtc/modules/video_processing/video_processing_impl.h b/include/webrtc/modules/video_processing/video_processing_impl.h deleted file mode 100644 index 21e23c9..0000000 --- a/include/webrtc/modules/video_processing/video_processing_impl.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_PROCESSING_IMPL_H_ -#define WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_PROCESSING_IMPL_H_ - -#include "webrtc/base/criticalsection.h" -#include "webrtc/modules/video_processing/include/video_processing.h" -#include "webrtc/modules/video_processing/frame_preprocessor.h" - -namespace webrtc { -class CriticalSectionWrapper; - -class VideoProcessingImpl : public VideoProcessing { - public: - VideoProcessingImpl(); - ~VideoProcessingImpl() override; - - // Implements VideoProcessing. - void EnableTemporalDecimation(bool enable) override; - void SetInputFrameResampleMode(VideoFrameResampling resampling_mode) override; - int32_t SetTargetResolution(uint32_t width, - uint32_t height, - uint32_t frame_rate) override; - uint32_t GetDecimatedFrameRate() override; - uint32_t GetDecimatedWidth() const override; - uint32_t GetDecimatedHeight() const override; - void EnableDenoising(bool enable) override; - const VideoFrame* PreprocessFrame(const VideoFrame& frame) override; - - private: - rtc::CriticalSection mutex_; - VPMFramePreprocessor frame_pre_processor_ GUARDED_BY(mutex_); -}; - -} // namespace webrtc - -#endif // WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_PROCESSING_IMPL_H_ diff --git a/include/webrtc/ortc/ortcfactory.h b/include/webrtc/ortc/ortcfactory.h new file mode 100644 index 0000000..71f525d --- /dev/null +++ b/include/webrtc/ortc/ortcfactory.h @@ -0,0 +1,144 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_ORTCFACTORY_H_ +#define WEBRTC_ORTC_ORTCFACTORY_H_ + +#include +#include + +#include "webrtc/api/ortc/ortcfactoryinterface.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/media/base/mediaengine.h" +#include "webrtc/media/engine/webrtcmediaengine.h" +#include "webrtc/pc/channelmanager.h" + +namespace webrtc { + +// Implementation of OrtcFactoryInterface. +// +// See ortcfactoryinterface.h for documentation. +class OrtcFactory : public OrtcFactoryInterface { + public: + ~OrtcFactory() override; + + // Internal-only Create method that allows passing in a fake media engine, + // for testing. + static RTCErrorOr> Create( + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + AudioDeviceModule* adm, + std::unique_ptr media_engine); + + RTCErrorOr> + CreateRtpTransportController() override; + + RTCErrorOr> CreateRtpTransport( + const RtcpParameters& rtcp_parameters, + PacketTransportInterface* rtp, + PacketTransportInterface* rtcp, + RtpTransportControllerInterface* transport_controller) override; + + RtpCapabilities GetRtpSenderCapabilities( + cricket::MediaType kind) const override; + + RTCErrorOr> CreateRtpSender( + rtc::scoped_refptr track, + RtpTransportInterface* transport) override; + + RTCErrorOr> CreateRtpSender( + cricket::MediaType kind, + RtpTransportInterface* transport) override; + + RtpCapabilities GetRtpReceiverCapabilities( + cricket::MediaType kind) const override; + + RTCErrorOr> CreateRtpReceiver( + cricket::MediaType kind, + RtpTransportInterface* transport) override; + + RTCErrorOr> + CreateUdpTransport(int family, uint16_t min_port, uint16_t max_port) override; + + rtc::scoped_refptr CreateAudioSource( + const cricket::AudioOptions& options) override; + + rtc::scoped_refptr CreateVideoSource( + std::unique_ptr capturer, + const MediaConstraintsInterface* constraints) override; + + rtc::scoped_refptr CreateVideoTrack( + const std::string& id, + VideoTrackSourceInterface* source) override; + + rtc::scoped_refptr CreateAudioTrack( + const std::string& id, + AudioSourceInterface* source) override; + + rtc::Thread* network_thread() { return network_thread_; } + rtc::Thread* worker_thread() { return worker_thread_.get(); } + rtc::Thread* signaling_thread() { return signaling_thread_; } + + private: + // Should only be called by OrtcFactoryInterface::Create. + OrtcFactory(rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + AudioDeviceModule* adm); + + // Thread::Invoke doesn't support move-only arguments, so we need to remove + // the unique_ptr wrapper from media_engine. TODO(deadbeef): Fix this. + static RTCErrorOr> Create_s( + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + AudioDeviceModule* adm, + cricket::MediaEngineInterface* media_engine); + + // Performs initialization that can fail. Called by factory method after + // construction, and if it fails, no object is returned. + RTCError Initialize( + std::unique_ptr media_engine); + std::unique_ptr CreateMediaEngine_w(); + + // Threads and networking objects. + rtc::Thread* network_thread_; + rtc::Thread* signaling_thread_; + rtc::NetworkManager* network_manager_; + rtc::PacketSocketFactory* socket_factory_; + AudioDeviceModule* adm_; + // If we created/own the objects above, these will be non-null and thus will + // be released automatically upon destruction. + std::unique_ptr owned_network_thread_; + bool wraps_signaling_thread_ = false; + std::unique_ptr owned_network_manager_; + std::unique_ptr owned_socket_factory_; + // We always own the worker thread. + std::unique_ptr worker_thread_; + // Media-releated objects. + std::unique_ptr null_event_log_; + rtc::scoped_refptr audio_decoder_factory_; + std::unique_ptr channel_manager_; + // Default CNAME to use for RtpTransports if none is passed in. + std::string default_cname_; + + friend class OrtcFactoryInterface; + + RTC_DISALLOW_COPY_AND_ASSIGN(OrtcFactory); +}; + +} // namespace webrtc + +#endif // WEBRTC_ORTC_ORTCFACTORY_H_ diff --git a/include/webrtc/ortc/ortcrtpreceiveradapter.h b/include/webrtc/ortc/ortcrtpreceiveradapter.h new file mode 100644 index 0000000..8e081e7 --- /dev/null +++ b/include/webrtc/ortc/ortcrtpreceiveradapter.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_ORTCRTPRECEIVERADAPTER_H_ +#define WEBRTC_ORTC_ORTCRTPRECEIVERADAPTER_H_ + +#include + +#include "webrtc/api/ortc/ortcrtpreceiverinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/thread.h" +#include "webrtc/ortc/rtptransportcontrolleradapter.h" +#include "webrtc/pc/rtpreceiver.h" + +namespace webrtc { + +// Implementation of OrtcRtpReceiverInterface that works with +// RtpTransportAdapter, and wraps a VideoRtpReceiver/AudioRtpReceiver that's +// normally used with the PeerConnection. +// +// TODO(deadbeef): When BaseChannel is split apart into separate +// "RtpReceiver"/"RtpTransceiver"/"RtpReceiver"/"RtpReceiver" objects, this +// adapter object can be removed. +class OrtcRtpReceiverAdapter : public OrtcRtpReceiverInterface { + public: + // Wraps |wrapped_receiver| in a proxy that will safely call methods on the + // correct thread. + static std::unique_ptr CreateProxy( + std::unique_ptr wrapped_receiver); + + // Should only be called by RtpTransportControllerAdapter. + OrtcRtpReceiverAdapter( + cricket::MediaType kind, + RtpTransportInterface* transport, + RtpTransportControllerAdapter* rtp_transport_controller); + ~OrtcRtpReceiverAdapter() override; + + // OrtcRtpReceiverInterface implementation. + rtc::scoped_refptr GetTrack() const override; + + RTCError SetTransport(RtpTransportInterface* transport) override; + RtpTransportInterface* GetTransport() const override; + + RTCError Receive(const RtpParameters& parameters) override; + RtpParameters GetParameters() const override; + + cricket::MediaType GetKind() const override; + + // Used so that the RtpTransportControllerAdapter knows when it can + // deallocate resources allocated for this object. + sigslot::signal0<> SignalDestroyed; + + private: + void MaybeRecreateInternalReceiver(); + + cricket::MediaType kind_; + RtpTransportInterface* transport_; + RtpTransportControllerAdapter* rtp_transport_controller_; + // Scoped refptr due to ref-counted interface, but we should be the only + // reference holder. + rtc::scoped_refptr internal_receiver_; + RtpParameters last_applied_parameters_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(OrtcRtpReceiverAdapter); +}; + +} // namespace webrtc + +#endif // WEBRTC_ORTC_ORTCRTPRECEIVERADAPTER_H_ diff --git a/include/webrtc/ortc/ortcrtpsenderadapter.h b/include/webrtc/ortc/ortcrtpsenderadapter.h new file mode 100644 index 0000000..9b60f15 --- /dev/null +++ b/include/webrtc/ortc/ortcrtpsenderadapter.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_ORTCRTPSENDERADAPTER_H_ +#define WEBRTC_ORTC_ORTCRTPSENDERADAPTER_H_ + +#include + +#include "webrtc/api/ortc/ortcrtpsenderinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/ortc/rtptransportcontrolleradapter.h" +#include "webrtc/pc/rtpsender.h" + +namespace webrtc { + +// Implementation of OrtcRtpSenderInterface that works with RtpTransportAdapter, +// and wraps a VideoRtpSender/AudioRtpSender that's normally used with the +// PeerConnection. +// +// TODO(deadbeef): When BaseChannel is split apart into separate +// "RtpSender"/"RtpTransceiver"/"RtpSender"/"RtpReceiver" objects, this adapter +// object can be removed. +class OrtcRtpSenderAdapter : public OrtcRtpSenderInterface { + public: + // Wraps |wrapped_sender| in a proxy that will safely call methods on the + // correct thread. + static std::unique_ptr CreateProxy( + std::unique_ptr wrapped_sender); + + // Should only be called by RtpTransportControllerAdapter. + OrtcRtpSenderAdapter(cricket::MediaType kind, + RtpTransportInterface* transport, + RtpTransportControllerAdapter* rtp_transport_controller); + ~OrtcRtpSenderAdapter() override; + + // OrtcRtpSenderInterface implementation. + RTCError SetTrack(MediaStreamTrackInterface* track) override; + rtc::scoped_refptr GetTrack() const override; + + RTCError SetTransport(RtpTransportInterface* transport) override; + RtpTransportInterface* GetTransport() const override; + + RTCError Send(const RtpParameters& parameters) override; + RtpParameters GetParameters() const override; + + cricket::MediaType GetKind() const override; + + // Used so that the RtpTransportControllerAdapter knows when it can + // deallocate resources allocated for this object. + sigslot::signal0<> SignalDestroyed; + + private: + void CreateInternalSender(); + + cricket::MediaType kind_; + RtpTransportInterface* transport_; + RtpTransportControllerAdapter* rtp_transport_controller_; + // Scoped refptr due to ref-counted interface, but we should be the only + // reference holder. + rtc::scoped_refptr internal_sender_; + rtc::scoped_refptr track_; + RtpParameters last_applied_parameters_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(OrtcRtpSenderAdapter); +}; + +} // namespace webrtc + +#endif // WEBRTC_ORTC_ORTCRTPSENDERADAPTER_H_ diff --git a/include/webrtc/ortc/rtpparametersconversion.h b/include/webrtc/ortc/rtpparametersconversion.h new file mode 100644 index 0000000..a1680a2 --- /dev/null +++ b/include/webrtc/ortc/rtpparametersconversion.h @@ -0,0 +1,96 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_RTPPARAMETERSCONVERSION_H_ +#define WEBRTC_ORTC_RTPPARAMETERSCONVERSION_H_ + +#include +#include + +#include "webrtc/api/rtcerror.h" +#include "webrtc/api/rtpparameters.h" +#include "webrtc/base/optional.h" +#include "webrtc/pc/mediasession.h" +#include "webrtc/media/base/codec.h" + +namespace webrtc { + +// NOTE: Some functions are templated for convenience, such that template-based +// code dealing with AudioContentDescription and VideoContentDescription can +// use this easily. Such methods are usable with cricket::AudioCodec and +// cricket::VideoCodec. + +//*************************************************************************** +// Functions for converting from new webrtc:: structures to old cricket:: +// structures. +// +// As the return values imply, all of these functions do validation of the +// parameters and return an error if they're invalid. It's expected that any +// default values (such as video clock rate of 90000) have been filled by the +// time the webrtc:: structure is being converted to the cricket:: one. +// +// These are expected to be used when parameters are passed into an RtpSender +// or RtpReceiver, and need to be validated and converted so they can be +// applied to the media engine level. +//*************************************************************************** + +// Returns error on invalid input. Certain message types are only valid for +// certain feedback types. +RTCErrorOr ToCricketFeedbackParam( + const RtcpFeedback& feedback); + +// Verifies that the codec kind is correct, and it has mandatory parameters +// filled, with values in valid ranges. +template +RTCErrorOr ToCricketCodec(const RtpCodecParameters& codec); + +// Verifies that payload types aren't duplicated, in addition to normal +// validation. +template +RTCErrorOr> ToCricketCodecs( + const std::vector& codecs); + +// Validates that header extension IDs aren't duplicated. +RTCErrorOr ToCricketRtpHeaderExtensions( + const std::vector& extensions); + +// SSRCs are allowed to be ommitted. This may be used for receive parameters +// where SSRCs are unsignaled. +RTCErrorOr ToCricketStreamParamsVec( + const std::vector& encodings); + +//***************************************************************************** +// Functions for converting from old cricket:: structures to new webrtc:: +// structures. Unlike the above functions, these are permissive with regards to +// input validation; it's assumed that any necessary validation already +// occurred. +// +// These are expected to be used either to convert from audio/video engine +// capabilities to RtpCapabilities, or to convert from already-parsed SDP +// (in the form of cricket:: structures) to webrtc:: structures. The latter +// functionality is not yet implemented. +//***************************************************************************** + +// Returns empty value if |cricket_feedback| is a feedback type not +// supported/recognized. +rtc::Optional ToRtcpFeedback( + const cricket::FeedbackParam& cricket_feedback); + +template +RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec); + +template +RtpCapabilities ToRtpCapabilities( + const std::vector& cricket_codecs, + const cricket::RtpHeaderExtensions& cricket_extensions); + +} // namespace webrtc + +#endif // WEBRTC_ORTC_RTPPARAMETERSCONVERSION_H_ diff --git a/include/webrtc/ortc/rtptransportadapter.h b/include/webrtc/ortc/rtptransportadapter.h new file mode 100644 index 0000000..169ae61 --- /dev/null +++ b/include/webrtc/ortc/rtptransportadapter.h @@ -0,0 +1,83 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_RTPTRANSPORTADAPTER_H_ +#define WEBRTC_ORTC_RTPTRANSPORTADAPTER_H_ + +#include +#include + +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/api/rtcerror.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/media/base/streamparams.h" +#include "webrtc/ortc/rtptransportcontrolleradapter.h" +#include "webrtc/pc/channel.h" + +namespace webrtc { + +// Implementation of RtpTransportInterface to be used with RtpSenderAdapter, +// RtpReceiverAdapter, and RtpTransportControllerAdapter classes. +// +// TODO(deadbeef): When BaseChannel is split apart into separate +// "RtpTransport"/"RtpTransceiver"/"RtpSender"/"RtpReceiver" objects, this +// adapter object can be removed. +class RtpTransportAdapter : public RtpTransportInterface { + public: + // |rtp| can't be null. |rtcp| can if RTCP muxing is used immediately (meaning + // |rtcp_parameters.mux| is also true). + static RTCErrorOr> CreateProxied( + const RtcpParameters& rtcp_parameters, + PacketTransportInterface* rtp, + PacketTransportInterface* rtcp, + RtpTransportControllerAdapter* rtp_transport_controller); + ~RtpTransportAdapter() override; + + // RtpTransportInterface implementation. + PacketTransportInterface* GetRtpPacketTransport() const override; + PacketTransportInterface* GetRtcpPacketTransport() const override; + RTCError SetRtcpParameters(const RtcpParameters& parameters) override; + RtcpParameters GetRtcpParameters() const override { return rtcp_parameters_; } + + // Methods used internally by OrtcFactory. + RtpTransportControllerAdapter* rtp_transport_controller() { + return rtp_transport_controller_; + } + void TakeOwnershipOfRtpTransportController( + std::unique_ptr controller); + + // Used by RtpTransportControllerAdapter to tell when it should stop + // returning this transport from GetTransports(). + sigslot::signal1 SignalDestroyed; + + protected: + RtpTransportAdapter* GetInternal() override { return this; } + + private: + RtpTransportAdapter(const RtcpParameters& rtcp_parameters, + PacketTransportInterface* rtp, + PacketTransportInterface* rtcp, + RtpTransportControllerAdapter* rtp_transport_controller); + + PacketTransportInterface* rtp_packet_transport_; + PacketTransportInterface* rtcp_packet_transport_; + RtpTransportControllerAdapter* rtp_transport_controller_; + // Non-null if this class owns the transport controller. + std::unique_ptr + owned_rtp_transport_controller_; + RtcpParameters rtcp_parameters_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtpTransportAdapter); +}; + +} // namespace webrtc + +#endif // WEBRTC_ORTC_RTPTRANSPORTADAPTER_H_ diff --git a/include/webrtc/ortc/rtptransportcontrolleradapter.h b/include/webrtc/ortc/rtptransportcontrolleradapter.h new file mode 100644 index 0000000..4e02b95 --- /dev/null +++ b/include/webrtc/ortc/rtptransportcontrolleradapter.h @@ -0,0 +1,202 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_RTPTRANSPORTCONTROLLERADAPTER_H_ +#define WEBRTC_ORTC_RTPTRANSPORTCONTROLLERADAPTER_H_ + +#include +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/thread.h" +#include "webrtc/call/call.h" +#include "webrtc/logging/rtc_event_log/rtc_event_log.h" +#include "webrtc/api/ortc/ortcrtpreceiverinterface.h" +#include "webrtc/api/ortc/ortcrtpsenderinterface.h" +#include "webrtc/api/ortc/rtptransportcontrollerinterface.h" +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/pc/channelmanager.h" +#include "webrtc/pc/mediacontroller.h" +#include "webrtc/media/base/mediachannel.h" // For MediaConfig. + +namespace webrtc { + +class RtpTransportAdapter; +class OrtcRtpSenderAdapter; +class OrtcRtpReceiverAdapter; + +// Implementation of RtpTransportControllerInterface. Wraps a MediaController, +// a VoiceChannel and VideoChannel, and maintains a list of dependent RTP +// transports. +// +// When used along with an RtpSenderAdapter or RtpReceiverAdapter, the +// sender/receiver passes its parameters along to this class, which turns them +// into cricket:: media descriptions (the interface used by BaseChannel). +// +// Due to the fact that BaseChannel has different subclasses for audio/video, +// the actual BaseChannel object is not created until an RtpSender/RtpReceiver +// needs them. +// +// All methods should be called on the signaling thread. +// +// TODO(deadbeef): When BaseChannel is split apart into separate +// "RtpSender"/"RtpTransceiver"/"RtpSender"/"RtpReceiver" objects, this adapter +// object can be replaced by a "real" one. +class RtpTransportControllerAdapter : public RtpTransportControllerInterface, + public sigslot::has_slots<> { + public: + // Creates a proxy that will call "public interface" methods on the correct + // thread. + // + // Doesn't take ownership of any objects passed in. + // + // |channel_manager| must not be null. + static std::unique_ptr CreateProxied( + const cricket::MediaConfig& config, + cricket::ChannelManager* channel_manager, + webrtc::RtcEventLog* event_log, + rtc::Thread* signaling_thread, + rtc::Thread* worker_thread); + + ~RtpTransportControllerAdapter() override; + + // RtpTransportControllerInterface implementation. + std::vector GetTransports() const override; + + // These methods are used by OrtcFactory to create RtpTransports, RtpSenders + // and RtpReceivers using this controller. Called "CreateProxied" because + // these methods return proxies that will safely call methods on the correct + // thread. + RTCErrorOr> CreateProxiedRtpTransport( + const RtcpParameters& rtcp_parameters, + PacketTransportInterface* rtp, + PacketTransportInterface* rtcp); + // |transport_proxy| needs to be a proxy to a transport because the + // application may call GetTransport() on the returned sender or receiver, + // and expects it to return a thread-safe transport proxy. + RTCErrorOr> CreateProxiedRtpSender( + cricket::MediaType kind, + RtpTransportInterface* transport_proxy); + RTCErrorOr> + CreateProxiedRtpReceiver(cricket::MediaType kind, + RtpTransportInterface* transport_proxy); + + // Methods used internally by other "adapter" classes. + rtc::Thread* signaling_thread() const { return signaling_thread_; } + rtc::Thread* worker_thread() const { return worker_thread_; } + + RTCError SetRtcpParameters(const RtcpParameters& parameters, + RtpTransportInterface* inner_transport); + + cricket::VoiceChannel* voice_channel() { return voice_channel_; } + cricket::VideoChannel* video_channel() { return video_channel_; } + + // |primary_ssrc| out parameter is filled with either + // |parameters.encodings[0].ssrc|, or a generated SSRC if that's left unset. + RTCError ValidateAndApplyAudioSenderParameters( + const RtpParameters& parameters, + uint32_t* primary_ssrc); + RTCError ValidateAndApplyVideoSenderParameters( + const RtpParameters& parameters, + uint32_t* primary_ssrc); + RTCError ValidateAndApplyAudioReceiverParameters( + const RtpParameters& parameters); + RTCError ValidateAndApplyVideoReceiverParameters( + const RtpParameters& parameters); + + protected: + RtpTransportControllerAdapter* GetInternal() override { return this; } + + private: + // Only expected to be called by RtpTransportControllerAdapter::CreateProxied. + RtpTransportControllerAdapter(const cricket::MediaConfig& config, + cricket::ChannelManager* channel_manager, + webrtc::RtcEventLog* event_log, + rtc::Thread* signaling_thread, + rtc::Thread* worker_thread); + + // These return an error if another of the same type of object is already + // attached, or if |transport_proxy| can't be used with the sender/receiver + // due to the limitation that the sender/receiver of the same media type must + // use the same transport. + RTCError AttachAudioSender(OrtcRtpSenderAdapter* sender, + RtpTransportInterface* inner_transport); + RTCError AttachVideoSender(OrtcRtpSenderAdapter* sender, + RtpTransportInterface* inner_transport); + RTCError AttachAudioReceiver(OrtcRtpReceiverAdapter* receiver, + RtpTransportInterface* inner_transport); + RTCError AttachVideoReceiver(OrtcRtpReceiverAdapter* receiver, + RtpTransportInterface* inner_transport); + + void OnRtpTransportDestroyed(RtpTransportAdapter* transport); + + void OnAudioSenderDestroyed(); + void OnVideoSenderDestroyed(); + void OnAudioReceiverDestroyed(); + void OnVideoReceiverDestroyed(); + + void CreateVoiceChannel(); + void CreateVideoChannel(); + void DestroyVoiceChannel(); + void DestroyVideoChannel(); + + void CopyRtcpParametersToDescriptions( + const RtcpParameters& params, + cricket::MediaContentDescription* local, + cricket::MediaContentDescription* remote); + + // Helper function to generate an SSRC that doesn't match one in any of the + // "content description" structs, or in |new_ssrcs| (which is needed since + // multiple SSRCs may be generated in one go). + uint32_t GenerateUnusedSsrc(std::set* new_ssrcs) const; + + // |description| is the matching description where existing SSRCs can be + // found. + // + // This is a member function because it may need to generate SSRCs that don't + // match existing ones, which is more than ToStreamParamsVec does. + RTCErrorOr MakeSendStreamParamsVec( + std::vector encodings, + const std::string& cname, + const cricket::MediaContentDescription& description) const; + + rtc::Thread* signaling_thread_; + rtc::Thread* worker_thread_; + // |transport_proxies_| and |inner_audio_transport_|/|inner_audio_transport_| + // are somewhat redundant, but the latter are only set when + // RtpSenders/RtpReceivers are attached to the transport. + std::vector transport_proxies_; + RtpTransportInterface* inner_audio_transport_ = nullptr; + RtpTransportInterface* inner_video_transport_ = nullptr; + std::unique_ptr media_controller_; + + // BaseChannel takes content descriptions as input, so we store them here + // such that they can be updated when a new RtpSenderAdapter/ + // RtpReceiverAdapter attaches itself. + cricket::AudioContentDescription local_audio_description_; + cricket::AudioContentDescription remote_audio_description_; + cricket::VideoContentDescription local_video_description_; + cricket::VideoContentDescription remote_video_description_; + cricket::VoiceChannel* voice_channel_ = nullptr; + cricket::VideoChannel* video_channel_ = nullptr; + bool have_audio_sender_ = false; + bool have_video_sender_ = false; + bool have_audio_receiver_ = false; + bool have_video_receiver_ = false; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RtpTransportControllerAdapter); +}; + +} // namespace webrtc + +#endif // WEBRTC_ORTC_RTPTRANSPORTCONTROLLERADAPTER_H_ diff --git a/include/webrtc/ortc/testrtpparameters.h b/include/webrtc/ortc/testrtpparameters.h new file mode 100644 index 0000000..87108ca --- /dev/null +++ b/include/webrtc/ortc/testrtpparameters.h @@ -0,0 +1,72 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_ORTC_TESTRTPPARAMETERS_H_ +#define WEBRTC_ORTC_TESTRTPPARAMETERS_H_ + +#include "webrtc/api/ortc/rtptransportinterface.h" +#include "webrtc/api/rtpparameters.h" + +namespace webrtc { + +// Helper methods to create RtpParameters to use for sending/receiving. +// +// "MakeMinimal" methods contain the minimal necessary information for an +// RtpSender or RtpReceiver to function. The "MakeFull" methods are the +// opposite, and include all features that would normally be offered by a +// PeerConnection, and in some cases additional ones. +// +// These methods are intended to be used for end-to-end testing (such as in +// ortcfactory_integrationtest.cc), or unit testing that doesn't care about the +// specific contents of the parameters. Tests should NOT assume that these +// methods will not change; tests that are testing that a specific value in the +// parameters is applied properly should construct the parameters in the test +// itself. + +inline RtcpParameters MakeRtcpMuxParameters() { + RtcpParameters rtcp_parameters; + rtcp_parameters.mux = true; + return rtcp_parameters; +} + +RtpParameters MakeMinimalOpusParameters(); +RtpParameters MakeMinimalIsacParameters(); +RtpParameters MakeMinimalOpusParametersWithSsrc(uint32_t ssrc); +RtpParameters MakeMinimalIsacParametersWithSsrc(uint32_t ssrc); + +RtpParameters MakeMinimalVp8Parameters(); +RtpParameters MakeMinimalVp9Parameters(); +RtpParameters MakeMinimalVp8ParametersWithSsrc(uint32_t ssrc); +RtpParameters MakeMinimalVp9ParametersWithSsrc(uint32_t ssrc); + +// Will create an encoding with no SSRC (meaning "match first SSRC seen" for a +// receiver, or "pick one automatically" for a sender). +RtpParameters MakeMinimalOpusParametersWithNoSsrc(); +RtpParameters MakeMinimalIsacParametersWithNoSsrc(); +RtpParameters MakeMinimalVp8ParametersWithNoSsrc(); +RtpParameters MakeMinimalVp9ParametersWithNoSsrc(); + +// Make audio parameters with all the available properties configured and +// features used, and with multiple codecs offered. Obtained by taking a +// snapshot of a default PeerConnection offer (and adding other things, like +// bitrate limit). +RtpParameters MakeFullOpusParameters(); +RtpParameters MakeFullIsacParameters(); + +// Make video parameters with all the available properties configured and +// features used, and with multiple codecs offered. Obtained by taking a +// snapshot of a default PeerConnection offer (and adding other things, like +// bitrate limit). +RtpParameters MakeFullVp8Parameters(); +RtpParameters MakeFullVp9Parameters(); + +} // namespace webrtc + +#endif // WEBRTC_ORTC_TESTRTPPARAMETERS_H_ diff --git a/include/webrtc/p2p/base/candidate.h b/include/webrtc/p2p/base/candidate.h index b918344..723dbc9 100644 --- a/include/webrtc/p2p/base/candidate.h +++ b/include/webrtc/p2p/base/candidate.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -20,15 +21,13 @@ #include #include "webrtc/p2p/base/p2pconstants.h" -#include "webrtc/base/basictypes.h" +#include "webrtc/base/checks.h" #include "webrtc/base/helpers.h" #include "webrtc/base/network.h" #include "webrtc/base/socketaddress.h" namespace cricket { -const uint16_t kMaxNetworkCost = 999; - // Candidate for ICE based connection discovery. class Candidate { @@ -148,9 +147,9 @@ class Candidate { // |network_cost| measures the cost/penalty of using this candidate. A network // cost of 0 indicates this candidate can be used freely. A value of - // |kMaxNetworkCost| indicates it should be used only as the last resort. + // rtc::kNetworkCostMax indicates it should be used only as the last resort. void set_network_cost(uint16_t network_cost) { - ASSERT(network_cost <= kMaxNetworkCost); + RTC_DCHECK_LE(network_cost, rtc::kNetworkCostMax); network_cost_ = network_cost; } uint16_t network_cost() const { return network_cost_; } @@ -162,7 +161,6 @@ class Candidate { const std::string& foundation() const { return foundation_; } - void set_foundation(const std::string& foundation) { foundation_ = foundation; } @@ -185,6 +183,10 @@ class Candidate { transport_name_ = transport_name; } + // The URL of the ICE server which this candidate is gathered from. + const std::string& url() const { return url_; } + void set_url(const std::string& url) { url_ = url; } + // Determines whether this candidate is equivalent to the given one. bool IsEquivalent(const Candidate& c) const { // We ignore the network name, since that is just debug information, and @@ -285,6 +287,7 @@ class Candidate { std::string transport_name_; uint16_t network_id_; uint16_t network_cost_; + std::string url_; }; // Used during parsing and writing to map component to channel name diff --git a/include/webrtc/p2p/base/dtlstransport.h b/include/webrtc/p2p/base/dtlstransport.h deleted file mode 100644 index a4bf383..0000000 --- a/include/webrtc/p2p/base/dtlstransport.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright 2012 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ -#define WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ - -#include - -#include "webrtc/p2p/base/dtlstransportchannel.h" -#include "webrtc/p2p/base/transport.h" - -namespace rtc { -class SSLIdentity; -} - -namespace cricket { - -class PortAllocator; - -// Base should be a descendant of cricket::Transport and have a constructor -// that takes a transport name and PortAllocator. -// -// Everything in this class should be called on the worker thread. -template -class DtlsTransport : public Base { - public: - DtlsTransport(const std::string& name, - PortAllocator* allocator, - const rtc::scoped_refptr& certificate) - : Base(name, allocator), - certificate_(certificate), - secure_role_(rtc::SSL_CLIENT), - ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12) {} - - ~DtlsTransport() { - Base::DestroyAllChannels(); - } - - void SetLocalCertificate( - const rtc::scoped_refptr& certificate) override { - certificate_ = certificate; - } - bool GetLocalCertificate( - rtc::scoped_refptr* certificate) override { - if (!certificate_) - return false; - - *certificate = certificate_; - return true; - } - - bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override { - ssl_max_version_ = version; - return true; - } - - bool ApplyLocalTransportDescription(TransportChannelImpl* channel, - std::string* error_desc) override { - rtc::SSLFingerprint* local_fp = - Base::local_description()->identity_fingerprint.get(); - - if (!local_fp) { - certificate_ = nullptr; - } else if (!Base::VerifyCertificateFingerprint(certificate_.get(), local_fp, - error_desc)) { - return false; - } - - if (!channel->SetLocalCertificate(certificate_)) { - return BadTransportDescription("Failed to set local identity.", - error_desc); - } - - // Apply the description in the base class. - return Base::ApplyLocalTransportDescription(channel, error_desc); - } - - bool NegotiateTransportDescription(ContentAction local_role, - std::string* error_desc) override { - if (!Base::local_description() || !Base::remote_description()) { - const std::string msg = "Local and Remote description must be set before " - "transport descriptions are negotiated"; - return BadTransportDescription(msg, error_desc); - } - rtc::SSLFingerprint* local_fp = - Base::local_description()->identity_fingerprint.get(); - rtc::SSLFingerprint* remote_fp = - Base::remote_description()->identity_fingerprint.get(); - if (remote_fp && local_fp) { - remote_fingerprint_.reset(new rtc::SSLFingerprint(*remote_fp)); - if (!Base::NegotiateRole(local_role, &secure_role_, error_desc)) { - return false; - } - } else if (local_fp && (local_role == CA_ANSWER)) { - return BadTransportDescription( - "Local fingerprint supplied when caller didn't offer DTLS.", - error_desc); - } else { - // We are not doing DTLS - remote_fingerprint_.reset(new rtc::SSLFingerprint("", nullptr, 0)); - } - // Now run the negotiation for the base class. - return Base::NegotiateTransportDescription(local_role, error_desc); - } - - DtlsTransportChannelWrapper* CreateTransportChannel(int component) override { - DtlsTransportChannelWrapper* channel = new DtlsTransportChannelWrapper( - Base::CreateTransportChannel(component)); - channel->SetSslMaxProtocolVersion(ssl_max_version_); - return channel; - } - - void DestroyTransportChannel(TransportChannelImpl* channel) override { - // Kind of ugly, but this lets us do the exact inverse of the create. - DtlsTransportChannelWrapper* dtls_channel = - static_cast(channel); - TransportChannelImpl* base_channel = dtls_channel->channel(); - delete dtls_channel; - Base::DestroyTransportChannel(base_channel); - } - - bool GetSslRole(rtc::SSLRole* ssl_role) const override { - ASSERT(ssl_role != NULL); - *ssl_role = secure_role_; - return true; - } - - private: - bool ApplyNegotiatedTransportDescription(TransportChannelImpl* channel, - std::string* error_desc) override { - // Set ssl role. Role must be set before fingerprint is applied, which - // initiates DTLS setup. - if (!channel->SetSslRole(secure_role_)) { - return BadTransportDescription("Failed to set ssl role for the channel.", - error_desc); - } - // Apply remote fingerprint. - if (!channel->SetRemoteFingerprint(remote_fingerprint_->algorithm, - reinterpret_cast( - remote_fingerprint_->digest.data()), - remote_fingerprint_->digest.size())) { - return BadTransportDescription("Failed to apply remote fingerprint.", - error_desc); - } - return Base::ApplyNegotiatedTransportDescription(channel, error_desc); - } - - rtc::scoped_refptr certificate_; - rtc::SSLRole secure_role_; - rtc::SSLProtocolVersion ssl_max_version_; - std::unique_ptr remote_fingerprint_; -}; - -} // namespace cricket - -#endif // WEBRTC_P2P_BASE_DTLSTRANSPORT_H_ diff --git a/include/webrtc/p2p/base/dtlstransportchannel.h b/include/webrtc/p2p/base/dtlstransportchannel.h index c5f5546..d16d8a6 100644 --- a/include/webrtc/p2p/base/dtlstransportchannel.h +++ b/include/webrtc/p2p/base/dtlstransportchannel.h @@ -15,20 +15,25 @@ #include #include -#include "webrtc/p2p/base/transportchannelimpl.h" #include "webrtc/base/buffer.h" #include "webrtc/base/bufferqueue.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/sslstreamadapter.h" #include "webrtc/base/stream.h" +#include "webrtc/p2p/base/dtlstransportinternal.h" +#include "webrtc/p2p/base/icetransportinternal.h" + +namespace rtc { +class PacketTransportInternal; +} namespace cricket { -// A bridge between a packet-oriented/channel-type interface on +// A bridge between a packet-oriented/transport-type interface on // the bottom and a StreamInterface on the top. class StreamInterfaceChannel : public rtc::StreamInterface { public: - explicit StreamInterfaceChannel(TransportChannel* channel); + explicit StreamInterfaceChannel(IceTransportInternal* ice_transport); // Push in a packet; this gets pulled out from Read(). bool OnPacketReceived(const char* data, size_t size); @@ -46,7 +51,7 @@ class StreamInterfaceChannel : public rtc::StreamInterface { int* error) override; private: - TransportChannel* channel_; // owned by DtlsTransportChannelWrapper + IceTransportInternal* ice_transport_; // owned by DtlsTransport rtc::StreamState state_; rtc::BufferQueue packets_; @@ -59,36 +64,43 @@ class StreamInterfaceChannel : public rtc::StreamInterface { // (e.g a P2PTransportChannel) // Here's the way this works: // -// DtlsTransportChannelWrapper { +// DtlsTransport { // SSLStreamAdapter* dtls_ { // StreamInterfaceChannel downward_ { -// TransportChannelImpl* channel_; +// IceTransportInternal* ice_transport_; // } // } // } // -// - Data which comes into DtlsTransportChannelWrapper from the underlying -// channel_ via OnReadPacket() is checked for whether it is DTLS -// or not, and if it is, is passed to DtlsTransportChannelWrapper:: -// HandleDtlsPacket, which pushes it into to downward_. -// dtls_ is listening for events on downward_, so it immediately calls -// downward_->Read(). +// - Data which comes into DtlsTransport from the underlying +// ice_transport_ via OnReadPacket() is checked for whether it is DTLS +// or not, and if it is, is passed to DtlsTransport::HandleDtlsPacket, +// which pushes it into to downward_. dtls_ is listening for events on +// downward_, so it immediately calls downward_->Read(). // -// - Data written to DtlsTransportChannelWrapper is passed either to -// downward_ or directly to channel_, depending on whether DTLS is -// negotiated and whether the flags include PF_SRTP_BYPASS +// - Data written to DtlsTransport is passed either to downward_ or directly +// to ice_transport_, depending on whether DTLS is negotiated and whether +// the flags include PF_SRTP_BYPASS // -// - The SSLStreamAdapter writes to downward_->Write() -// which translates it into packet writes on channel_. -class DtlsTransportChannelWrapper : public TransportChannelImpl { +// - The SSLStreamAdapter writes to downward_->Write() which translates it +// into packet writes on ice_transport_. +class DtlsTransport : public DtlsTransportInternal { public: - // The parameters here are: - // channel -- the TransportChannel we are wrapping - explicit DtlsTransportChannelWrapper(TransportChannelImpl* channel); - ~DtlsTransportChannelWrapper() override; + // The parameters here is: + // ice_transport -- the ice transport we are wrapping + explicit DtlsTransport(IceTransportInternal* ice_transport); + ~DtlsTransport() override; + + DtlsTransportState dtls_state() const override { return dtls_state_; } + + const std::string& transport_name() const override { return transport_name_; } + + int component() const override { return component_; } + + // Returns false if no local certificate was set, or if the peer doesn't + // support DTLS. + bool IsDtlsActive() const override { return dtls_active_; } - void SetIceRole(IceRole role) override { channel_->SetIceRole(role); } - IceRole GetIceRole() const override { return channel_->GetIceRole(); } bool SetLocalCertificate( const rtc::scoped_refptr& certificate) override; rtc::scoped_refptr GetLocalCertificate() const override; @@ -97,9 +109,6 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { const uint8_t* digest, size_t digest_len) override; - // Returns false if no local certificate was set, or if the peer doesn't - // support DTLS. - bool IsDtlsActive() const override { return dtls_active_; } // Called to send a packet (via DTLS, if turned on). int SendPacket(const char* data, @@ -107,18 +116,9 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { const rtc::PacketOptions& options, int flags) override; - // TransportChannel calls that we forward to the wrapped transport. - int SetOption(rtc::Socket::Option opt, int value) override { - return channel_->SetOption(opt, value); - } bool GetOption(rtc::Socket::Option opt, int* value) override { - return channel_->GetOption(opt, value); + return ice_transport_->GetOption(opt, value); } - int GetError() override { return channel_->GetError(); } - bool GetStats(ConnectionInfos* infos) override { - return channel_->GetStats(infos); - } - const std::string SessionId() const override { return channel_->SessionId(); } virtual bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version); @@ -140,9 +140,9 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { // use by the remote peer, for use in external identity verification. std::unique_ptr GetRemoteSSLCertificate() const override; - // Once DTLS has established (i.e., this channel is writable), this method - // extracts the keys negotiated during the DTLS handshake, for use in external - // encryption. DTLS-SRTP uses this to extract the needed SRTP keys. + // Once DTLS has established (i.e., this ice_transport is writable), this + // method extracts the keys negotiated during the DTLS handshake, for use in + // external encryption. DTLS-SRTP uses this to extract the needed SRTP keys. // See the SSLStreamAdapter documentation for info on the specific parameters. bool ExportKeyingMaterial(const std::string& label, const uint8_t* context, @@ -157,78 +157,72 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { : false; } - // TransportChannelImpl calls. - TransportChannelState GetState() const override { - return channel_->GetState(); - } - void SetIceTiebreaker(uint64_t tiebreaker) override { - channel_->SetIceTiebreaker(tiebreaker); - } - void SetIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - channel_->SetIceCredentials(ice_ufrag, ice_pwd); - } - void SetRemoteIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - channel_->SetRemoteIceCredentials(ice_ufrag, ice_pwd); - } - void SetRemoteIceMode(IceMode mode) override { - channel_->SetRemoteIceMode(mode); - } + IceTransportInternal* ice_transport() override { return ice_transport_; } - void Connect() override; + // For informational purposes. Tells if the DTLS handshake has finished. + // This may be true even if writable() is false, if the remote fingerprint + // has not yet been verified. + bool IsDtlsConnected(); - void MaybeStartGathering() override { channel_->MaybeStartGathering(); } + bool receiving() const override { return receiving_; } - IceGatheringState gathering_state() const override { - return channel_->gathering_state(); - } + bool writable() const override { return writable_; } - void AddRemoteCandidate(const Candidate& candidate) override { - channel_->AddRemoteCandidate(candidate); - } - void RemoveRemoteCandidate(const Candidate& candidate) override { - channel_->RemoveRemoteCandidate(candidate); + int GetError() override { return ice_transport_->GetError(); } + + int SetOption(rtc::Socket::Option opt, int value) override { + return ice_transport_->SetOption(opt, value); } - void SetIceConfig(const IceConfig& config) override { - channel_->SetIceConfig(config); + bool SetSrtpCiphers(const std::vector& ciphers) override { + std::vector crypto_suites; + for (const auto cipher : ciphers) { + crypto_suites.push_back(rtc::SrtpCryptoSuiteFromName(cipher)); + } + return SetSrtpCryptoSuites(crypto_suites); } - // Needed by DtlsTransport. - TransportChannelImpl* channel() { return channel_; } + std::string ToString() const { + const char RECEIVING_ABBREV[2] = {'_', 'R'}; + const char WRITABLE_ABBREV[2] = {'_', 'W'}; + std::stringstream ss; + ss << "DtlsTransport[" << transport_name_ << "|" << component_ << "|" + << RECEIVING_ABBREV[receiving()] << WRITABLE_ABBREV[writable()] << "]"; + return ss.str(); + } private: - void OnReadableState(TransportChannel* channel); - void OnWritableState(TransportChannel* channel); - void OnReadPacket(TransportChannel* channel, const char* data, size_t size, - const rtc::PacketTime& packet_time, int flags); - void OnSentPacket(TransportChannel* channel, + void OnWritableState(rtc::PacketTransportInternal* transport); + void OnReadPacket(rtc::PacketTransportInternal* transport, + const char* data, + size_t size, + const rtc::PacketTime& packet_time, + int flags); + void OnSentPacket(rtc::PacketTransportInternal* transport, const rtc::SentPacket& sent_packet); - void OnReadyToSend(TransportChannel* channel); - void OnReceivingState(TransportChannel* channel); + void OnReadyToSend(rtc::PacketTransportInternal* transport); + void OnReceivingState(rtc::PacketTransportInternal* transport); void OnDtlsEvent(rtc::StreamInterface* stream_, int sig, int err); bool SetupDtls(); - bool MaybeStartDtls(); + void MaybeStartDtls(); bool HandleDtlsPacket(const char* data, size_t size); - void OnGatheringState(TransportChannelImpl* channel); - void OnCandidateGathered(TransportChannelImpl* channel, const Candidate& c); - void OnCandidatesRemoved(TransportChannelImpl* channel, - const Candidates& candidates); - void OnRoleConflict(TransportChannelImpl* channel); - void OnRouteChange(TransportChannel* channel, const Candidate& candidate); - void OnSelectedCandidatePairChanged( - TransportChannel* channel, - CandidatePairInterface* selected_candidate_pair, - int last_sent_packet_id); - void OnConnectionRemoved(TransportChannelImpl* channel); - void Reconnect(); - - rtc::Thread* worker_thread_; // Everything should occur on this thread. - // Underlying channel, not owned by this class. - TransportChannelImpl* const channel_; + void OnDtlsHandshakeError(rtc::SSLHandshakeError error); + void ConfigureHandshakeTimeout(); + + void set_receiving(bool receiving); + void set_writable(bool writable); + // Sets the DTLS state, signaling if necessary. + void set_dtls_state(DtlsTransportState state); + + std::string transport_name_; + int component_; + DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW; + rtc::Thread* network_thread_; // Everything should occur on this thread. + // Underlying ice_transport, not owned by this class. + IceTransportInternal* const ice_transport_; std::unique_ptr dtls_; // The DTLS stream - StreamInterfaceChannel* downward_; // Wrapper for channel_, owned by dtls_. + StreamInterfaceChannel* + downward_; // Wrapper for ice_transport_, owned by dtls_. std::vector srtp_ciphers_; // SRTP ciphers to use with DTLS. bool dtls_active_ = false; rtc::scoped_refptr local_certificate_; @@ -239,11 +233,13 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { // Cached DTLS ClientHello packet that was received before we started the // DTLS handshake. This could happen if the hello was received before the - // transport channel became writable, or before a remote fingerprint was - // received. + // ice transport became writable, or before a remote fingerprint was received. rtc::Buffer cached_client_hello_; - RTC_DISALLOW_COPY_AND_ASSIGN(DtlsTransportChannelWrapper); + bool receiving_ = false; + bool writable_ = false; + + RTC_DISALLOW_COPY_AND_ASSIGN(DtlsTransport); }; } // namespace cricket diff --git a/include/webrtc/p2p/base/dtlstransportinternal.h b/include/webrtc/p2p/base/dtlstransportinternal.h new file mode 100644 index 0000000..7a1e8ad --- /dev/null +++ b/include/webrtc/p2p/base/dtlstransportinternal.h @@ -0,0 +1,113 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_DTLSTRANSPORTINTERNAL_H_ +#define WEBRTC_P2P_BASE_DTLSTRANSPORTINTERNAL_H_ + +#include +#include +#include + +#include "webrtc/base/sslstreamadapter.h" +#include "webrtc/base/stringencode.h" +#include "webrtc/p2p/base/icetransportinternal.h" +#include "webrtc/p2p/base/jseptransport.h" +#include "webrtc/p2p/base/packettransportinternal.h" + +namespace cricket { + +enum PacketFlags { + PF_NORMAL = 0x00, // A normal packet. + PF_SRTP_BYPASS = 0x01, // An encrypted SRTP packet; bypass any additional + // crypto provided by the transport (e.g. DTLS) +}; + +// DtlsTransportInternal is an internal interface that does DTLS. +// Once the public interface is supported, +// (https://www.w3.org/TR/webrtc/#rtcdtlstransport-interface) +// the DtlsTransportInterface will be split from this class. +class DtlsTransportInternal : public rtc::PacketTransportInternal { + public: + virtual ~DtlsTransportInternal() {} + + virtual DtlsTransportState dtls_state() const = 0; + + virtual const std::string& transport_name() const = 0; + + virtual int component() const = 0; + + virtual bool IsDtlsActive() const = 0; + + virtual bool GetSslRole(rtc::SSLRole* role) const = 0; + + virtual bool SetSslRole(rtc::SSLRole role) = 0; + + // Sets up the ciphers to use for DTLS-SRTP. + virtual bool SetSrtpCryptoSuites(const std::vector& ciphers) = 0; + + // Keep the original one for backward compatibility until all dependencies + // move away. TODO(zhihuang): Remove this function. + virtual bool SetSrtpCiphers(const std::vector& ciphers) = 0; + + // Finds out which DTLS-SRTP cipher was negotiated. + // TODO(zhihuang): Remove this once all dependencies implement this. + virtual bool GetSrtpCryptoSuite(int* cipher) = 0; + + // Finds out which DTLS cipher was negotiated. + // TODO(zhihuang): Remove this once all dependencies implement this. + virtual bool GetSslCipherSuite(int* cipher) = 0; + + // Gets the local RTCCertificate used for DTLS. + virtual rtc::scoped_refptr GetLocalCertificate() + const = 0; + + virtual bool SetLocalCertificate( + const rtc::scoped_refptr& certificate) = 0; + + // Gets a copy of the remote side's SSL certificate. + virtual std::unique_ptr GetRemoteSSLCertificate() + const = 0; + + // Allows key material to be extracted for external encryption. + virtual bool ExportKeyingMaterial(const std::string& label, + const uint8_t* context, + size_t context_len, + bool use_context, + uint8_t* result, + size_t result_len) = 0; + + // Set DTLS remote fingerprint. Must be after local identity set. + virtual bool SetRemoteFingerprint(const std::string& digest_alg, + const uint8_t* digest, + size_t digest_len) = 0; + + // Expose the underneath IceTransport. + virtual IceTransportInternal* ice_transport() = 0; + + sigslot::signal2 SignalDtlsState; + + // Emitted whenever the Dtls handshake failed on some transport channel. + sigslot::signal1 SignalDtlsHandshakeError; + + // Debugging description of this transport. + std::string debug_name() const override { + return transport_name() + " " + rtc::ToString(component()); + } + + protected: + DtlsTransportInternal() {} + + private: + RTC_DISALLOW_COPY_AND_ASSIGN(DtlsTransportInternal); +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_DTLSTRANSPORTINTERNAL_H_ diff --git a/include/webrtc/p2p/base/fakecandidatepair.h b/include/webrtc/p2p/base/fakecandidatepair.h new file mode 100644 index 0000000..73e6c67 --- /dev/null +++ b/include/webrtc/p2p/base/fakecandidatepair.h @@ -0,0 +1,54 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_ +#define WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_ + +#include + +#include "webrtc/p2p/base/candidate.h" +#include "webrtc/p2p/base/candidatepairinterface.h" + +namespace cricket { + +// Fake candidate pair class, which can be passed to BaseChannel for testing +// purposes. +class FakeCandidatePair : public CandidatePairInterface { + public: + FakeCandidatePair(const Candidate& local_candidate, + const Candidate& remote_candidate) + : local_candidate_(local_candidate), + remote_candidate_(remote_candidate) {} + const Candidate& local_candidate() const override { return local_candidate_; } + const Candidate& remote_candidate() const override { + return remote_candidate_; + } + + static std::unique_ptr Create( + const rtc::SocketAddress& local_address, + int16_t local_network_id, + const rtc::SocketAddress& remote_address, + int16_t remote_network_id) { + Candidate local_candidate(0, "udp", local_address, 0u, "", "", "local", 0, + "foundation", local_network_id, 0); + Candidate remote_candidate(0, "udp", remote_address, 0u, "", "", "local", 0, + "foundation", remote_network_id, 0); + return std::unique_ptr( + new FakeCandidatePair(local_candidate, remote_candidate)); + } + + private: + Candidate local_candidate_; + Candidate remote_candidate_; +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_FAKECANDIDATEPAIR_H_ diff --git a/include/webrtc/p2p/base/fakedtlstransport.h b/include/webrtc/p2p/base/fakedtlstransport.h new file mode 100644 index 0000000..da3537f --- /dev/null +++ b/include/webrtc/p2p/base/fakedtlstransport.h @@ -0,0 +1,270 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ +#define WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ + +#include +#include +#include + +#include "webrtc/base/fakesslidentity.h" +#include "webrtc/p2p/base/dtlstransportinternal.h" +#include "webrtc/p2p/base/fakeicetransport.h" + +namespace cricket { + +// Fake DTLS transport which is implemented by wrapping a fake ICE transport. +// Doesn't interact directly with fake ICE transport for anything other than +// sending packets. +class FakeDtlsTransport : public DtlsTransportInternal { + public: + explicit FakeDtlsTransport(FakeIceTransport* ice_transport) + : ice_transport_(ice_transport), + transport_name_(ice_transport->transport_name()), + component_(ice_transport->component()), + dtls_fingerprint_("", nullptr, 0) { + ice_transport_->SignalReadPacket.connect( + this, &FakeDtlsTransport::OnIceTransportReadPacket); + } + + // If this constructor is called, a new fake ICE transport will be created, + // and this FakeDtlsTransport will take the ownership. + explicit FakeDtlsTransport(const std::string& name, int component) + : owned_ice_transport_(new FakeIceTransport(name, component)), + transport_name_(owned_ice_transport_->transport_name()), + component_(owned_ice_transport_->component()), + dtls_fingerprint_("", nullptr, 0) { + ice_transport_ = owned_ice_transport_.get(); + ice_transport_->SignalReadPacket.connect( + this, &FakeDtlsTransport::OnIceTransportReadPacket); + } + + ~FakeDtlsTransport() override { + if (dest_ && dest_->dest_ == this) { + dest_->dest_ = nullptr; + } + } + + // Get inner fake ICE transport. + FakeIceTransport* fake_ice_transport() { return ice_transport_; } + + // If async, will send packets by "Post"-ing to message queue instead of + // synchronously "Send"-ing. + void SetAsync(bool async) { ice_transport_->SetAsync(async); } + void SetAsyncDelay(int delay_ms) { ice_transport_->SetAsyncDelay(delay_ms); } + + // SetWritable, SetReceiving and SetDestination are the main methods that can + // be used for testing, to simulate connectivity or lack thereof. + void SetWritable(bool writable) { + ice_transport_->SetWritable(writable); + set_writable(writable); + } + void SetReceiving(bool receiving) { + ice_transport_->SetReceiving(receiving); + set_receiving(receiving); + } + + // Simulates the two DTLS transports connecting to each other. + // If |asymmetric| is true this method only affects this FakeDtlsTransport. + // If false, it affects |dest| as well. + void SetDestination(FakeDtlsTransport* dest, bool asymmetric = false) { + if (dest == dest_) { + return; + } + RTC_DCHECK(!dest || !dest_) + << "Changing fake destination from one to another is not supported."; + if (dest && !dest_) { + // This simulates the DTLS handshake. + dest_ = dest; + if (local_cert_ && dest_->local_cert_) { + do_dtls_ = true; + NegotiateSrtpCiphers(); + } + SetWritable(true); + if (!asymmetric) { + dest->SetDestination(this, true); + } + ice_transport_->SetDestination( + static_cast(dest->ice_transport()), asymmetric); + } else { + // Simulates loss of connectivity, by asymmetrically forgetting dest_. + dest_ = nullptr; + SetWritable(false); + ice_transport_->SetDestination(nullptr, asymmetric); + } + } + + // Fake DtlsTransportInternal implementation. + DtlsTransportState dtls_state() const override { return dtls_state_; } + const std::string& transport_name() const override { return transport_name_; } + int component() const override { return component_; } + const rtc::SSLFingerprint& dtls_fingerprint() const { + return dtls_fingerprint_; + } + bool SetRemoteFingerprint(const std::string& alg, + const uint8_t* digest, + size_t digest_len) override { + dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len); + return true; + } + bool SetSslRole(rtc::SSLRole role) override { + ssl_role_ = role; + return true; + } + bool GetSslRole(rtc::SSLRole* role) const override { + *role = ssl_role_; + return true; + } + bool SetLocalCertificate( + const rtc::scoped_refptr& certificate) override { + local_cert_ = certificate; + return true; + } + void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) { + remote_cert_ = cert; + } + bool IsDtlsActive() const override { return do_dtls_; } + bool SetSrtpCryptoSuites(const std::vector& ciphers) override { + srtp_ciphers_ = ciphers; + return true; + } + bool GetSrtpCryptoSuite(int* crypto_suite) override { + if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) { + *crypto_suite = chosen_crypto_suite_; + return true; + } + return false; + } + bool GetSslCipherSuite(int* cipher_suite) override { return false; } + rtc::scoped_refptr GetLocalCertificate() const override { + return local_cert_; + } + std::unique_ptr GetRemoteSSLCertificate() + const override { + return remote_cert_ ? std::unique_ptr( + remote_cert_->GetReference()) + : nullptr; + } + bool ExportKeyingMaterial(const std::string& label, + const uint8_t* context, + size_t context_len, + bool use_context, + uint8_t* result, + size_t result_len) override { + if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) { + memset(result, 0xff, result_len); + return true; + } + + return false; + } + void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) { + ssl_max_version_ = version; + } + rtc::SSLProtocolVersion ssl_max_protocol_version() const { + return ssl_max_version_; + } + bool SetSrtpCiphers(const std::vector& ciphers) override { + std::vector crypto_suites; + for (const auto cipher : ciphers) { + crypto_suites.push_back(rtc::SrtpCryptoSuiteFromName(cipher)); + } + return SetSrtpCryptoSuites(crypto_suites); + } + + IceTransportInternal* ice_transport() override { return ice_transport_; } + + // PacketTransportInternal implementation, which passes through to fake ICE + // transport for sending actual packets. + bool writable() const override { return writable_; } + bool receiving() const override { return receiving_; } + int SendPacket(const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags) override { + // We expect only SRTP packets to be sent through this interface. + if (flags != PF_SRTP_BYPASS && flags != 0) { + return -1; + } + return ice_transport_->SendPacket(data, len, options, flags); + } + int SetOption(rtc::Socket::Option opt, int value) override { + return ice_transport_->SetOption(opt, value); + } + bool GetOption(rtc::Socket::Option opt, int* value) override { + return ice_transport_->GetOption(opt, value); + } + int GetError() override { return ice_transport_->GetError(); } + + private: + void OnIceTransportReadPacket(PacketTransportInternal* ice_, + const char* data, + size_t len, + const rtc::PacketTime& time, + int flags) { + SignalReadPacket(this, data, len, time, flags); + } + + void NegotiateSrtpCiphers() { + for (std::vector::const_iterator it1 = srtp_ciphers_.begin(); + it1 != srtp_ciphers_.end(); ++it1) { + for (std::vector::const_iterator it2 = dest_->srtp_ciphers_.begin(); + it2 != dest_->srtp_ciphers_.end(); ++it2) { + if (*it1 == *it2) { + chosen_crypto_suite_ = *it1; + return; + } + } + } + } + + void set_receiving(bool receiving) { + if (receiving_ == receiving) { + return; + } + receiving_ = receiving; + SignalReceivingState(this); + } + + void set_writable(bool writable) { + if (writable_ == writable) { + return; + } + writable_ = writable; + if (writable_) { + SignalReadyToSend(this); + } + SignalWritableState(this); + } + + FakeIceTransport* ice_transport_; + std::unique_ptr owned_ice_transport_; + std::string transport_name_; + int component_; + FakeDtlsTransport* dest_ = nullptr; + rtc::scoped_refptr local_cert_; + rtc::FakeSSLCertificate* remote_cert_ = nullptr; + bool do_dtls_ = false; + std::vector srtp_ciphers_; + int chosen_crypto_suite_ = rtc::SRTP_INVALID_CRYPTO_SUITE; + rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; + rtc::SSLFingerprint dtls_fingerprint_; + rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT; + + DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW; + + bool receiving_ = false; + bool writable_ = false; +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_FAKEDTLSTRANSPORT_H_ diff --git a/include/webrtc/p2p/base/fakeicetransport.h b/include/webrtc/p2p/base/fakeicetransport.h new file mode 100644 index 0000000..2b0662f --- /dev/null +++ b/include/webrtc/p2p/base/fakeicetransport.h @@ -0,0 +1,240 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_ +#define WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_ + +#include + +#include "webrtc/base/asyncinvoker.h" +#include "webrtc/base/copyonwritebuffer.h" +#include "webrtc/p2p/base/icetransportinternal.h" + +namespace cricket { + +class FakeIceTransport : public IceTransportInternal { + public: + explicit FakeIceTransport(const std::string& name, int component) + : name_(name), component_(component) {} + ~FakeIceTransport() override { + if (dest_ && dest_->dest_ == this) { + dest_->dest_ = nullptr; + } + } + + // If async, will send packets by "Post"-ing to message queue instead of + // synchronously "Send"-ing. + void SetAsync(bool async) { async_ = async; } + void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; } + + // SetWritable, SetReceiving and SetDestination are the main methods that can + // be used for testing, to simulate connectivity or lack thereof. + void SetWritable(bool writable) { set_writable(writable); } + void SetReceiving(bool receiving) { set_receiving(receiving); } + + // Simulates the two transports connecting to each other. + // If |asymmetric| is true this method only affects this FakeIceTransport. + // If false, it affects |dest| as well. + void SetDestination(FakeIceTransport* dest, bool asymmetric = false) { + if (dest == dest_) { + return; + } + RTC_DCHECK(!dest || !dest_) + << "Changing fake destination from one to another is not supported."; + if (dest) { + // This simulates the delivery of candidates. + dest_ = dest; + set_writable(true); + if (!asymmetric) { + dest->SetDestination(this, true); + } + } else { + // Simulates loss of connectivity, by asymmetrically forgetting dest_. + dest_ = nullptr; + set_writable(false); + } + } + + void SetConnectionCount(size_t connection_count) { + size_t old_connection_count = connection_count_; + connection_count_ = connection_count; + if (connection_count) { + had_connection_ = true; + } + // In this fake transport channel, |connection_count_| determines the + // transport state. + if (connection_count_ < old_connection_count) { + SignalStateChanged(this); + } + } + + void SetCandidatesGatheringComplete() { + if (gathering_state_ != kIceGatheringComplete) { + gathering_state_ = kIceGatheringComplete; + SignalGatheringState(this); + } + } + + // Convenience functions for accessing ICE config and other things. + int receiving_timeout() const { return ice_config_.receiving_timeout; } + bool gather_continually() const { return ice_config_.gather_continually(); } + const Candidates& remote_candidates() const { return remote_candidates_; } + + // Fake IceTransportInternal implementation. + const std::string& transport_name() const override { return name_; } + int component() const override { return component_; } + uint64_t IceTiebreaker() const { return tiebreaker_; } + IceMode remote_ice_mode() const { return remote_ice_mode_; } + const std::string& ice_ufrag() const { return ice_ufrag_; } + const std::string& ice_pwd() const { return ice_pwd_; } + const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; } + const std::string& remote_ice_pwd() const { return remote_ice_pwd_; } + + IceTransportState GetState() const override { + if (connection_count_ == 0) { + return had_connection_ ? IceTransportState::STATE_FAILED + : IceTransportState::STATE_INIT; + } + + if (connection_count_ == 1) { + return IceTransportState::STATE_COMPLETED; + } + + return IceTransportState::STATE_CONNECTING; + } + + void SetIceRole(IceRole role) override { role_ = role; } + IceRole GetIceRole() const override { return role_; } + void SetIceTiebreaker(uint64_t tiebreaker) override { + tiebreaker_ = tiebreaker; + } + void SetIceParameters(const IceParameters& ice_params) override { + ice_ufrag_ = ice_params.ufrag; + ice_pwd_ = ice_params.pwd; + } + void SetRemoteIceParameters(const IceParameters& params) override { + remote_ice_ufrag_ = params.ufrag; + remote_ice_pwd_ = params.pwd; + } + + void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; } + + void MaybeStartGathering() override { + if (gathering_state_ == kIceGatheringNew) { + gathering_state_ = kIceGatheringGathering; + SignalGatheringState(this); + } + } + + IceGatheringState gathering_state() const override { + return gathering_state_; + } + + void SetIceConfig(const IceConfig& config) override { ice_config_ = config; } + + void AddRemoteCandidate(const Candidate& candidate) override { + remote_candidates_.push_back(candidate); + } + void RemoveRemoteCandidate(const Candidate& candidate) override {} + + bool GetStats(ConnectionInfos* infos) override { + ConnectionInfo info; + infos->clear(); + infos->push_back(info); + return true; + } + + rtc::Optional GetRttEstimate() override { + return rtc::Optional(); + } + + void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override { + } + + // Fake PacketTransportInternal implementation. + bool writable() const override { return writable_; } + bool receiving() const override { return receiving_; } + int SendPacket(const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags) override { + if (!dest_) { + return -1; + } + rtc::CopyOnWriteBuffer packet(data, len); + if (async_) { + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, rtc::Thread::Current(), + rtc::Bind(&FakeIceTransport::SendPacketInternal, this, packet), + async_delay_ms_); + } else { + SendPacketInternal(packet); + } + rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis()); + SignalSentPacket(this, sent_packet); + return static_cast(len); + } + int SetOption(rtc::Socket::Option opt, int value) override { return true; } + bool GetOption(rtc::Socket::Option opt, int* value) override { return true; } + int GetError() override { return 0; } + + private: + void set_writable(bool writable) { + if (writable_ == writable) { + return; + } + LOG(INFO) << "set_writable from:" << writable_ << " to " << writable; + writable_ = writable; + if (writable_) { + SignalReadyToSend(this); + } + SignalWritableState(this); + } + + void set_receiving(bool receiving) { + if (receiving_ == receiving) { + return; + } + receiving_ = receiving; + SignalReceivingState(this); + } + + void SendPacketInternal(const rtc::CopyOnWriteBuffer& packet) { + if (dest_) { + dest_->SignalReadPacket(dest_, packet.data(), packet.size(), + rtc::CreatePacketTime(0), 0); + } + } + + rtc::AsyncInvoker invoker_; + std::string name_; + int component_; + FakeIceTransport* dest_ = nullptr; + bool async_ = false; + int async_delay_ms_ = 0; + Candidates remote_candidates_; + IceConfig ice_config_; + IceRole role_ = ICEROLE_UNKNOWN; + uint64_t tiebreaker_ = 0; + std::string ice_ufrag_; + std::string ice_pwd_; + std::string remote_ice_ufrag_; + std::string remote_ice_pwd_; + IceMode remote_ice_mode_ = ICEMODE_FULL; + size_t connection_count_ = 0; + IceGatheringState gathering_state_ = kIceGatheringNew; + bool had_connection_ = false; + bool writable_ = false; + bool receiving_ = false; +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_FAKEICETRANSPORT_H_ diff --git a/include/webrtc/p2p/base/fakepackettransport.h b/include/webrtc/p2p/base/fakepackettransport.h new file mode 100644 index 0000000..7e2f084 --- /dev/null +++ b/include/webrtc/p2p/base/fakepackettransport.h @@ -0,0 +1,131 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_ +#define WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_ + +#include + +#include "webrtc/api/ortc/packettransportinterface.h" +#include "webrtc/base/asyncinvoker.h" +#include "webrtc/base/copyonwritebuffer.h" +#include "webrtc/p2p/base/packettransportinternal.h" + +namespace rtc { + +// Used to simulate a packet-based transport. +class FakePacketTransport : public PacketTransportInternal, + public webrtc::PacketTransportInterface { + public: + explicit FakePacketTransport(const std::string& debug_name) + : debug_name_(debug_name) {} + ~FakePacketTransport() override { + if (dest_ && dest_->dest_ == this) { + dest_->dest_ = nullptr; + } + } + + // If async, will send packets by "Post"-ing to message queue instead of + // synchronously "Send"-ing. + void SetAsync(bool async) { async_ = async; } + void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; } + + // SetWritable, SetReceiving and SetDestination are the main methods that can + // be used for testing, to simulate connectivity or lack thereof. + void SetWritable(bool writable) { set_writable(writable); } + void SetReceiving(bool receiving) { set_receiving(receiving); } + + // Simulates the two transports connecting to each other. + // If |asymmetric| is true this method only affects this FakePacketTransport. + // If false, it affects |dest| as well. + void SetDestination(FakePacketTransport* dest, bool asymmetric) { + if (dest) { + dest_ = dest; + set_writable(true); + if (!asymmetric) { + dest->SetDestination(this, true); + } + } else { + // Simulates loss of connectivity, by asymmetrically forgetting dest_. + dest_ = nullptr; + set_writable(false); + } + } + + // Fake PacketTransportInternal implementation. + std::string debug_name() const override { return debug_name_; } + bool writable() const override { return writable_; } + bool receiving() const override { return receiving_; } + int SendPacket(const char* data, + size_t len, + const PacketOptions& options, + int flags) override { + if (!dest_) { + return -1; + } + CopyOnWriteBuffer packet(data, len); + if (async_) { + invoker_.AsyncInvokeDelayed( + RTC_FROM_HERE, Thread::Current(), + Bind(&FakePacketTransport::SendPacketInternal, this, packet), + async_delay_ms_); + } else { + SendPacketInternal(packet); + } + SentPacket sent_packet(options.packet_id, TimeMillis()); + SignalSentPacket(this, sent_packet); + return static_cast(len); + } + int SetOption(Socket::Option opt, int value) override { return true; } + bool GetOption(Socket::Option opt, int* value) override { return true; } + int GetError() override { return 0; } + + protected: + PacketTransportInternal* GetInternal() override { return this; } + + private: + void set_writable(bool writable) { + if (writable_ == writable) { + return; + } + writable_ = writable; + if (writable_) { + SignalReadyToSend(this); + } + SignalWritableState(this); + } + + void set_receiving(bool receiving) { + if (receiving_ == receiving) { + return; + } + receiving_ = receiving; + SignalReceivingState(this); + } + + void SendPacketInternal(const CopyOnWriteBuffer& packet) { + if (dest_) { + dest_->SignalReadPacket(dest_, packet.data(), packet.size(), + CreatePacketTime(0), 0); + } + } + + AsyncInvoker invoker_; + std::string debug_name_; + FakePacketTransport* dest_ = nullptr; + bool async_ = false; + int async_delay_ms_ = 0; + bool writable_ = false; + bool receiving_ = false; +}; + +} // namespace rtc + +#endif // WEBRTC_P2P_BASE_FAKEPACKETTRANSPORT_H_ diff --git a/include/webrtc/p2p/base/fakeportallocator.h b/include/webrtc/p2p/base/fakeportallocator.h index 6730d1e..a1dbbf8 100644 --- a/include/webrtc/p2p/base/fakeportallocator.h +++ b/include/webrtc/p2p/base/fakeportallocator.h @@ -15,6 +15,7 @@ #include #include +#include "webrtc/base/nethelpers.h" #include "webrtc/p2p/base/basicpacketsocketfactory.h" #include "webrtc/p2p/base/portallocator.h" #include "webrtc/p2p/base/udpport.h" @@ -82,10 +83,13 @@ class TestUDPPort : public UDPPort { bool sent_binding_response_ = false; }; +// A FakePortAllocatorSession can be used with either a real or fake socket +// factory. It gathers a single loopback port, using IPv6 if available and +// not disabled. class FakePortAllocatorSession : public PortAllocatorSession { public: FakePortAllocatorSession(PortAllocator* allocator, - rtc::Thread* worker_thread, + rtc::Thread* network_thread, rtc::PacketSocketFactory* factory, const std::string& content_name, int component, @@ -96,23 +100,39 @@ class FakePortAllocatorSession : public PortAllocatorSession { ice_ufrag, ice_pwd, allocator->flags()), - worker_thread_(worker_thread), + network_thread_(network_thread), factory_(factory), - network_("network", "unittest", rtc::IPAddress(INADDR_LOOPBACK), 8), + ipv4_network_("network", + "unittest", + rtc::IPAddress(INADDR_LOOPBACK), + 32), + ipv6_network_("network", + "unittest", + rtc::IPAddress(in6addr_loopback), + 64), port_(), - running_(false), port_config_count_(0), stun_servers_(allocator->stun_servers()), - turn_servers_(allocator->turn_servers()), - candidate_filter_(allocator->candidate_filter()) { - network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK)); + turn_servers_(allocator->turn_servers()) { + ipv4_network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK)); + ipv6_network_.AddIP(rtc::IPAddress(in6addr_loopback)); + } + + void SetCandidateFilter(uint32_t filter) override { + candidate_filter_ = filter; } void StartGettingPorts() override { if (!port_) { - port_.reset(TestUDPPort::Create(worker_thread_, factory_, &network_, - network_.GetBestIP(), 0, 0, username(), + rtc::Network& network = + (rtc::HasIPv6Enabled() && (flags() & PORTALLOCATOR_ENABLE_IPV6)) + ? ipv6_network_ + : ipv4_network_; + port_.reset(TestUDPPort::Create(network_thread_, factory_, &network, + network.GetBestIP(), 0, 0, username(), password(), std::string(), false)); + port_->SignalDestroyed.connect( + this, &FakePortAllocatorSession::OnPortDestroyed); AddPort(port_.get()); } ++port_config_count_; @@ -122,12 +142,14 @@ class FakePortAllocatorSession : public PortAllocatorSession { void StopGettingPorts() override { running_ = false; } bool IsGettingPorts() override { return running_; } void ClearGettingPorts() override {} + std::vector ReadyPorts() const override { return ready_ports_; } std::vector ReadyCandidates() const override { return candidates_; } + void PruneAllPorts() override { port_->Prune(); } bool CandidatesAllocationDone() const override { return allocation_done_; } int port_config_count() { return port_config_count_; } @@ -140,6 +162,18 @@ class FakePortAllocatorSession : public PortAllocatorSession { uint32_t candidate_filter() const { return candidate_filter_; } + int transport_info_update_count() const { + return transport_info_update_count_; + } + + protected: + void UpdateIceParametersInternal() override { + // Since this class is a fake and this method only is overridden for tests, + // we don't need to actually update the transport info. + ++transport_info_update_count_; + } + + private: void AddPort(cricket::Port* port) { port->set_component(component()); port->set_generation(generation()); @@ -148,6 +182,7 @@ class FakePortAllocatorSession : public PortAllocatorSession { port->PrepareAddress(); ready_ports_.push_back(port); SignalPortReady(this, port); + port->KeepAliveUntilPruned(); } void OnPortComplete(cricket::Port* port) { const std::vector& candidates = port->Candidates(); @@ -157,45 +192,44 @@ class FakePortAllocatorSession : public PortAllocatorSession { allocation_done_ = true; SignalCandidatesAllocationDone(this); } - - int transport_info_update_count() const { - return transport_info_update_count_; - } - - protected: - void UpdateIceParametersInternal() override { - // Since this class is a fake and this method only is overridden for tests, - // we don't need to actually update the transport info. - ++transport_info_update_count_; + void OnPortDestroyed(cricket::PortInterface* port) { + // Don't want to double-delete port if it deletes itself. + port_.release(); } - private: - rtc::Thread* worker_thread_; + rtc::Thread* network_thread_; rtc::PacketSocketFactory* factory_; - rtc::Network network_; + rtc::Network ipv4_network_; + rtc::Network ipv6_network_; std::unique_ptr port_; - bool running_; int port_config_count_; std::vector candidates_; std::vector ready_ports_; bool allocation_done_ = false; ServerAddresses stun_servers_; std::vector turn_servers_; - uint32_t candidate_filter_; + uint32_t candidate_filter_ = CF_ALL; int transport_info_update_count_ = 0; + bool running_ = false; }; class FakePortAllocator : public cricket::PortAllocator { public: - FakePortAllocator(rtc::Thread* worker_thread, + FakePortAllocator(rtc::Thread* network_thread, rtc::PacketSocketFactory* factory) - : worker_thread_(worker_thread), factory_(factory) { + : network_thread_(network_thread), factory_(factory) { if (factory_ == NULL) { - owned_factory_.reset(new rtc::BasicPacketSocketFactory(worker_thread_)); + owned_factory_.reset(new rtc::BasicPacketSocketFactory(network_thread_)); factory_ = owned_factory_.get(); } } + void Initialize() override { + // Port allocator should be initialized on the network thread. + RTC_CHECK(network_thread_->IsCurrent()); + initialized_ = true; + } + void SetNetworkIgnoreMask(int network_ignore_mask) override {} cricket::PortAllocatorSession* CreateSessionInternal( @@ -203,15 +237,18 @@ class FakePortAllocator : public cricket::PortAllocator { int component, const std::string& ice_ufrag, const std::string& ice_pwd) override { - return new FakePortAllocatorSession(this, worker_thread_, factory_, + return new FakePortAllocatorSession(this, network_thread_, factory_, content_name, component, ice_ufrag, ice_pwd); } + bool initialized() const { return initialized_; } + private: - rtc::Thread* worker_thread_; + rtc::Thread* network_thread_; rtc::PacketSocketFactory* factory_; std::unique_ptr owned_factory_; + bool initialized_ = false; }; } // namespace cricket diff --git a/include/webrtc/p2p/base/faketransportcontroller.h b/include/webrtc/p2p/base/faketransportcontroller.h index 321537d..35af390 100644 --- a/include/webrtc/p2p/base/faketransportcontroller.h +++ b/include/webrtc/p2p/base/faketransportcontroller.h @@ -11,477 +11,22 @@ #ifndef WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_ #define WEBRTC_P2P_BASE_FAKETRANSPORTCONTROLLER_H_ -#include #include #include #include -#include "webrtc/p2p/base/candidatepairinterface.h" -#include "webrtc/p2p/base/transport.h" -#include "webrtc/p2p/base/transportchannel.h" -#include "webrtc/p2p/base/transportcontroller.h" -#include "webrtc/p2p/base/transportchannelimpl.h" #include "webrtc/base/bind.h" -#include "webrtc/base/buffer.h" -#include "webrtc/base/fakesslidentity.h" -#include "webrtc/base/messagequeue.h" -#include "webrtc/base/sigslot.h" #include "webrtc/base/sslfingerprint.h" #include "webrtc/base/thread.h" +#include "webrtc/p2p/base/fakedtlstransport.h" +#include "webrtc/p2p/base/fakeicetransport.h" +#include "webrtc/p2p/base/transportcontroller.h" namespace cricket { -class FakeTransport; - -namespace { -struct PacketMessageData : public rtc::MessageData { - PacketMessageData(const char* data, size_t len) : packet(data, len) {} - rtc::Buffer packet; -}; -} // namespace - -// Fake transport channel class, which can be passed to anything that needs a -// transport channel. Can be informed of another FakeTransportChannel via -// SetDestination. -// TODO(hbos): Move implementation to .cc file, this and other classes in file. -class FakeTransportChannel : public TransportChannelImpl, - public rtc::MessageHandler { - public: - explicit FakeTransportChannel(const std::string& name, int component) - : TransportChannelImpl(name, component), - dtls_fingerprint_("", nullptr, 0) {} - ~FakeTransportChannel() { Reset(); } - - uint64_t IceTiebreaker() const { return tiebreaker_; } - IceMode remote_ice_mode() const { return remote_ice_mode_; } - const std::string& ice_ufrag() const { return ice_ufrag_; } - const std::string& ice_pwd() const { return ice_pwd_; } - const std::string& remote_ice_ufrag() const { return remote_ice_ufrag_; } - const std::string& remote_ice_pwd() const { return remote_ice_pwd_; } - const rtc::SSLFingerprint& dtls_fingerprint() const { - return dtls_fingerprint_; - } - - // If async, will send packets by "Post"-ing to message queue instead of - // synchronously "Send"-ing. - void SetAsync(bool async) { async_ = async; } - - TransportChannelState GetState() const override { - if (connection_count_ == 0) { - return had_connection_ ? TransportChannelState::STATE_FAILED - : TransportChannelState::STATE_INIT; - } - - if (connection_count_ == 1) { - return TransportChannelState::STATE_COMPLETED; - } - - return TransportChannelState::STATE_CONNECTING; - } - - void SetIceRole(IceRole role) override { role_ = role; } - IceRole GetIceRole() const override { return role_; } - void SetIceTiebreaker(uint64_t tiebreaker) override { - tiebreaker_ = tiebreaker; - } - void SetIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - ice_ufrag_ = ice_ufrag; - ice_pwd_ = ice_pwd; - } - void SetRemoteIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - remote_ice_ufrag_ = ice_ufrag; - remote_ice_pwd_ = ice_pwd; - } - - void SetRemoteIceMode(IceMode mode) override { remote_ice_mode_ = mode; } - bool SetRemoteFingerprint(const std::string& alg, - const uint8_t* digest, - size_t digest_len) override { - dtls_fingerprint_ = rtc::SSLFingerprint(alg, digest, digest_len); - return true; - } - bool SetSslRole(rtc::SSLRole role) override { - ssl_role_ = role; - return true; - } - bool GetSslRole(rtc::SSLRole* role) const override { - *role = ssl_role_; - return true; - } - - void Connect() override { - if (state_ == STATE_INIT) { - state_ = STATE_CONNECTING; - } - } - - void MaybeStartGathering() override { - if (gathering_state_ == kIceGatheringNew) { - gathering_state_ = kIceGatheringGathering; - SignalGatheringState(this); - } - } - - IceGatheringState gathering_state() const override { - return gathering_state_; - } - - void Reset() { - if (state_ != STATE_INIT) { - state_ = STATE_INIT; - if (dest_) { - dest_->state_ = STATE_INIT; - dest_->dest_ = nullptr; - dest_ = nullptr; - } - } - } - - void SetWritable(bool writable) { set_writable(writable); } - - // Simulates the two transport channels connecting to each other. - // If |asymmetric| is true this method only affects this FakeTransportChannel. - // If false, it affects |dest| as well. - void SetDestination(FakeTransportChannel* dest, bool asymmetric = false) { - if (state_ == STATE_CONNECTING && dest) { - // This simulates the delivery of candidates. - dest_ = dest; - if (local_cert_ && dest_->local_cert_) { - do_dtls_ = true; - NegotiateSrtpCiphers(); - } - state_ = STATE_CONNECTED; - set_writable(true); - if (!asymmetric) { - dest->SetDestination(this, true); - } - } else if (state_ == STATE_CONNECTED && !dest) { - // Simulates loss of connectivity, by asymmetrically forgetting dest_. - dest_ = nullptr; - state_ = STATE_CONNECTING; - set_writable(false); - } - } - - void SetConnectionCount(size_t connection_count) { - size_t old_connection_count = connection_count_; - connection_count_ = connection_count; - if (connection_count) - had_connection_ = true; - if (connection_count_ < old_connection_count) - SignalConnectionRemoved(this); - } - - void SetCandidatesGatheringComplete() { - if (gathering_state_ != kIceGatheringComplete) { - gathering_state_ = kIceGatheringComplete; - SignalGatheringState(this); - } - } - - void SetReceiving(bool receiving) { set_receiving(receiving); } - - void SetIceConfig(const IceConfig& config) override { - receiving_timeout_ = config.receiving_timeout; - gather_continually_ = config.gather_continually; - } - - int receiving_timeout() const { return receiving_timeout_; } - bool gather_continually() const { return gather_continually_; } - - int SendPacket(const char* data, - size_t len, - const rtc::PacketOptions& options, - int flags) override { - if (state_ != STATE_CONNECTED) { - return -1; - } - - if (flags != PF_SRTP_BYPASS && flags != 0) { - return -1; - } - - PacketMessageData* packet = new PacketMessageData(data, len); - if (async_) { - rtc::Thread::Current()->Post(this, 0, packet); - } else { - rtc::Thread::Current()->Send(this, 0, packet); - } - rtc::SentPacket sent_packet(options.packet_id, rtc::TimeMillis()); - SignalSentPacket(this, sent_packet); - return static_cast(len); - } - int SetOption(rtc::Socket::Option opt, int value) override { return true; } - bool GetOption(rtc::Socket::Option opt, int* value) override { return true; } - int GetError() override { return 0; } - - void AddRemoteCandidate(const Candidate& candidate) override { - remote_candidates_.push_back(candidate); - } - - void RemoveRemoteCandidate(const Candidate& candidate) override {} - - const Candidates& remote_candidates() const { return remote_candidates_; } - - void OnMessage(rtc::Message* msg) override { - PacketMessageData* data = static_cast(msg->pdata); - dest_->SignalReadPacket(dest_, data->packet.data(), - data->packet.size(), rtc::CreatePacketTime(0), 0); - delete data; - } - - bool SetLocalCertificate( - const rtc::scoped_refptr& certificate) override { - local_cert_ = certificate; - return true; - } - - void SetRemoteSSLCertificate(rtc::FakeSSLCertificate* cert) { - remote_cert_ = cert; - } - - bool IsDtlsActive() const override { return do_dtls_; } - - bool SetSrtpCryptoSuites(const std::vector& ciphers) override { - srtp_ciphers_ = ciphers; - return true; - } - - bool GetSrtpCryptoSuite(int* crypto_suite) override { - if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) { - *crypto_suite = chosen_crypto_suite_; - return true; - } - return false; - } - - bool GetSslCipherSuite(int* cipher_suite) override { return false; } - - rtc::scoped_refptr GetLocalCertificate() const override { - return local_cert_; - } - - std::unique_ptr GetRemoteSSLCertificate() - const override { - return remote_cert_ ? std::unique_ptr( - remote_cert_->GetReference()) - : nullptr; - } - - bool ExportKeyingMaterial(const std::string& label, - const uint8_t* context, - size_t context_len, - bool use_context, - uint8_t* result, - size_t result_len) override { - if (chosen_crypto_suite_ != rtc::SRTP_INVALID_CRYPTO_SUITE) { - memset(result, 0xff, result_len); - return true; - } - - return false; - } - - bool GetStats(ConnectionInfos* infos) override { - ConnectionInfo info; - infos->clear(); - infos->push_back(info); - return true; - } - - void set_ssl_max_protocol_version(rtc::SSLProtocolVersion version) { - ssl_max_version_ = version; - } - rtc::SSLProtocolVersion ssl_max_protocol_version() const { - return ssl_max_version_; - } - - private: - void NegotiateSrtpCiphers() { - for (std::vector::const_iterator it1 = srtp_ciphers_.begin(); - it1 != srtp_ciphers_.end(); ++it1) { - for (std::vector::const_iterator it2 = dest_->srtp_ciphers_.begin(); - it2 != dest_->srtp_ciphers_.end(); ++it2) { - if (*it1 == *it2) { - chosen_crypto_suite_ = *it1; - return; - } - } - } - } - - enum State { STATE_INIT, STATE_CONNECTING, STATE_CONNECTED }; - FakeTransportChannel* dest_ = nullptr; - State state_ = STATE_INIT; - bool async_ = false; - Candidates remote_candidates_; - rtc::scoped_refptr local_cert_; - rtc::FakeSSLCertificate* remote_cert_ = nullptr; - bool do_dtls_ = false; - std::vector srtp_ciphers_; - int chosen_crypto_suite_ = rtc::SRTP_INVALID_CRYPTO_SUITE; - int receiving_timeout_ = -1; - bool gather_continually_ = false; - IceRole role_ = ICEROLE_UNKNOWN; - uint64_t tiebreaker_ = 0; - std::string ice_ufrag_; - std::string ice_pwd_; - std::string remote_ice_ufrag_; - std::string remote_ice_pwd_; - IceMode remote_ice_mode_ = ICEMODE_FULL; - rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; - rtc::SSLFingerprint dtls_fingerprint_; - rtc::SSLRole ssl_role_ = rtc::SSL_CLIENT; - size_t connection_count_ = 0; - IceGatheringState gathering_state_ = kIceGatheringNew; - bool had_connection_ = false; -}; - -// Fake transport class, which can be passed to anything that needs a Transport. -// Can be informed of another FakeTransport via SetDestination (low-tech way -// of doing candidates) -class FakeTransport : public Transport { - public: - typedef std::map ChannelMap; - - explicit FakeTransport(const std::string& name) : Transport(name, nullptr) {} - - // Note that we only have a constructor with the allocator parameter so it can - // be wrapped by a DtlsTransport. - FakeTransport(const std::string& name, PortAllocator* allocator) - : Transport(name, nullptr) {} - - ~FakeTransport() { DestroyAllChannels(); } - - const ChannelMap& channels() const { return channels_; } - - // If async, will send packets by "Post"-ing to message queue instead of - // synchronously "Send"-ing. - void SetAsync(bool async) { async_ = async; } - - // If |asymmetric| is true, only set the destination for this transport, and - // not |dest|. - void SetDestination(FakeTransport* dest, bool asymmetric = false) { - dest_ = dest; - for (const auto& kv : channels_) { - kv.second->SetLocalCertificate(certificate_); - SetChannelDestination(kv.first, kv.second, asymmetric); - } - } - - void SetWritable(bool writable) { - for (const auto& kv : channels_) { - kv.second->SetWritable(writable); - } - } - - void SetLocalCertificate( - const rtc::scoped_refptr& certificate) override { - certificate_ = certificate; - } - bool GetLocalCertificate( - rtc::scoped_refptr* certificate) override { - if (!certificate_) - return false; - - *certificate = certificate_; - return true; - } - - bool GetSslRole(rtc::SSLRole* role) const override { - if (channels_.empty()) { - return false; - } - return channels_.begin()->second->GetSslRole(role); - } - - bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override { - ssl_max_version_ = version; - for (const auto& kv : channels_) { - kv.second->set_ssl_max_protocol_version(ssl_max_version_); - } - return true; - } - rtc::SSLProtocolVersion ssl_max_protocol_version() const { - return ssl_max_version_; - } - - using Transport::local_description; - using Transport::remote_description; - using Transport::VerifyCertificateFingerprint; - using Transport::NegotiateRole; - - protected: - TransportChannelImpl* CreateTransportChannel(int component) override { - if (channels_.find(component) != channels_.end()) { - return nullptr; - } - FakeTransportChannel* channel = new FakeTransportChannel(name(), component); - channel->set_ssl_max_protocol_version(ssl_max_version_); - channel->SetAsync(async_); - SetChannelDestination(component, channel, false); - channels_[component] = channel; - return channel; - } - - void DestroyTransportChannel(TransportChannelImpl* channel) override { - channels_.erase(channel->component()); - delete channel; - } - - private: - FakeTransportChannel* GetFakeChannel(int component) { - auto it = channels_.find(component); - return (it != channels_.end()) ? it->second : nullptr; - } - - void SetChannelDestination(int component, - FakeTransportChannel* channel, - bool asymmetric) { - FakeTransportChannel* dest_channel = nullptr; - if (dest_) { - dest_channel = dest_->GetFakeChannel(component); - if (dest_channel && !asymmetric) { - dest_channel->SetLocalCertificate(dest_->certificate_); - } - } - channel->SetDestination(dest_channel, asymmetric); - } - - // Note, this is distinct from the Channel map owned by Transport. - // This map just tracks the FakeTransportChannels created by this class. - // It's mainly needed so that we can access a FakeTransportChannel directly, - // even if wrapped by a DtlsTransportChannelWrapper. - ChannelMap channels_; - FakeTransport* dest_ = nullptr; - bool async_ = false; - rtc::scoped_refptr certificate_; - rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; -}; - -// Fake candidate pair class, which can be passed to BaseChannel for testing -// purposes. -class FakeCandidatePair : public CandidatePairInterface { - public: - FakeCandidatePair(const Candidate& local_candidate, - const Candidate& remote_candidate) - : local_candidate_(local_candidate), - remote_candidate_(remote_candidate) {} - const Candidate& local_candidate() const override { return local_candidate_; } - const Candidate& remote_candidate() const override { - return remote_candidate_; - } - - private: - Candidate local_candidate_; - Candidate remote_candidate_; -}; - -// Fake TransportController class, which can be passed into a BaseChannel object -// for test purposes. Can be connected to other FakeTransportControllers via -// Connect(). +// Fake TransportController class, which can be passed into a WebRtcSession +// object for test purposes. Can be connected to other FakeTransportControllers +// via Connect(). // // This fake is unusual in that for the most part, it's implemented with the // real TransportController code, but with fake TransportChannels underneath. @@ -490,98 +35,110 @@ class FakeTransportController : public TransportController { FakeTransportController() : TransportController(rtc::Thread::Current(), rtc::Thread::Current(), - nullptr), - fail_create_channel_(false) {} + nullptr) {} + + explicit FakeTransportController(bool redetermine_role_on_ice_restart) + : TransportController(rtc::Thread::Current(), + rtc::Thread::Current(), + nullptr, + redetermine_role_on_ice_restart) {} explicit FakeTransportController(IceRole role) : TransportController(rtc::Thread::Current(), rtc::Thread::Current(), - nullptr), - fail_create_channel_(false) { + nullptr) { SetIceRole(role); } - explicit FakeTransportController(rtc::Thread* worker_thread) - : TransportController(rtc::Thread::Current(), worker_thread, nullptr), - fail_create_channel_(false) {} + explicit FakeTransportController(rtc::Thread* network_thread) + : TransportController(rtc::Thread::Current(), network_thread, nullptr) {} - FakeTransportController(rtc::Thread* worker_thread, IceRole role) - : TransportController(rtc::Thread::Current(), worker_thread, nullptr), - fail_create_channel_(false) { + FakeTransportController(rtc::Thread* network_thread, IceRole role) + : TransportController(rtc::Thread::Current(), network_thread, nullptr) { SetIceRole(role); } - FakeTransport* GetTransport_n(const std::string& transport_name) { - return static_cast( - TransportController::GetTransport_n(transport_name)); + FakeDtlsTransport* GetFakeDtlsTransport_n(const std::string& transport_name, + int component) { + return static_cast( + get_channel_for_testing(transport_name, component)); } + // Simulate the exchange of transport descriptions, and the gathering and + // exchange of ICE candidates. void Connect(FakeTransportController* dest) { + for (const std::string& transport_name : transport_names_for_testing()) { + std::unique_ptr local_fingerprint; + std::unique_ptr remote_fingerprint; + if (certificate_for_testing()) { + local_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate( + certificate_for_testing())); + } + if (dest->certificate_for_testing()) { + remote_fingerprint.reset(rtc::SSLFingerprint::CreateFromCertificate( + dest->certificate_for_testing())); + } + TransportDescription local_desc( + std::vector(), + rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), + rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), + cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, + local_fingerprint.get()); + TransportDescription remote_desc( + std::vector(), + rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), + rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), + cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_NONE, + remote_fingerprint.get()); + std::string err; + SetLocalTransportDescription(transport_name, local_desc, + cricket::CA_OFFER, &err); + dest->SetRemoteTransportDescription(transport_name, local_desc, + cricket::CA_OFFER, &err); + dest->SetLocalTransportDescription(transport_name, remote_desc, + cricket::CA_ANSWER, &err); + SetRemoteTransportDescription(transport_name, remote_desc, + cricket::CA_ANSWER, &err); + } + MaybeStartGathering(); + dest->MaybeStartGathering(); network_thread()->Invoke( - rtc::Bind(&FakeTransportController::Connect_n, this, dest)); + RTC_FROM_HERE, + rtc::Bind(&FakeTransportController::SetChannelDestinations_n, this, + dest)); } - TransportChannel* CreateTransportChannel_n(const std::string& transport_name, - int component) override { - if (fail_create_channel_) { - return nullptr; - } - return TransportController::CreateTransportChannel_n(transport_name, - component); - } - - FakeCandidatePair* CreateFakeCandidatePair( - const rtc::SocketAddress& local_address, - int16_t local_network_id, - const rtc::SocketAddress& remote_address, - int16_t remote_network_id) { - Candidate local_candidate(0, "udp", local_address, 0u, "", "", "local", 0, - "foundation", local_network_id, 0); - Candidate remote_candidate(0, "udp", remote_address, 0u, "", "", "local", 0, - "foundation", remote_network_id, 0); - return new FakeCandidatePair(local_candidate, remote_candidate); - } - - void set_fail_channel_creation(bool fail_channel_creation) { - fail_create_channel_ = fail_channel_creation; + void DestroyRtcpTransport(const std::string& transport_name) { + DestroyDtlsTransport_n(transport_name, + cricket::ICE_CANDIDATE_COMPONENT_RTCP); } protected: - Transport* CreateTransport_n(const std::string& transport_name) override { - return new FakeTransport(transport_name); + IceTransportInternal* CreateIceTransportChannel_n( + const std::string& transport_name, + int component) override { + return new FakeIceTransport(transport_name, component); } - void Connect_n(FakeTransportController* dest) { - // Simulate the exchange of candidates. - ConnectChannels_n(); - dest->ConnectChannels_n(); - for (auto& kv : transports()) { - FakeTransport* transport = static_cast(kv.second); - transport->SetDestination(dest->GetTransport_n(kv.first)); - } + DtlsTransportInternal* CreateDtlsTransportChannel_n( + const std::string& transport_name, + int component, + IceTransportInternal* ice) override { + return new FakeDtlsTransport(static_cast(ice)); } - void ConnectChannels_n() { - TransportDescription faketransport_desc( - std::vector(), - rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), - rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), cricket::ICEMODE_FULL, - cricket::CONNECTIONROLE_NONE, nullptr); - for (auto& kv : transports()) { - FakeTransport* transport = static_cast(kv.second); - // Set local transport description for FakeTransport before connecting. - // Otherwise, the RTC_CHECK in Transport.ConnectChannel will fail. - if (!transport->local_description()) { - transport->SetLocalTransportDescription(faketransport_desc, - cricket::CA_OFFER, nullptr); + private: + void SetChannelDestinations_n(FakeTransportController* dest) { + for (DtlsTransportInternal* tc : channels_for_testing()) { + FakeDtlsTransport* local = static_cast(tc); + FakeDtlsTransport* remote = dest->GetFakeDtlsTransport_n( + local->transport_name(), local->component()); + if (remote) { + bool asymmetric = false; + local->SetDestination(remote, asymmetric); } - transport->ConnectChannels(); - transport->MaybeStartGathering(); } } - - private: - bool fail_create_channel_; }; } // namespace cricket diff --git a/include/webrtc/p2p/base/icetransportinternal.h b/include/webrtc/p2p/base/icetransportinternal.h new file mode 100644 index 0000000..074a34a --- /dev/null +++ b/include/webrtc/p2p/base/icetransportinternal.h @@ -0,0 +1,153 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_ICETRANSPORTINTERNAL_H_ +#define WEBRTC_P2P_BASE_ICETRANSPORTINTERNAL_H_ + +#include + +#include "webrtc/base/stringencode.h" +#include "webrtc/p2p/base/candidate.h" +#include "webrtc/p2p/base/candidatepairinterface.h" +#include "webrtc/p2p/base/jseptransport.h" +#include "webrtc/p2p/base/packettransportinternal.h" +#include "webrtc/p2p/base/transportdescription.h" + +namespace webrtc { +class MetricsObserverInterface; +} + +namespace cricket { + +class IceTransportInternal; +typedef IceTransportInternal IceTransportInternal2; + +// TODO(zhihuang): Replace this with +// PeerConnectionInterface::IceConnectionState. +enum class IceTransportState { + STATE_INIT, + STATE_CONNECTING, // Will enter this state once a connection is created + STATE_COMPLETED, + STATE_FAILED +}; + +// TODO(zhihuang): Remove this once it's no longer used in +// remoting/protocol/libjingle_transport_factory.cc +enum IceProtocolType { + ICEPROTO_RFC5245 // Standard RFC 5245 version of ICE. +}; + +// IceTransportInternal is an internal abstract class that does ICE. +// Once the public interface is supported, +// (https://www.w3.org/TR/webrtc/#rtcicetransport-interface) +// the IceTransportInterface will be split from this class. +class IceTransportInternal : public rtc::PacketTransportInternal { + public: + virtual ~IceTransportInternal(){}; + + virtual IceTransportState GetState() const = 0; + + virtual const std::string& transport_name() const = 0; + + virtual int component() const = 0; + + virtual IceRole GetIceRole() const = 0; + + virtual void SetIceRole(IceRole role) = 0; + + virtual void SetIceTiebreaker(uint64_t tiebreaker) = 0; + + // TODO(zhihuang): Remove this once it's no longer called in + // remoting/protocol/libjingle_transport_factory.cc + virtual void SetIceProtocolType(IceProtocolType type) {} + + virtual void SetIceCredentials(const std::string& ice_ufrag, + const std::string& ice_pwd) { + SetIceParameters(IceParameters(ice_ufrag, ice_pwd, false)); + } + + virtual void SetRemoteIceCredentials(const std::string& ice_ufrag, + const std::string& ice_pwd) { + SetRemoteIceParameters(IceParameters(ice_ufrag, ice_pwd, false)); + } + + // The ufrag and pwd in |ice_params| must be set + // before candidate gathering can start. + virtual void SetIceParameters(const IceParameters& ice_params) = 0; + + virtual void SetRemoteIceParameters(const IceParameters& ice_params) = 0; + + virtual void SetRemoteIceMode(IceMode mode) = 0; + + virtual void SetIceConfig(const IceConfig& config) = 0; + + // Start gathering candidates if not already started, or if an ICE restart + // occurred. + virtual void MaybeStartGathering() = 0; + + virtual void SetMetricsObserver( + webrtc::MetricsObserverInterface* observer) = 0; + + virtual void AddRemoteCandidate(const Candidate& candidate) = 0; + + virtual void RemoveRemoteCandidate(const Candidate& candidate) = 0; + + virtual IceGatheringState gathering_state() const = 0; + + // Returns the current stats for this connection. + virtual bool GetStats(ConnectionInfos* infos) = 0; + + // Returns RTT estimate over the currently active connection, or an empty + // rtc::Optional if there is none. + virtual rtc::Optional GetRttEstimate() = 0; + + sigslot::signal1 SignalGatheringState; + + // Handles sending and receiving of candidates. + sigslot::signal2 + SignalCandidateGathered; + + sigslot::signal2 + SignalCandidatesRemoved; + + // Deprecated by SignalSelectedCandidatePairChanged + // This signal occurs when there is a change in the way that packets are + // being routed, i.e. to a different remote location. The candidate + // indicates where and how we are currently sending media. + sigslot::signal2 SignalRouteChange; + + // Signalled when the current selected candidate pair has changed. + // The first parameter is the transport that signals the event. + // The second parameter is the new selected candidate pair. The third + // parameter is the last packet id sent on the previous candidate pair. + // The fourth parameter is a boolean which is true if the Transport + // is ready to send with this candidate pair. + sigslot::signal4 + SignalSelectedCandidatePairChanged; + + // Invoked when there is conflict in the ICE role between local and remote + // agents. + sigslot::signal1 SignalRoleConflict; + + // Emitted whenever the transport state changed. + sigslot::signal1 SignalStateChanged; + + // Invoked when the transport is being destroyed. + sigslot::signal1 SignalDestroyed; + + // Debugging description of this transport. + std::string debug_name() const override { + return transport_name() + " " + rtc::ToString(component()); + } +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_ICETRANSPORTINTERNAL_H_ diff --git a/include/webrtc/p2p/base/jseptransport.h b/include/webrtc/p2p/base/jseptransport.h new file mode 100644 index 0000000..e29dd0d --- /dev/null +++ b/include/webrtc/p2p/base/jseptransport.h @@ -0,0 +1,378 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ +#define WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ + +#include +#include +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/messagequeue.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/rtccertificate.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/sslstreamadapter.h" +#include "webrtc/p2p/base/candidate.h" +#include "webrtc/p2p/base/p2pconstants.h" +#include "webrtc/p2p/base/sessiondescription.h" +#include "webrtc/p2p/base/transportinfo.h" + +namespace cricket { + +class DtlsTransportInternal; +enum class IceCandidatePairState; + +typedef std::vector Candidates; + +// TODO(deadbeef): Move all of these enums, POD types and utility methods to +// another header file. + +// TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState +// once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming +// style. +enum IceConnectionState { + kIceConnectionConnecting = 0, + kIceConnectionFailed, + kIceConnectionConnected, // Writable, but still checking one or more + // connections + kIceConnectionCompleted, +}; + +enum DtlsTransportState { + // Haven't started negotiating. + DTLS_TRANSPORT_NEW = 0, + // Have started negotiating. + DTLS_TRANSPORT_CONNECTING, + // Negotiated, and has a secure connection. + DTLS_TRANSPORT_CONNECTED, + // Transport is closed. + DTLS_TRANSPORT_CLOSED, + // Failed due to some error in the handshake process. + DTLS_TRANSPORT_FAILED, +}; + +// TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState +// once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming +// style. +enum IceGatheringState { + kIceGatheringNew = 0, + kIceGatheringGathering, + kIceGatheringComplete, +}; + +enum ContinualGatheringPolicy { + // All port allocator sessions will stop after a writable connection is found. + GATHER_ONCE = 0, + // The most recent port allocator session will keep on running. + GATHER_CONTINUALLY, + // The most recent port allocator session will keep on running, and it will + // try to recover connectivity if the channel becomes disconnected. + GATHER_CONTINUALLY_AND_RECOVER, +}; + +// Stats that we can return about the connections for a transport channel. +// TODO(hta): Rename to ConnectionStats +struct ConnectionInfo { + ConnectionInfo(); + + bool best_connection; // Is this the best connection we have? + bool writable; // Has this connection received a STUN response? + bool receiving; // Has this connection received anything? + bool timeout; // Has this connection timed out? + bool new_connection; // Is this a newly created connection? + size_t rtt; // The STUN RTT for this connection. + size_t sent_total_bytes; // Total bytes sent on this connection. + size_t sent_bytes_second; // Bps over the last measurement interval. + size_t sent_discarded_packets; // Number of outgoing packets discarded due to + // socket errors. + size_t sent_total_packets; // Number of total outgoing packets attempted for + // sending. + size_t sent_ping_requests_total; // Number of STUN ping request sent. + size_t sent_ping_requests_before_first_response; // Number of STUN ping + // sent before receiving the first response. + size_t sent_ping_responses; // Number of STUN ping response sent. + + size_t recv_total_bytes; // Total bytes received on this connection. + size_t recv_bytes_second; // Bps over the last measurement interval. + size_t recv_ping_requests; // Number of STUN ping request received. + size_t recv_ping_responses; // Number of STUN ping response received. + Candidate local_candidate; // The local candidate for this connection. + Candidate remote_candidate; // The remote candidate for this connection. + void* key; // A static value that identifies this conn. + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-state + IceCandidatePairState state; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-priority + uint64_t priority; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-nominated + bool nominated; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime + uint64_t total_round_trip_time_ms; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime + rtc::Optional current_round_trip_time_ms; +}; + +// Information about all the connections of a channel. +typedef std::vector ConnectionInfos; + +// Information about a specific channel +struct TransportChannelStats { + int component = 0; + ConnectionInfos connection_infos; + int srtp_crypto_suite = rtc::SRTP_INVALID_CRYPTO_SUITE; + int ssl_cipher_suite = rtc::TLS_NULL_WITH_NULL_NULL; + DtlsTransportState dtls_state = DTLS_TRANSPORT_NEW; +}; + +// Information about all the channels of a transport. +// TODO(hta): Consider if a simple vector is as good as a map. +typedef std::vector TransportChannelStatsList; + +// Information about the stats of a transport. +struct TransportStats { + std::string transport_name; + TransportChannelStatsList channel_stats; +}; + +// ICE Nomination mode. +enum class NominationMode { + REGULAR, // Nominate once per ICE restart (Not implemented yet). + AGGRESSIVE, // Nominate every connection except that it will behave as if + // REGULAR when the remote is an ICE-LITE endpoint. + SEMI_AGGRESSIVE // Our current implementation of the nomination algorithm. + // The details are described in P2PTransportChannel. +}; + +// Information about ICE configuration. +// TODO(deadbeef): Use rtc::Optional to represent unset values, instead of +// -1. +struct IceConfig { + // The ICE connection receiving timeout value in milliseconds. + int receiving_timeout = -1; + // Time interval in milliseconds to ping a backup connection when the ICE + // channel is strongly connected. + int backup_connection_ping_interval = -1; + + ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; + + bool gather_continually() const { + return continual_gathering_policy == GATHER_CONTINUALLY || + continual_gathering_policy == GATHER_CONTINUALLY_AND_RECOVER; + } + + // Whether we should prioritize Relay/Relay candidate when nothing + // is writable yet. + bool prioritize_most_likely_candidate_pairs = false; + + // Writable connections are pinged at a slower rate once stablized. + int stable_writable_connection_ping_interval = -1; + + // If set to true, this means the ICE transport should presume TURN-to-TURN + // candidate pairs will succeed, even before a binding response is received. + bool presume_writable_when_fully_relayed = false; + + // Interval to check on all networks and to perform ICE regathering on any + // active network having no connection on it. + rtc::Optional regather_on_failed_networks_interval; + + // The time period in which we will not switch the selected connection + // when a new connection becomes receiving but the selected connection is not + // in case that the selected connection may become receiving soon. + rtc::Optional receiving_switching_delay; + + // TODO(honghaiz): Change the default to regular nomination. + // Default nomination mode if the remote does not support renomination. + NominationMode default_nomination_mode = NominationMode::SEMI_AGGRESSIVE; + + // ICE checks (STUN pings) will not be sent at higher rate (lower interval) + // than this, no matter what other settings there are. + // Measure in milliseconds. + rtc::Optional ice_check_min_interval; + + IceConfig() {} + IceConfig(int receiving_timeout_ms, + int backup_connection_ping_interval, + ContinualGatheringPolicy gathering_policy, + bool prioritize_most_likely_candidate_pairs, + int stable_writable_connection_ping_interval_ms, + bool presume_writable_when_fully_relayed, + int regather_on_failed_networks_interval_ms, + int receiving_switching_delay_ms) + : receiving_timeout(receiving_timeout_ms), + backup_connection_ping_interval(backup_connection_ping_interval), + continual_gathering_policy(gathering_policy), + prioritize_most_likely_candidate_pairs( + prioritize_most_likely_candidate_pairs), + stable_writable_connection_ping_interval( + stable_writable_connection_ping_interval_ms), + presume_writable_when_fully_relayed( + presume_writable_when_fully_relayed), + regather_on_failed_networks_interval( + regather_on_failed_networks_interval_ms), + receiving_switching_delay(receiving_switching_delay_ms) {} +}; + +bool BadTransportDescription(const std::string& desc, std::string* err_desc); + +bool IceCredentialsChanged(const std::string& old_ufrag, + const std::string& old_pwd, + const std::string& new_ufrag, + const std::string& new_pwd); + +// If a candidate is not acceptable, returns false and sets error. +bool VerifyCandidate(const Candidate& candidate, std::string* error); +bool VerifyCandidates(const Candidates& candidates, std::string* error); + +// Helper class used by TransportController that processes +// TransportDescriptions. A TransportDescription represents the +// transport-specific properties of an SDP m= section, processed according to +// JSEP. Each transport consists of DTLS and ICE transport channels for RTP +// (and possibly RTCP, if rtcp-mux isn't used). +// +// On Threading: Transport performs work solely on the network thread, and so +// its methods should only be called on the network thread. +// +// TODO(deadbeef): Move this into /pc/ and out of /p2p/base/, since it's +// PeerConnection-specific. +class JsepTransport : public sigslot::has_slots<> { + public: + // |mid| is just used for log statements in order to identify the Transport. + // Note that |certificate| is allowed to be null since a remote description + // may be set before a local certificate is generated. + JsepTransport(const std::string& mid, + const rtc::scoped_refptr& certificate); + + // Returns the MID of this transport. + const std::string& mid() const { return mid_; } + + // Add or remove channel that is affected when a local/remote transport + // description is set on this transport. Need to add all channels before + // setting a transport description. + bool AddChannel(DtlsTransportInternal* dtls, int component); + bool RemoveChannel(int component); + bool HasChannels() const; + + bool ready_for_remote_candidates() const { + return local_description_set_ && remote_description_set_; + } + + // Must be called before applying local session description. + // Needed in order to verify the local fingerprint. + void SetLocalCertificate( + const rtc::scoped_refptr& certificate); + + // Get a copy of the local certificate provided by SetLocalCertificate. + bool GetLocalCertificate( + rtc::scoped_refptr* certificate) const; + + // Set the local TransportDescription to be used by DTLS and ICE channels + // that are part of this Transport. + bool SetLocalTransportDescription(const TransportDescription& description, + ContentAction action, + std::string* error_desc); + + // Set the remote TransportDescription to be used by DTLS and ICE channels + // that are part of this Transport. + bool SetRemoteTransportDescription(const TransportDescription& description, + ContentAction action, + std::string* error_desc); + + // Set the "needs-ice-restart" flag as described in JSEP. After the flag is + // set, offers should generate new ufrags/passwords until an ICE restart + // occurs. + // + // This and the below method can be called safely from any thread as long as + // SetXTransportDescription is not in progress. + void SetNeedsIceRestartFlag(); + // Returns true if the ICE restart flag above was set, and no ICE restart has + // occurred yet for this transport (by applying a local description with + // changed ufrag/password). + bool NeedsIceRestart() const; + + void GetSslRole(rtc::SSLRole* ssl_role) const; + + // TODO(deadbeef): Make this const. See comment in transportcontroller.h. + bool GetStats(TransportStats* stats); + + // The current local transport description, possibly used + // by the transport controller. + const TransportDescription* local_description() const { + return local_description_.get(); + } + + // The current remote transport description, possibly used + // by the transport controller. + const TransportDescription* remote_description() const { + return remote_description_.get(); + } + + // TODO(deadbeef): The methods below are only public for testing. Should make + // them utility functions or objects so they can be tested independently from + // this class. + + // Returns false if the certificate's identity does not match the fingerprint, + // or either is NULL. + bool VerifyCertificateFingerprint(const rtc::RTCCertificate* certificate, + const rtc::SSLFingerprint* fingerprint, + std::string* error_desc) const; + + // Negotiates the SSL role based off the offer and answer as specified by + // RFC 4145, section-4.1. Returns false if the SSL role cannot be determined + // from the local description and remote description. + bool NegotiateRole(ContentAction local_role, + rtc::SSLRole* ssl_role, + std::string* error_desc) const; + + private: + // Negotiates the transport parameters based on the current local and remote + // transport description, such as the ICE role to use, and whether DTLS + // should be activated. + // + // Called when an answer TransportDescription is applied. + bool NegotiateTransportDescription(ContentAction local_role, + std::string* error_desc); + + // Pushes down the transport parameters from the local description, such + // as the ICE ufrag and pwd. + bool ApplyLocalTransportDescription(DtlsTransportInternal* dtls_transport, + std::string* error_desc); + + // Pushes down the transport parameters from the remote description to the + // transport channel. + bool ApplyRemoteTransportDescription(DtlsTransportInternal* dtls_transport, + std::string* error_desc); + + // Pushes down the transport parameters obtained via negotiation. + bool ApplyNegotiatedTransportDescription( + DtlsTransportInternal* dtls_transport, + std::string* error_desc); + + const std::string mid_; + // needs-ice-restart bit as described in JSEP. + bool needs_ice_restart_ = false; + rtc::scoped_refptr certificate_; + rtc::SSLRole secure_role_ = rtc::SSL_CLIENT; + std::unique_ptr remote_fingerprint_; + std::unique_ptr local_description_; + std::unique_ptr remote_description_; + bool local_description_set_ = false; + bool remote_description_set_ = false; + + // Candidate component => DTLS channel + std::map channels_; + + RTC_DISALLOW_COPY_AND_ASSIGN(JsepTransport); +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_JSEPTRANSPORT_H_ diff --git a/include/webrtc/p2p/base/mockicetransport.h b/include/webrtc/p2p/base/mockicetransport.h new file mode 100644 index 0000000..53549ab --- /dev/null +++ b/include/webrtc/p2p/base/mockicetransport.h @@ -0,0 +1,81 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_MOCKICETRANSPORT_H_ +#define WEBRTC_P2P_BASE_MOCKICETRANSPORT_H_ + +#include +#include +#include + +#include "webrtc/base/gunit.h" +#include "webrtc/p2p/base/icetransportinternal.h" +#include "webrtc/test/gmock.h" + +using testing::_; +using testing::Return; + +namespace cricket { + +// Used in Chromium/remoting/protocol/channel_socket_adapter_unittest.cc +class MockIceTransport : public IceTransportInternal { + public: + MockIceTransport() { + SignalReadyToSend(this); + SignalWritableState(this); + } + + MOCK_METHOD4(SendPacket, + int(const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags)); + MOCK_METHOD2(SetOption, int(rtc::Socket::Option opt, int value)); + MOCK_METHOD0(GetError, int()); + MOCK_CONST_METHOD0(GetIceRole, cricket::IceRole()); + MOCK_METHOD1(GetStats, bool(cricket::ConnectionInfos* infos)); + MOCK_CONST_METHOD0(IsDtlsActive, bool()); + MOCK_CONST_METHOD1(GetSslRole, bool(rtc::SSLRole* role)); + + IceTransportState GetState() const override { + return IceTransportState::STATE_INIT; + } + const std::string& transport_name() const override { return transport_name_; } + int component() const override { return 0; } + void SetIceRole(IceRole role) override {} + void SetIceTiebreaker(uint64_t tiebreaker) override {} + // The ufrag and pwd in |ice_params| must be set + // before candidate gathering can start. + void SetIceParameters(const IceParameters& ice_params) override {} + void SetRemoteIceParameters(const IceParameters& ice_params) override {} + void SetRemoteIceMode(IceMode mode) override {} + void SetIceConfig(const IceConfig& config) override {} + rtc::Optional GetRttEstimate() override { + return rtc::Optional(); + } + void MaybeStartGathering() override {} + void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override { + } + void AddRemoteCandidate(const Candidate& candidate) override {} + void RemoveRemoteCandidate(const Candidate& candidate) override {} + IceGatheringState gathering_state() const override { + return IceGatheringState::kIceGatheringComplete; + } + + bool receiving() const override { return true; } + bool writable() const override { return true; } + + private: + std::string transport_name_; +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_MOCKICETRANSPORT_H_ diff --git a/include/webrtc/p2p/base/p2ptransport.h b/include/webrtc/p2p/base/p2ptransport.h deleted file mode 100644 index d4da224..0000000 --- a/include/webrtc/p2p/base/p2ptransport.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_BASE_P2PTRANSPORT_H_ -#define WEBRTC_P2P_BASE_P2PTRANSPORT_H_ - -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/p2p/base/transport.h" - -namespace cricket { - -// Everything in this class should be called on the worker thread. -class P2PTransport : public Transport { - public: - P2PTransport(const std::string& name, PortAllocator* allocator); - virtual ~P2PTransport(); - - protected: - // Creates and destroys P2PTransportChannel. - virtual TransportChannelImpl* CreateTransportChannel(int component); - virtual void DestroyTransportChannel(TransportChannelImpl* channel); - - friend class P2PTransportChannel; - - RTC_DISALLOW_COPY_AND_ASSIGN(P2PTransport); -}; - -} // namespace cricket - -#endif // WEBRTC_P2P_BASE_P2PTRANSPORT_H_ diff --git a/include/webrtc/p2p/base/p2ptransportchannel.h b/include/webrtc/p2p/base/p2ptransportchannel.h index b002c8b..a535edd 100644 --- a/include/webrtc/p2p/base/p2ptransportchannel.h +++ b/include/webrtc/p2p/base/p2ptransportchannel.h @@ -26,31 +26,26 @@ #include #include +#include "webrtc/base/asyncpacketsocket.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/sigslot.h" #include "webrtc/p2p/base/candidate.h" #include "webrtc/p2p/base/candidatepairinterface.h" -#include "webrtc/p2p/base/p2ptransport.h" +#include "webrtc/p2p/base/icetransportinternal.h" #include "webrtc/p2p/base/portallocator.h" #include "webrtc/p2p/base/portinterface.h" -#include "webrtc/p2p/base/transportchannelimpl.h" -#include "webrtc/base/asyncpacketsocket.h" -#include "webrtc/base/sigslot.h" namespace cricket { -extern const int WEAK_PING_INTERVAL; - -struct IceParameters { - std::string ufrag; - std::string pwd; - IceParameters(const std::string& ice_ufrag, const std::string& ice_pwd) - : ufrag(ice_ufrag), pwd(ice_pwd) {} +// Enum for UMA metrics, used to record whether the channel is +// connected/connecting/disconnected when ICE restart happens. +enum class IceRestartState { CONNECTING, CONNECTED, DISCONNECTED, MAX_VALUE }; - bool operator==(const IceParameters& other) { - return ufrag == other.ufrag && pwd == other.pwd; - } - bool operator!=(const IceParameters& other) { return !(*this == other); } -}; +extern const int WEAK_PING_INTERVAL; +extern const int STRONG_PING_INTERVAL; +extern const int WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL; +extern const int STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL; +static const int MIN_PINGS_AT_WEAK_PING_INTERVAL = 3; // Adds the port on which the candidate originated. class RemoteCandidate : public Candidate { @@ -66,31 +61,29 @@ class RemoteCandidate : public Candidate { // P2PTransportChannel manages the candidates and connection process to keep // two P2P clients connected to each other. -class P2PTransportChannel : public TransportChannelImpl, +class P2PTransportChannel : public IceTransportInternal, public rtc::MessageHandler { public: P2PTransportChannel(const std::string& transport_name, int component, PortAllocator* allocator); - // TODO(mikescarlett): Deprecated. Remove when Chromium's - // IceTransportChannel does not depend on this. - P2PTransportChannel(const std::string& transport_name, - int component, - P2PTransport* transport, - PortAllocator* allocator); virtual ~P2PTransportChannel(); // From TransportChannelImpl: - TransportChannelState GetState() const override; + IceTransportState GetState() const override; + const std::string& transport_name() const override { return transport_name_; } + int component() const override { return component_; } + bool writable() const override { return writable_; } + bool receiving() const override { return receiving_; } void SetIceRole(IceRole role) override; IceRole GetIceRole() const override { return ice_role_; } void SetIceTiebreaker(uint64_t tiebreaker) override; - void SetIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override; - void SetRemoteIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override; + void SetIceParameters(const IceParameters& ice_params) override; + void SetRemoteIceParameters(const IceParameters& ice_params) override; void SetRemoteIceMode(IceMode mode) override; - void Connect() override; + // TODO(deadbeef): Deprecated. Remove when Chromium's + // IceTransportChannel does not depend on this. + void Connect() {} void MaybeStartGathering() override; IceGatheringState gathering_state() const override { return gathering_state_; @@ -101,8 +94,10 @@ class P2PTransportChannel : public TransportChannelImpl, // only update the parameter if it is considered set in |config|. For example, // a negative value of receiving_timeout will be considered "not set" and we // will not use it to update the respective parameter in |config_|. + // TODO(deadbeef): Use rtc::Optional instead of negative values. void SetIceConfig(const IceConfig& config) override; const IceConfig& config() const; + void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override; // From TransportChannel: int SendPacket(const char* data, @@ -113,67 +108,23 @@ class P2PTransportChannel : public TransportChannelImpl, bool GetOption(rtc::Socket::Option opt, int* value) override; int GetError() override { return error_; } bool GetStats(std::vector* stats) override; + rtc::Optional GetRttEstimate() override; - const Connection* best_connection() const { return best_connection_; } + // TODO(honghaiz): Remove this method once the reference of it in + // Chromoting is removed. + const Connection* best_connection() const { return selected_connection_; } + + const Connection* selected_connection() const { return selected_connection_; } void set_incoming_only(bool value) { incoming_only_ = value; } - // Note: This is only for testing purpose. - // |ports_| should not be changed from outside. + // Note: These are only for testing purpose. + // |ports_| and |pruned_ports| should not be changed from outside. const std::vector& ports() { return ports_; } + const std::vector& pruned_ports() { return pruned_ports_; } IceMode remote_ice_mode() const { return remote_ice_mode_; } - // DTLS methods. - bool IsDtlsActive() const override { return false; } - - // Default implementation. - bool GetSslRole(rtc::SSLRole* role) const override { return false; } - - bool SetSslRole(rtc::SSLRole role) override { return false; } - - // Set up the ciphers to use for DTLS-SRTP. - bool SetSrtpCryptoSuites(const std::vector& ciphers) override { - return false; - } - - // Find out which DTLS-SRTP cipher was negotiated. - bool GetSrtpCryptoSuite(int* cipher) override { return false; } - - // Find out which DTLS cipher was negotiated. - bool GetSslCipherSuite(int* cipher) override { return false; } - - // Returns null because the channel is not encrypted by default. - rtc::scoped_refptr GetLocalCertificate() const override { - return nullptr; - } - - std::unique_ptr GetRemoteSSLCertificate() - const override { - return nullptr; - } - - // Allows key material to be extracted for external encryption. - bool ExportKeyingMaterial(const std::string& label, - const uint8_t* context, - size_t context_len, - bool use_context, - uint8_t* result, - size_t result_len) override { - return false; - } - - bool SetLocalCertificate( - const rtc::scoped_refptr& certificate) override { - return false; - } - - // Set DTLS Remote fingerprint. Must be after local identity set. - bool SetRemoteFingerprint(const std::string& digest_alg, - const uint8_t* digest, - size_t digest_len) override { - return false; - } - + void PruneAllPorts(); int receiving_timeout() const { return config_.receiving_timeout; } int check_receiving_interval() const { return check_receiving_interval_; } @@ -197,21 +148,79 @@ class P2PTransportChannel : public TransportChannelImpl, return remote_candidates_; } + std::string ToString() const { + const char RECEIVING_ABBREV[2] = {'_', 'R'}; + const char WRITABLE_ABBREV[2] = {'_', 'W'}; + std::stringstream ss; + ss << "Channel[" << transport_name_ << "|" << component_ << "|" + << RECEIVING_ABBREV[receiving_] << WRITABLE_ABBREV[writable_] << "]"; + return ss.str(); + } + private: - rtc::Thread* thread() { return worker_thread_; } + rtc::Thread* thread() const { return network_thread_; } bool IsGettingPorts() { return allocator_session()->IsGettingPorts(); } // A transport channel is weak if the current best connection is either // not receiving or not writable, or if there is no best connection at all. bool weak() const; + + int weak_ping_interval() const { + if (config_.ice_check_min_interval && + weak_ping_interval_ < *config_.ice_check_min_interval) { + return *config_.ice_check_min_interval; + } + return weak_ping_interval_; + } + + int strong_ping_interval() const { + if (config_.ice_check_min_interval && + STRONG_PING_INTERVAL < *config_.ice_check_min_interval) { + return *config_.ice_check_min_interval; + } + return STRONG_PING_INTERVAL; + } + + // Returns true if it's possible to send packets on |connection|. + bool ReadyToSend(Connection* connection) const; void UpdateConnectionStates(); - void RequestSort(); - void SortConnections(); - void SwitchBestConnectionTo(Connection* conn); + void RequestSortAndStateUpdate(); + // Start pinging if we haven't already started, and we now have a connection + // that's pingable. + void MaybeStartPinging(); + + // The methods below return a positive value if |a| is preferable to |b|, + // a negative value if |b| is preferable, and 0 if they're equally preferable. + // If |receiving_unchanged_threshold| is set, then when |b| is receiving and + // |a| is not, returns a negative value only if |b| has been in receiving + // state and |a| has been in not receiving state since + // |receiving_unchanged_threshold| and sets + // |missed_receiving_unchanged_threshold| to true otherwise. + int CompareConnectionStates( + const cricket::Connection* a, + const cricket::Connection* b, + rtc::Optional receiving_unchanged_threshold, + bool* missed_receiving_unchanged_threshold) const; + int CompareConnectionCandidates(const cricket::Connection* a, + const cricket::Connection* b) const; + // Compares two connections based on the connection states + // (writable/receiving/connected), nomination states, last data received time, + // and static preferences. Does not include latency. Used by both sorting + // and ShouldSwitchSelectedConnection(). + // Returns a positive value if |a| is better than |b|. + int CompareConnections(const cricket::Connection* a, + const cricket::Connection* b, + rtc::Optional receiving_unchanged_threshold, + bool* missed_receiving_unchanged_threshold) const; + + bool PresumedWritable(const cricket::Connection* conn) const; + + void SortConnectionsAndUpdateState(); + void SwitchSelectedConnection(Connection* conn); void UpdateState(); void HandleAllTimedOut(); void MaybeStopPortAllocatorSessions(); - TransportChannelState ComputeState() const; + IceTransportState ComputeState() const; Connection* GetBestConnectionOnNetwork(rtc::Network* network) const; bool CreateConnections(const Candidate& remote_candidate, @@ -225,14 +234,24 @@ class P2PTransportChannel : public TransportChannelImpl, bool IsDuplicateRemoteCandidate(const Candidate& candidate); void RememberRemoteCandidate(const Candidate& remote_candidate, PortInterface* origin_port); - bool IsPingable(Connection* conn, int64_t now); + bool IsPingable(const Connection* conn, int64_t now) const; + // Whether a writable connection is past its ping interval and needs to be + // pinged again. + bool WritableConnectionPastPingInterval(const Connection* conn, + int64_t now) const; + int CalculateActiveWritablePingInterval(const Connection* conn, + int64_t now) const; void PingConnection(Connection* conn); void AddAllocatorSession(std::unique_ptr session); void AddConnection(Connection* connection); void OnPortReady(PortAllocatorSession *session, PortInterface* port); + void OnPortsPruned(PortAllocatorSession* session, + const std::vector& ports); void OnCandidatesReady(PortAllocatorSession *session, const std::vector& candidates); + void OnCandidatesRemoved(PortAllocatorSession* session, + const std::vector& candidates); void OnCandidatesAllocationDone(PortAllocatorSession* session); void OnUnknownAddress(PortInterface* port, const rtc::SocketAddress& addr, @@ -240,8 +259,13 @@ class P2PTransportChannel : public TransportChannelImpl, IceMessage* stun_msg, const std::string& remote_username, bool port_muxed); + + // When a port is destroyed, remove it from both lists |ports_| + // and |pruned_ports_|. void OnPortDestroyed(PortInterface* port); - void OnPortNetworkInactive(PortInterface* port); + // When pruning a port, move it from |ports_| to |pruned_ports_|. + // Returns true if the port is found and removed from |ports_|. + bool PrunePort(PortInterface* port); void OnRoleConflict(PortInterface* port); void OnConnectionStateChange(Connection* connection); @@ -254,19 +278,32 @@ class P2PTransportChannel : public TransportChannelImpl, void OnNominated(Connection* conn); void OnMessage(rtc::Message* pmsg) override; - void OnSort(); void OnCheckAndPing(); - + void OnRegatherOnFailedNetworks(); + + uint32_t GetNominationAttr(Connection* conn) const; + bool GetUseCandidateAttr(Connection* conn, NominationMode mode) const; + + // Returns true if we should switch to the new connection. + // sets |missed_receiving_unchanged_threshold| to true if either + // the selected connection or the new connection missed its + // receiving-unchanged-threshold. + bool ShouldSwitchSelectedConnection( + Connection* new_connection, + bool* missed_receiving_unchanged_threshold) const; + // Returns true if the new_connection is selected for transmission. + bool MaybeSwitchSelectedConnection(Connection* new_connection, + const std::string& reason); + // Gets the best connection for each network. + std::map GetBestConnectionByNetwork() const; + std::vector GetBestWritableConnectionPerNetwork() const; void PruneConnections(); - Connection* best_nominated_connection() const; - bool IsBackupConnection(Connection* conn) const; + bool IsBackupConnection(const Connection* conn) const; - Connection* FindConnectionToPing(int64_t now); Connection* FindOldestConnectionNeedingTriggeredCheck(int64_t now); // Between |conn1| and |conn2|, this function returns the one which should // be pinged first. - Connection* SelectMostPingableConnection(Connection* conn1, - Connection* conn2); + Connection* MorePingable(Connection* conn1, Connection* conn2); // Select the connection which is Relay/Relay. If both of them are, // UDP relay protocol takes precedence. Connection* MostLikelyToWork(Connection* conn1, Connection* conn2); @@ -291,15 +328,29 @@ class P2PTransportChannel : public TransportChannelImpl, : static_cast(remote_ice_parameters_.size() - 1); } + // Sets the writable state, signaling if necessary. + void set_writable(bool writable); + // Sets the receiving state, signaling if necessary. + void set_receiving(bool receiving); + + std::string transport_name_; + int component_; PortAllocator* allocator_; - rtc::Thread* worker_thread_; + rtc::Thread* network_thread_; bool incoming_only_; int error_; std::vector> allocator_sessions_; - std::vector ports_; + // |ports_| contains ports that are used to form new connections when + // new remote candidates are added. + std::vector ports_; + // |pruned_ports_| contains ports that have been removed from |ports_| and + // are not being used to form new connections, but that aren't yet destroyed. + // They may have existing connections, and they still fire signals such as + // SignalUnknownAddress. + std::vector pruned_ports_; // |connections_| is a sorted list with the first one always be the - // |best_connection_| when it's not nullptr. The combination of + // |selected_connection_| when it's not nullptr. The combination of // |pinged_connections_| and |unpinged_connections_| has the same // connections as |connections_|. These 2 sets maintain whether a // connection should be pinged next or not. @@ -307,18 +358,14 @@ class P2PTransportChannel : public TransportChannelImpl, std::set pinged_connections_; std::set unpinged_connections_; - Connection* best_connection_; + Connection* selected_connection_ = nullptr; - // Connection selected by the controlling agent. This should be used only - // at controlled side when protocol type is RFC5245. - Connection* pending_best_connection_; std::vector remote_candidates_; bool sort_dirty_; // indicates whether another sort is needed right now bool had_connection_ = false; // if connections_ has ever been nonempty typedef std::map OptionMap; OptionMap options_; - std::string ice_ufrag_; - std::string ice_pwd_; + IceParameters ice_parameters_; std::vector remote_ice_parameters_; IceMode remote_ice_mode_; IceRole ice_role_; @@ -328,9 +375,17 @@ class P2PTransportChannel : public TransportChannelImpl, int check_receiving_interval_; int64_t last_ping_sent_ms_ = 0; int weak_ping_interval_ = WEAK_PING_INTERVAL; - TransportChannelState state_ = TransportChannelState::STATE_INIT; + IceTransportState state_ = IceTransportState::STATE_INIT; IceConfig config_; int last_sent_packet_id_ = -1; // -1 indicates no packet was sent before. + bool started_pinging_ = false; + // The value put in the "nomination" attribute for the next nominated + // connection. A zero-value indicates the connection will not be nominated. + uint32_t nomination_ = 0; + bool receiving_ = false; + bool writable_ = false; + + webrtc::MetricsObserverInterface* metrics_observer_ = nullptr; RTC_DISALLOW_COPY_AND_ASSIGN(P2PTransportChannel); }; diff --git a/include/webrtc/p2p/base/packetsocketfactory.h b/include/webrtc/p2p/base/packetsocketfactory.h index 290d9ca..c3b2417 100644 --- a/include/webrtc/p2p/base/packetsocketfactory.h +++ b/include/webrtc/p2p/base/packetsocketfactory.h @@ -22,9 +22,15 @@ class AsyncResolverInterface; class PacketSocketFactory { public: enum Options { - OPT_SSLTCP = 0x01, // Pseudo-TLS. - OPT_TLS = 0x02, OPT_STUN = 0x04, + + // The TLS options below are mutually exclusive. + OPT_TLS = 0x02, // Real and secure TLS. + OPT_TLS_FAKE = 0x01, // Fake TLS with a dummy SSL handshake. + OPT_TLS_INSECURE = 0x08, // Insecure TLS without certificate validation. + + // Deprecated, use OPT_TLS_FAKE. + OPT_SSLTCP = OPT_TLS_FAKE, }; PacketSocketFactory() { } diff --git a/include/webrtc/p2p/base/packettransportinterface.h b/include/webrtc/p2p/base/packettransportinterface.h new file mode 100644 index 0000000..05ca746 --- /dev/null +++ b/include/webrtc/p2p/base/packettransportinterface.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This exists for backwards compatibility with chromium remoting code that +// uses it. +// TODO(deadbeef): Update chromium and remove this file. + +#ifndef WEBRTC_P2P_BASE_PACKETTRANSPORTINTERFACE_H_ +#define WEBRTC_P2P_BASE_PACKETTRANSPORTINTERFACE_H_ + +#include "webrtc/p2p/base/packettransportinternal.h" + +namespace rtc { +typedef PacketTransportInternal PacketTransportInterface; +} + +#endif diff --git a/include/webrtc/p2p/base/packettransportinternal.h b/include/webrtc/p2p/base/packettransportinternal.h new file mode 100644 index 0000000..325c00e --- /dev/null +++ b/include/webrtc/p2p/base/packettransportinternal.h @@ -0,0 +1,95 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_PACKETTRANSPORTINTERNAL_H_ +#define WEBRTC_P2P_BASE_PACKETTRANSPORTINTERNAL_H_ + +#include +#include + +// This is included for PacketOptions. +#include "webrtc/base/asyncpacketsocket.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/socket.h" + +namespace cricket { +class TransportChannel; +} + +namespace rtc { +struct PacketOptions; +struct PacketTime; +struct SentPacket; + +class PacketTransportInternal : public sigslot::has_slots<> { + public: + // Identify the object for logging and debug purpose. + virtual std::string debug_name() const = 0; + + // The transport has been established. + virtual bool writable() const = 0; + + // The transport has received a packet in the last X milliseconds, here X is + // configured by each implementation. + virtual bool receiving() const = 0; + + // Attempts to send the given packet. + // The return value is < 0 on failure. The return value in failure case is not + // descriptive. Depending on failure cause and implementation details + // GetError() returns an descriptive errno.h error value. + // This mimics posix socket send() or sendto() behavior. + // TODO(johan): Reliable, meaningful, consistent error codes for all + // implementations would be nice. + // TODO(johan): Remove the default argument once channel code is updated. + virtual int SendPacket(const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags = 0) = 0; + + // Sets a socket option. Note that not all options are + // supported by all transport types. + virtual int SetOption(rtc::Socket::Option opt, int value) = 0; + + // TODO(pthatcher): Once Chrome's MockPacketTransportInterface implements + // this, remove the default implementation. + virtual bool GetOption(rtc::Socket::Option opt, int* value) { return false; } + + // Returns the most recent error that occurred on this channel. + virtual int GetError() = 0; + + // Emitted when the writable state, represented by |writable()|, changes. + sigslot::signal1 SignalWritableState; + + // Emitted when the PacketTransportInternal is ready to send packets. "Ready + // to send" is more sensitive than the writable state; a transport may be + // writable, but temporarily not able to send packets. For example, the + // underlying transport's socket buffer may be full, as indicated by + // SendPacket's return code and/or GetError. + sigslot::signal1 SignalReadyToSend; + + // Emitted when receiving state changes to true. + sigslot::signal1 SignalReceivingState; + + // Signalled each time a packet is received on this channel. + sigslot::signal5 + SignalReadPacket; + + // Signalled each time a packet is sent on this channel. + sigslot::signal2 + SignalSentPacket; +}; + +} // namespace rtc + +#endif // WEBRTC_P2P_BASE_PACKETTRANSPORTINTERNAL_H_ diff --git a/include/webrtc/p2p/base/port.h b/include/webrtc/p2p/base/port.h index 937f3cd..4d15656 100644 --- a/include/webrtc/p2p/base/port.h +++ b/include/webrtc/p2p/base/port.h @@ -19,13 +19,15 @@ #include "webrtc/p2p/base/candidate.h" #include "webrtc/p2p/base/candidatepairinterface.h" +#include "webrtc/p2p/base/jseptransport.h" #include "webrtc/p2p/base/packetsocketfactory.h" #include "webrtc/p2p/base/portinterface.h" #include "webrtc/p2p/base/stun.h" #include "webrtc/p2p/base/stunrequest.h" -#include "webrtc/p2p/base/transport.h" #include "webrtc/base/asyncpacketsocket.h" +#include "webrtc/base/checks.h" #include "webrtc/base/network.h" +#include "webrtc/base/optional.h" #include "webrtc/base/proxyinfo.h" #include "webrtc/base/ratetracker.h" #include "webrtc/base/sigslot.h" @@ -45,6 +47,7 @@ extern const char RELAY_PORT_TYPE[]; extern const char UDP_PROTOCOL_NAME[]; extern const char TCP_PROTOCOL_NAME[]; extern const char SSLTCP_PROTOCOL_NAME[]; +extern const char TLS_PROTOCOL_NAME[]; // RFC 6544, TCP candidate encoding rules. extern const int DISCARD_PORT; @@ -70,7 +73,10 @@ static const int CONNECTION_WRITE_TIMEOUT = 15 * 1000; // 15 seconds static const int CONNECTION_WRITE_CONNECT_TIMEOUT = 5 * 1000; // 5 seconds // This is the length of time that we wait for a ping response to come back. -static const int CONNECTION_RESPONSE_TIMEOUT = 5 * 1000; // 5 seconds +// There is no harm to keep this value high other than a small amount +// of increased memory. But in some networks (2G), +// we observe up to 60s RTTs. +static const int CONNECTION_RESPONSE_TIMEOUT = 60 * 1000; // 60 seconds // The number of pings that must fail to respond before we become unwritable. static const uint32_t CONNECTION_WRITE_CONNECT_FAILURES = 5; @@ -81,35 +87,38 @@ enum RelayType { }; enum IcePriorityValue { - // The reason we are choosing Relay preference 2 is because, we can run - // Relay from client to server on UDP/TCP/TLS. To distinguish the transport - // protocol, we prefer UDP over TCP over TLS. - // For UDP ICE_TYPE_PREFERENCE_RELAY will be 2. - // For TCP ICE_TYPE_PREFERENCE_RELAY will be 1. - // For TLS ICE_TYPE_PREFERENCE_RELAY will be 0. - // Check turnport.cc for setting these values. - ICE_TYPE_PREFERENCE_RELAY = 2, + ICE_TYPE_PREFERENCE_RELAY_TLS = 0, + ICE_TYPE_PREFERENCE_RELAY_TCP = 1, + ICE_TYPE_PREFERENCE_RELAY_UDP = 2, + ICE_TYPE_PREFERENCE_PRFLX_TCP = 80, ICE_TYPE_PREFERENCE_HOST_TCP = 90, ICE_TYPE_PREFERENCE_SRFLX = 100, ICE_TYPE_PREFERENCE_PRFLX = 110, ICE_TYPE_PREFERENCE_HOST = 126 }; +// States are from RFC 5245. http://tools.ietf.org/html/rfc5245#section-5.7.4 +enum class IceCandidatePairState { + WAITING = 0, // Check has not been performed, Waiting pair on CL. + IN_PROGRESS, // Check has been sent, transaction is in progress. + SUCCEEDED, // Check already done, produced a successful result. + FAILED, // Check for this connection failed. + // According to spec there should also be a frozen state, but nothing is ever + // frozen because we have not implemented ICE freezing logic. +}; + const char* ProtoToString(ProtocolType proto); bool StringToProto(const char* value, ProtocolType* proto); struct ProtocolAddress { rtc::SocketAddress address; ProtocolType proto; - bool secure; ProtocolAddress(const rtc::SocketAddress& a, ProtocolType p) - : address(a), proto(p), secure(false) { } - ProtocolAddress(const rtc::SocketAddress& a, ProtocolType p, bool sec) - : address(a), proto(p), secure(sec) { } + : address(a), proto(p) {} bool operator==(const ProtocolAddress& o) const { - return address == o.address && proto == o.proto && secure == o.secure; + return address == o.address && proto == o.proto; } bool operator!=(const ProtocolAddress& o) const { return !(*this == o); } }; @@ -122,7 +131,14 @@ typedef std::set ServerAddresses; class Port : public PortInterface, public rtc::MessageHandler, public sigslot::has_slots<> { public: + // INIT: The state when a port is just created. + // KEEP_ALIVE_UNTIL_PRUNED: A port should not be destroyed even if no + // connection is using it. + // PRUNED: It will be destroyed if no connection is using it for a period of + // 30 seconds. + enum class State { INIT, KEEP_ALIVE_UNTIL_PRUNED, PRUNED }; Port(rtc::Thread* thread, + const std::string& type, rtc::PacketSocketFactory* factory, rtc::Network* network, const rtc::IPAddress& ip, @@ -152,6 +168,12 @@ class Port : public PortInterface, public rtc::MessageHandler, virtual bool SharedSocket() const { return shared_socket_; } void ResetSharedSocket() { shared_socket_ = false; } + // Should not destroy the port even if no connection is using it. Called when + // a port is ready to use. + void KeepAliveUntilPruned(); + // Allows a port to be destroyed if no connection is using it. + void Prune(); + // The thread on which this port performs its I/O. rtc::Thread* thread() { return thread_; } @@ -178,7 +200,7 @@ class Port : public PortInterface, public rtc::MessageHandler, } // Identifies the generation that this port was created in. - uint32_t generation() { return generation_; } + uint32_t generation() const { return generation_; } void set_generation(uint32_t generation) { generation_ = generation; } const std::string username_fragment() const; @@ -230,7 +252,7 @@ class Port : public PortInterface, public rtc::MessageHandler, rtc::AsyncPacketSocket* socket, const char* data, size_t size, const rtc::SocketAddress& remote_addr, const rtc::PacketTime& packet_time) { - ASSERT(false); + RTC_NOTREACHED(); return false; } @@ -293,19 +315,28 @@ class Port : public PortInterface, public rtc::MessageHandler, // Returns the index of the new local candidate. size_t AddPrflxCandidate(const Candidate& local); - void set_candidate_filter(uint32_t candidate_filter) { - candidate_filter_ = candidate_filter; - } int16_t network_cost() const { return network_cost_; } protected: - enum { - MSG_DEAD = 0, - MSG_FIRST_AVAILABLE - }; + enum { MSG_DESTROY_IF_DEAD = 0, MSG_FIRST_AVAILABLE }; + + virtual void UpdateNetworkCost(); void set_type(const std::string& type) { type_ = type; } + // Deprecated. Use the AddAddress() method below with "url" instead. + // TODO(zhihuang): Remove this after downstream applications stop using it. + void AddAddress(const rtc::SocketAddress& address, + const rtc::SocketAddress& base_address, + const rtc::SocketAddress& related_address, + const std::string& protocol, + const std::string& relay_protocol, + const std::string& tcptype, + const std::string& type, + uint32_t type_preference, + uint32_t relay_preference, + bool final); + void AddAddress(const rtc::SocketAddress& address, const rtc::SocketAddress& base_address, const rtc::SocketAddress& related_address, @@ -315,10 +346,13 @@ class Port : public PortInterface, public rtc::MessageHandler, const std::string& type, uint32_t type_preference, uint32_t relay_preference, + const std::string& url, bool final); - // Adds the given connection to the list. (Deleting removes them.) - void AddConnection(Connection* conn); + // Adds the given connection to the map keyed by the remote candidate address. + // If an existing connection has the same address, the existing one will be + // replaced and destroyed. + void AddOrReplaceConnection(Connection* conn); // Called when a packet is received from an unknown address that is not // currently a connection. If this is an authenticated STUN binding request, @@ -347,20 +381,15 @@ class Port : public PortInterface, public rtc::MessageHandler, return rtc::DSCP_NO_CHANGE; } - uint32_t candidate_filter() { return candidate_filter_; } + // Extra work to be done in subclasses when a connection is destroyed. + virtual void HandleConnectionDestroyed(Connection* conn) {} private: void Construct(); // Called when one of our connections deletes itself. void OnConnectionDestroyed(Connection* conn); - // Whether this port is dead, and hence, should be destroyed on the controlled - // side. - bool dead() const { - return ice_role_ == ICEROLE_CONTROLLED && connections_.empty(); - } - - void OnNetworkInactive(const rtc::Network* network); + void OnNetworkTypeChanged(const rtc::Network* network); rtc::Thread* thread_; rtc::PacketSocketFactory* factory_; @@ -394,16 +423,12 @@ class Port : public PortInterface, public rtc::MessageHandler, std::string user_agent_; rtc::ProxyInfo proxy_; - // Candidate filter is pushed down to Port such that each Port could - // make its own decision on how to create candidates. For example, - // when IceTransportsType is set to relay, both RelayPort and - // TurnPort will hide raddr to avoid local address leakage. - uint32_t candidate_filter_; - // A virtual cost perceived by the user, usually based on the network type // (WiFi. vs. Cellular). It takes precedence over the priority when // comparing two connections. uint16_t network_cost_; + State state_ = State::INIT; + int64_t last_time_all_connections_removed_ = 0; friend class Connection; }; @@ -415,19 +440,12 @@ class Connection : public CandidatePairInterface, public sigslot::has_slots<> { public: struct SentPing { - SentPing(const std::string id, int64_t sent_time) - : id(id), sent_time(sent_time) {} + SentPing(const std::string id, int64_t sent_time, uint32_t nomination) + : id(id), sent_time(sent_time), nomination(nomination) {} std::string id; int64_t sent_time; - }; - - // States are from RFC 5245. http://tools.ietf.org/html/rfc5245#section-5.7.4 - enum State { - STATE_WAITING = 0, // Check has not been performed, Waiting pair on CL. - STATE_INPROGRESS, // Check has been sent, transaction is in progress. - STATE_SUCCEEDED, // Check already done, produced a successful result. - STATE_FAILED // Check for this connection failed. + uint32_t nomination; }; virtual ~Connection(); @@ -463,20 +481,17 @@ class Connection : public CandidatePairInterface, bool active() const { return write_state_ != STATE_WRITE_TIMEOUT; } + // A connection is dead if it can be safely deleted. bool dead(int64_t now) const; // Estimate of the round-trip time over this connection. int rtt() const { return rtt_; } - size_t sent_total_bytes(); - size_t sent_bytes_second(); - // Used to track how many packets are discarded in the application socket due - // to errors. - size_t sent_discarded_packets(); - size_t sent_total_packets(); - size_t recv_total_bytes(); - size_t recv_bytes_second(); + // Gets the |ConnectionInfo| stats, where |best_connection| has not been + // populated (default value false). + ConnectionInfo stats(); + sigslot::signal1 SignalStateChange; // Sent when the connection has decided that it is no longer of value. It @@ -514,14 +529,29 @@ class Connection : public CandidatePairInterface, bool use_candidate_attr() const { return use_candidate_attr_; } void set_use_candidate_attr(bool enable); - bool nominated() const { return nominated_; } - void set_nominated(bool nominated) { nominated_ = nominated; } + void set_nomination(uint32_t value) { nomination_ = value; } + + uint32_t remote_nomination() const { return remote_nomination_; } + // One or several pairs may be nominated based on if Regular or Aggressive + // Nomination is used. https://tools.ietf.org/html/rfc5245#section-8 + // |nominated| is defined both for the controlling or controlled agent based + // on if a nomination has been pinged or acknowledged. The controlled agent + // gets its |remote_nomination_| set when pinged by the controlling agent with + // a nomination value. The controlling agent gets its |acked_nomination_| set + // when receiving a response to a nominating ping. + bool nominated() const { return acked_nomination_ || remote_nomination_; } + // Public for unit tests. + void set_remote_nomination(uint32_t remote_nomination) { + remote_nomination_ = remote_nomination; + } + // Public for unit tests. + uint32_t acked_nomination() const { return acked_nomination_; } void set_remote_ice_mode(IceMode mode) { remote_ice_mode_ = mode; } - void set_receiving_timeout(int64_t receiving_timeout_ms) { + void set_receiving_timeout(int receiving_timeout_ms) { receiving_timeout_ = receiving_timeout_ms; } @@ -531,6 +561,10 @@ class Connection : public CandidatePairInterface, // Makes the connection go away, in a failed state. void FailAndDestroy(); + // Prunes the connection and sets its state to STATE_FAILED, + // It will not be used or send pings although it can still receive packets. + void FailAndPrune(); + // Checks that the state of this connection is up-to-date. The argument is // the current time, which is compared against various timeouts. void UpdateState(int64_t now); @@ -538,10 +572,12 @@ class Connection : public CandidatePairInterface, // Called when this connection should try checking writability again. int64_t last_ping_sent() const { return last_ping_sent_; } void Ping(int64_t now); - void ReceivedPingResponse(); + void ReceivedPingResponse(int rtt, const std::string& request_id); int64_t last_ping_response_received() const { return last_ping_response_received_; } + // Used to check if any STUN ping response has been received. + int rtt_samples() const { return rtt_samples_; } // Called whenever a valid ping is received on this connection. This is // public because the connection intercepts the first ping for us. @@ -550,6 +586,8 @@ class Connection : public CandidatePairInterface, // Handles the binding request; sends a response if this is a valid request. void HandleBindingRequest(IceMessage* msg); + int64_t last_data_received() const { return last_data_received_; } + // Debugging description of this connection std::string ToDebugId() const; std::string ToString() const; @@ -567,20 +605,19 @@ class Connection : public CandidatePairInterface, // Invoked when Connection receives STUN error response with 487 code. void HandleRoleConflictFromPeer(); - State state() const { return state_; } + IceCandidatePairState state() const { return state_; } + + int num_pings_sent() const { return num_pings_sent_; } IceMode remote_ice_mode() const { return remote_ice_mode_; } uint32_t ComputeNetworkCost() const; - // Update the ICE password and/or generation of the remote candidate if a - // ufrag in |remote_ice_parameters| matches the candidate's ufrag, and the + // Update the ICE password and/or generation of the remote candidate if the + // ufrag in |params| matches the candidate's ufrag, and the // candidate's password and/or ufrag has not been set. - // |remote_ice_parameters| should be a list of known ICE parameters ordered - // by generation. - void MaybeSetRemoteIceCredentialsAndGeneration(const std::string& ice_ufrag, - const std::string& ice_pwd, - int generation); + void MaybeSetRemoteIceParametersAndGeneration(const IceParameters& params, + int generation); // If |remote_candidate_| is peer reflexive and is equivalent to // |new_candidate| except the type, update |remote_candidate_| to @@ -590,6 +627,12 @@ class Connection : public CandidatePairInterface, // Returns the last received time of any data, stun request, or stun // response in milliseconds int64_t last_received() const; + // Returns the last time when the connection changed its receiving state. + int64_t receiving_unchanged_since() const { + return receiving_unchanged_since_; + } + + bool stable(int64_t now) const; protected: enum { MSG_DELETE = 0, MSG_FIRST_AVAILABLE }; @@ -608,17 +651,36 @@ class Connection : public CandidatePairInterface, void OnConnectionRequestTimeout(ConnectionRequest* req); void OnConnectionRequestSent(ConnectionRequest* req); + bool rtt_converged() const; + + // If the response is not received within 2 * RTT, the response is assumed to + // be missing. + bool missing_responses(int64_t now) const; + // Changes the state and signals if necessary. void set_write_state(WriteState value); - void set_receiving(bool value); - void set_state(State state); + void UpdateReceiving(int64_t now); + void set_state(IceCandidatePairState state); void set_connected(bool value); + uint32_t nomination() const { return nomination_; } + void OnMessage(rtc::Message *pmsg); Port* port_; size_t local_candidate_index_; Candidate remote_candidate_; + + ConnectionInfo stats_; + rtc::RateTracker recv_rate_tracker_; + rtc::RateTracker send_rate_tracker_; + + private: + // Update the local candidate based on the mapped address attribute. + // If the local candidate changed, fires SignalStateChange. + void MaybeUpdateLocalCandidate(ConnectionRequest* request, + StunMessage* response); + WriteState write_state_; bool receiving_; bool connected_; @@ -628,33 +690,41 @@ class Connection : public CandidatePairInterface, // But when peer is ice-lite, this flag "must" be initialized to false and // turn on when connection becomes "best connection". bool use_candidate_attr_; - // Whether this connection has been nominated by the controlling side via - // the use_candidate attribute. - bool nominated_; + // Used by the controlling side to indicate that this connection will be + // selected for transmission if the peer supports ICE-renomination when this + // value is positive. A larger-value indicates that a connection is nominated + // later and should be selected by the controlled side with higher precedence. + // A zero-value indicates not nominating this connection. + uint32_t nomination_ = 0; + // The last nomination that has been acknowledged. + uint32_t acked_nomination_ = 0; + // Used by the controlled side to remember the nomination value received from + // the controlling side. When the peer does not support ICE re-nomination, + // its value will be 1 if the connection has been nominated. + uint32_t remote_nomination_ = 0; + IceMode remote_ice_mode_; StunRequestManager requests_; int rtt_; + int rtt_samples_ = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime + uint64_t total_round_trip_time_ms_ = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime + rtc::Optional current_round_trip_time_ms_; int64_t last_ping_sent_; // last time we sent a ping to the other side int64_t last_ping_received_; // last time we received a ping from the other // side int64_t last_data_received_; int64_t last_ping_response_received_; + int64_t receiving_unchanged_since_ = 0; std::vector pings_since_last_response_; - rtc::RateTracker recv_rate_tracker_; - rtc::RateTracker send_rate_tracker_; - uint32_t sent_packets_discarded_; - uint32_t sent_packets_total_; - - private: - void MaybeAddPrflxCandidate(ConnectionRequest* request, - StunMessage* response); - bool reported_; - State state_; + IceCandidatePairState state_; // Time duration to switch from receiving to not receiving. int receiving_timeout_; int64_t time_created_ms_; + int num_pings_sent_ = 0; friend class Port; friend class ConnectionRequest; diff --git a/include/webrtc/p2p/base/portallocator.h b/include/webrtc/p2p/base/portallocator.h index 8796570..5147429 100644 --- a/include/webrtc/p2p/base/portallocator.h +++ b/include/webrtc/p2p/base/portallocator.h @@ -23,6 +23,10 @@ #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" +namespace webrtc { +class MetricsObserverInterface; +} + namespace cricket { // PortAllocator is responsible for allocating Port types for a given @@ -40,7 +44,6 @@ enum { // Disable local TCP ports. This doesn't impact how we connect to relay // servers. PORTALLOCATOR_DISABLE_TCP = 0x08, - PORTALLOCATOR_ENABLE_SHAKER = 0x10, PORTALLOCATOR_ENABLE_IPV6 = 0x40, // TODO(pthatcher): Remove this once it's no longer used in: // remoting/client/plugin/pepper_port_allocator.cc @@ -61,8 +64,21 @@ enum { // Disallow use of UDP when connecting to a relay server. Since proxy servers // usually don't handle UDP, using UDP will leak the IP address. PORTALLOCATOR_DISABLE_UDP_RELAY = 0x1000, + + // When multiple networks exist, do not gather candidates on the ones with + // high cost. So if both Wi-Fi and cellular networks exist, gather only on the + // Wi-Fi network. If a network type is "unknown", it has a cost lower than + // cellular but higher than Wi-Fi/Ethernet. So if an unknown network exists, + // cellular networks will not be used to gather candidates and if a Wi-Fi + // network is present, "unknown" networks will not be usd to gather + // candidates. Doing so ensures that even if a cellular network type was not + // detected initially, it would not be used if a Wi-Fi network is present. + PORTALLOCATOR_DISABLE_COSTLY_NETWORKS = 0x2000, }; +// Defines various reasons that have caused ICE regathering. +enum class IceRegatheringReason { NETWORK_CHANGE, NETWORK_FAILURE, MAX_VALUE }; + const uint32_t kDefaultPortAllocatorFlags = 0; const uint32_t kDefaultStepDelay = 1000; // 1 sec step delay. @@ -79,6 +95,17 @@ enum { CF_ALL = 0x7, }; +// TLS certificate policy. +enum class TlsCertPolicy { + // For TLS based protocols, ensure the connection is secure by not + // circumventing certificate validation. + TLS_CERT_POLICY_SECURE, + // For TLS based protocols, disregard security completely by skipping + // certificate validation. This is insecure and should never be used unless + // security is irrelevant in that particular context. + TLS_CERT_POLICY_INSECURE_NO_CHECK, +}; + // TODO(deadbeef): Rename to TurnCredentials (and username to ufrag). struct RelayCredentials { RelayCredentials() {} @@ -103,13 +130,24 @@ struct RelayServerConfig { int port, const std::string& username, const std::string& password, - ProtocolType proto, - bool secure) + ProtocolType proto) : type(RELAY_TURN), credentials(username, password) { - ports.push_back( - ProtocolAddress(rtc::SocketAddress(address, port), proto, secure)); + ports.push_back(ProtocolAddress(rtc::SocketAddress(address, port), proto)); } + // Legacy constructor where "secure" and PROTO_TCP implies PROTO_TLS. + RelayServerConfig(const std::string& address, + int port, + const std::string& username, + const std::string& password, + ProtocolType proto, + bool secure) + : RelayServerConfig(address, + port, + username, + password, + (proto == PROTO_TCP && secure ? PROTO_TLS : proto)) {} + bool operator==(const RelayServerConfig& o) const { return type == o.type && ports == o.ports && credentials == o.credentials && priority == o.priority; @@ -120,6 +158,7 @@ struct RelayServerConfig { PortList ports; RelayCredentials credentials; int priority = 0; + TlsCertPolicy tls_cert_policy = TlsCertPolicy::TLS_CERT_POLICY_SECURE; }; class PortAllocatorSession : public sigslot::has_slots<> { @@ -142,14 +181,45 @@ class PortAllocatorSession : public sigslot::has_slots<> { const std::string& ice_pwd() const { return ice_pwd_; } bool pooled() const { return ice_ufrag_.empty(); } - // Starts gathering STUN and Relay configurations. + // Setting this filter should affect not only candidates gathered in the + // future, but candidates already gathered and ports already "ready", + // which would be returned by ReadyCandidates() and ReadyPorts(). + // + // Default filter should be CF_ALL. + virtual void SetCandidateFilter(uint32_t filter) = 0; + + // Starts gathering ports and ICE candidates. virtual void StartGettingPorts() = 0; + // Completely stops gathering. Will not gather again unless StartGettingPorts + // is called again. virtual void StopGettingPorts() = 0; - // Only stop the existing gathering process but may start new ones if needed. - virtual void ClearGettingPorts() = 0; - // Whether the process of getting ports has been stopped. + // Whether the session is actively getting ports. virtual bool IsGettingPorts() = 0; + // + // NOTE: The group of methods below is only used for continual gathering. + // + + // ClearGettingPorts should have the same immediate effect as + // StopGettingPorts, but if the implementation supports continual gathering, + // ClearGettingPorts allows additional ports/candidates to be gathered if the + // network conditions change. + virtual void ClearGettingPorts() = 0; + // Whether it is in the state where the existing gathering process is stopped, + // but new ones may be started (basically after calling ClearGettingPorts). + virtual bool IsCleared() const { return false; } + // Whether the session has completely stopped. + virtual bool IsStopped() const { return false; } + // Re-gathers candidates on networks that do not have any connections. More + // precisely, a network interface may have more than one IP addresses (e.g., + // IPv4 and IPv6 addresses). Each address subnet will be used to create a + // network. Only if all networks of an interface have no connection, the + // implementation should start re-gathering on all networks of that interface. + virtual void RegatherOnFailedNetworks() {} + // Re-gathers candidates on all networks. + // TODO(honghaiz): Implement this in BasicPortAllocator. + virtual void RegatherOnAllNetworks() {} + // Another way of getting the information provided by the signals below. // // Ports and candidates are not guaranteed to be in the same order as the @@ -157,12 +227,28 @@ class PortAllocatorSession : public sigslot::has_slots<> { virtual std::vector ReadyPorts() const = 0; virtual std::vector ReadyCandidates() const = 0; virtual bool CandidatesAllocationDone() const = 0; + // Marks all ports in the current session as "pruned" so that they may be + // destroyed if no connection is using them. + virtual void PruneAllPorts() {} sigslot::signal2 SignalPortReady; + // Fires this signal when the network of the ports failed (either because the + // interface is down, or because there is no connection on the interface), + // or when TURN ports are pruned because a higher-priority TURN port becomes + // ready(pairable). + sigslot::signal2&> + SignalPortsPruned; sigslot::signal2&> SignalCandidatesReady; + // Candidates should be signaled to be removed when the port that generated + // the candidates is removed. + sigslot::signal2&> + SignalCandidatesRemoved; sigslot::signal1 SignalCandidatesAllocationDone; + sigslot::signal2 + SignalIceRegathering; + virtual uint32_t generation() { return generation_; } virtual void set_generation(uint32_t generation) { generation_ = generation; } sigslot::signal1 SignalDestroyed; @@ -205,8 +291,12 @@ class PortAllocatorSession : public sigslot::has_slots<> { friend class PortAllocator; }; -// Note that this class should only be used on one thread. -// This includes calling the destructor. +// Every method of PortAllocator (including the destructor) must be called on +// the same thread, except for the constructor which may be called on any +// thread. +// +// This allows constructing a PortAllocator subclass on one thread and +// passing it into an object that uses it on a different thread. class PortAllocator : public sigslot::has_slots<> { public: PortAllocator() : @@ -216,10 +306,13 @@ class PortAllocator : public sigslot::has_slots<> { step_delay_(kDefaultStepDelay), allow_tcp_listen_(true), candidate_filter_(CF_ALL) { - // This will allow us to have old behavior on non webrtc clients. } virtual ~PortAllocator() {} + // This should be called on the PortAllocator's thread before the + // PortAllocator is used. Subclasses may override this if necessary. + virtual void Initialize() {} + // Set STUN and TURN servers to be used in future sessions, and set // candidate pool size, as described in JSEP. // @@ -228,9 +321,12 @@ class PortAllocator : public sigslot::has_slots<> { // // If the servers are not changing but the candidate pool size is, // pooled sessions will be either created or destroyed as necessary. - void SetConfiguration(const ServerAddresses& stun_servers, + // + // Returns true if the configuration could successfully be changed. + bool SetConfiguration(const ServerAddresses& stun_servers, const std::vector& turn_servers, - int candidate_pool_size); + int candidate_pool_size, + bool prune_turn_ports); const ServerAddresses& stun_servers() const { return stun_servers_; } @@ -238,7 +334,7 @@ class PortAllocator : public sigslot::has_slots<> { return turn_servers_; } - int candidate_pool_size() const { return target_pooled_session_count_; } + int candidate_pool_size() const { return candidate_pool_size_; } // Sets the network types to ignore. // Values are defined by the AdapterType enum. @@ -248,7 +344,6 @@ class PortAllocator : public sigslot::has_slots<> { virtual void SetNetworkIgnoreMask(int network_ignore_mask) = 0; std::unique_ptr CreateSession( - const std::string& sid, const std::string& content_name, int component, const std::string& ice_ufrag, @@ -301,14 +396,19 @@ class PortAllocator : public sigslot::has_slots<> { uint32_t candidate_filter() { return candidate_filter_; } void set_candidate_filter(uint32_t filter) { - // TODO(mallinath) - Do transition check? candidate_filter_ = filter; } + bool prune_turn_ports() const { return prune_turn_ports_; } + // Gets/Sets the Origin value used for WebRTC STUN requests. const std::string& origin() const { return origin_; } void set_origin(const std::string& origin) { origin_ = origin; } + void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) { + metrics_observer_ = observer; + } + protected: virtual PortAllocatorSession* CreateSessionInternal( const std::string& content_name, @@ -316,6 +416,14 @@ class PortAllocator : public sigslot::has_slots<> { const std::string& ice_ufrag, const std::string& ice_pwd) = 0; + webrtc::MetricsObserverInterface* metrics_observer() { + return metrics_observer_; + } + + const std::deque>& pooled_sessions() { + return pooled_sessions_; + } + uint32_t flags_; std::string agent_; rtc::ProxyInfo proxy_; @@ -329,12 +437,11 @@ class PortAllocator : public sigslot::has_slots<> { private: ServerAddresses stun_servers_; std::vector turn_servers_; - // The last size passed into SetConfiguration. - int target_pooled_session_count_ = 0; - // This variable represents the total number of pooled sessions - // both owned by this class and taken by TakePooledSession. - int allocated_pooled_session_count_ = 0; + int candidate_pool_size_ = 0; // Last value passed into SetConfiguration. std::deque> pooled_sessions_; + bool prune_turn_ports_ = false; + + webrtc::MetricsObserverInterface* metrics_observer_ = nullptr; }; } // namespace cricket diff --git a/include/webrtc/p2p/base/portinterface.h b/include/webrtc/p2p/base/portinterface.h index e738619..4a6e900 100644 --- a/include/webrtc/p2p/base/portinterface.h +++ b/include/webrtc/p2p/base/portinterface.h @@ -13,9 +13,9 @@ #include -#include "webrtc/p2p/base/transport.h" #include "webrtc/base/asyncpacketsocket.h" #include "webrtc/base/socketaddress.h" +#include "webrtc/p2p/base/jseptransport.h" namespace rtc { class Network; @@ -30,8 +30,9 @@ class StunMessage; enum ProtocolType { PROTO_UDP, PROTO_TCP, - PROTO_SSLTCP, - PROTO_LAST = PROTO_SSLTCP + PROTO_SSLTCP, // Pseudo-TLS. + PROTO_TLS, + PROTO_LAST = PROTO_TLS }; // Defines the interface for a port, which represents a local communication @@ -76,6 +77,8 @@ class PortInterface { virtual int GetOption(rtc::Socket::Option opt, int* value) = 0; virtual int GetError() = 0; + virtual ProtocolType GetProtocol() const = 0; + virtual const std::vector& Candidates() const = 0; // Sends the given packet to the given address, provided that the address is @@ -104,9 +107,6 @@ class PortInterface { // any usefulness. sigslot::signal1 SignalDestroyed; - // Signaled when the network used by this port becomes inactive. - sigslot::signal1 SignalNetworkInactive; - // Signaled when Port discovers ice role conflict with the peer. sigslot::signal1 SignalRoleConflict; diff --git a/include/webrtc/p2p/base/rawtransport.h b/include/webrtc/p2p/base/rawtransport.h deleted file mode 100644 index cb700ae..0000000 --- a/include/webrtc/p2p/base/rawtransport.h +++ /dev/null @@ -1,2 +0,0 @@ -// TODO(pthatcher): Remove this file once Chrome's build files no -// longer refer to it. diff --git a/include/webrtc/p2p/base/rawtransportchannel.h b/include/webrtc/p2p/base/rawtransportchannel.h deleted file mode 100644 index cb700ae..0000000 --- a/include/webrtc/p2p/base/rawtransportchannel.h +++ /dev/null @@ -1,2 +0,0 @@ -// TODO(pthatcher): Remove this file once Chrome's build files no -// longer refer to it. diff --git a/include/webrtc/p2p/base/relayport.h b/include/webrtc/p2p/base/relayport.h index 402736c..8fa2235 100644 --- a/include/webrtc/p2p/base/relayport.h +++ b/include/webrtc/p2p/base/relayport.h @@ -68,6 +68,12 @@ class RelayPort : public Port { const ProtocolAddress * ServerAddress(size_t index) const; bool IsReady() { return ready_; } + ProtocolType GetProtocol() const override { + // We shouldn't be using RelayPort, but we need to provide an + // implementation here. + return PROTO_UDP; + } + // Used for testing. sigslot::signal1 SignalConnectFailure; sigslot::signal1 SignalSoftTimeout; diff --git a/include/webrtc/p2p/base/relayserver.h b/include/webrtc/p2p/base/relayserver.h index 7ee71d9..c60e271 100644 --- a/include/webrtc/p2p/base/relayserver.h +++ b/include/webrtc/p2p/base/relayserver.h @@ -115,7 +115,7 @@ class RelayServer : public rtc::MessageHandler, void RemoveConnection(RelayServerConnection* conn); void RemoveBinding(RelayServerBinding* binding); - // Handle messages in our worker thread. + // Handle messages in our thread. void OnMessage(rtc::Message *pmsg); // Called when the timer for checking lifetime times out. diff --git a/include/webrtc/p2p/base/sessiondescription.h b/include/webrtc/p2p/base/sessiondescription.h index 7880167..a20f7b7 100644 --- a/include/webrtc/p2p/base/sessiondescription.h +++ b/include/webrtc/p2p/base/sessiondescription.h @@ -32,20 +32,31 @@ class ContentDescription { // name = name of // type = xmlns of struct ContentInfo { - ContentInfo() : description(NULL) {} + ContentInfo() {} ContentInfo(const std::string& name, const std::string& type, - ContentDescription* description) : - name(name), type(type), rejected(false), description(description) {} + ContentDescription* description) + : name(name), type(type), description(description) {} ContentInfo(const std::string& name, const std::string& type, bool rejected, ContentDescription* description) : name(name), type(type), rejected(rejected), description(description) {} + ContentInfo(const std::string& name, + const std::string& type, + bool rejected, + bool bundle_only, + ContentDescription* description) + : name(name), + type(type), + rejected(rejected), + bundle_only(bundle_only), + description(description) {} std::string name; std::string type; - bool rejected; - ContentDescription* description; + bool rejected = false; + bool bundle_only = false; + ContentDescription* description = nullptr; }; typedef std::vector ContentNames; @@ -127,6 +138,11 @@ class SessionDescription { const std::string& type, bool rejected, ContentDescription* description); + void AddContent(const std::string& name, + const std::string& type, + bool rejected, + bool bundle_only, + ContentDescription* description); bool RemoveContentByName(const std::string& name); // Transport accessors. diff --git a/include/webrtc/p2p/base/sessionid.h b/include/webrtc/p2p/base/sessionid.h deleted file mode 100644 index f695700..0000000 --- a/include/webrtc/p2p/base/sessionid.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_BASE_SESSIONID_H_ -#define WEBRTC_P2P_BASE_SESSIONID_H_ - -// TODO: Remove this file. - -namespace cricket { - -} // namespace cricket - -#endif // WEBRTC_P2P_BASE_SESSIONID_H_ diff --git a/include/webrtc/p2p/base/stun.h b/include/webrtc/p2p/base/stun.h index c0f5cfd..028787c 100644 --- a/include/webrtc/p2p/base/stun.h +++ b/include/webrtc/p2p/base/stun.h @@ -158,10 +158,8 @@ class StunMessage { const StunErrorCodeAttribute* GetErrorCode() const; const StunUInt16ListAttribute* GetUnknownAttributes() const; - // Takes ownership of the specified attribute, verifies it is of the correct - // type, and adds it to the message. The return value indicates whether this - // was successful. - bool AddAttribute(StunAttribute* attr); + // Takes ownership of the specified attribute and adds it to the message. + void AddAttribute(StunAttribute* attr); // Validates that a raw STUN message has a correct MESSAGE-INTEGRITY value. // This can't currently be done on a StunMessage, since it is affected by @@ -606,6 +604,7 @@ enum IceAttributeType { STUN_ATTR_USE_CANDIDATE = 0x0025, // No content, Length = 0 STUN_ATTR_ICE_CONTROLLED = 0x8029, // UInt64 STUN_ATTR_ICE_CONTROLLING = 0x802A, // UInt64 + STUN_ATTR_NOMINATION = 0xC001, // UInt32 // UInt32. The higher 16 bits are the network ID. The lower 16 bits are the // network cost. STUN_ATTR_NETWORK_INFO = 0xC057 @@ -624,6 +623,7 @@ class IceMessage : public StunMessage { switch (type) { case STUN_ATTR_PRIORITY: case STUN_ATTR_NETWORK_INFO: + case STUN_ATTR_NOMINATION: return STUN_VALUE_UINT32; case STUN_ATTR_USE_CANDIDATE: return STUN_VALUE_BYTE_STRING; case STUN_ATTR_ICE_CONTROLLED: return STUN_VALUE_UINT64; diff --git a/include/webrtc/p2p/base/stunport.h b/include/webrtc/p2p/base/stunport.h index cd844aa..1bbe25f 100644 --- a/include/webrtc/p2p/base/stunport.h +++ b/include/webrtc/p2p/base/stunport.h @@ -26,6 +26,11 @@ class SignalThread; namespace cricket { +// Lifetime chosen for STUN ports on low-cost networks. +static const int INFINITE_LIFETIME = -1; +// Lifetime for STUN ports on high-cost networks: 2 minutes +static const int HIGH_COST_PORT_KEEPALIVE_LIFETIME = 2 * 60 * 1000; + // Communicates using the address on the outside of a NAT. class UDPPort : public Port { public: @@ -75,8 +80,7 @@ class UDPPort : public Port { const ServerAddresses& server_addresses() const { return server_addresses_; } - void - set_server_addresses(const ServerAddresses& addresses) { + void set_server_addresses(const ServerAddresses& addresses) { server_addresses_ = addresses; } @@ -100,6 +104,8 @@ class UDPPort : public Port { return protocol == UDP_PROTOCOL_NAME; } + virtual ProtocolType GetProtocol() const { return PROTO_UDP; } + void set_stun_keepalive_delay(int delay) { stun_keepalive_delay_ = delay; } @@ -145,6 +151,8 @@ class UDPPort : public Port { const rtc::PacketOptions& options, bool payload); + virtual void UpdateNetworkCost(); + void OnLocalAddressReady(rtc::AsyncPacketSocket* socket, const rtc::SocketAddress& address); void OnReadPacket(rtc::AsyncPacketSocket* socket, @@ -219,6 +227,15 @@ class UDPPort : public Port { bool HasCandidateWithAddress(const rtc::SocketAddress& addr) const; + // If this is a low-cost network, it will keep on sending STUN binding + // requests indefinitely to keep the NAT binding alive. Otherwise, stop + // sending STUN binding requests after HIGH_COST_PORT_KEEPALIVE_LIFETIME. + int GetStunKeepaliveLifetime() { + return (network_cost() >= rtc::kNetworkCostHigh) + ? HIGH_COST_PORT_KEEPALIVE_LIFETIME + : INFINITE_LIFETIME; + } + ServerAddresses server_addresses_; ServerAddresses bind_request_succeeded_servers_; ServerAddresses bind_request_failed_servers_; @@ -228,7 +245,7 @@ class UDPPort : public Port { std::unique_ptr resolver_; bool ready_; int stun_keepalive_delay_; - int stun_keepalive_lifetime_; + int stun_keepalive_lifetime_ = INFINITE_LIFETIME; // This is true by default and false when // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified. diff --git a/include/webrtc/p2p/base/stunrequest.h b/include/webrtc/p2p/base/stunrequest.h index f6d216d..99dff14 100644 --- a/include/webrtc/p2p/base/stunrequest.h +++ b/include/webrtc/p2p/base/stunrequest.h @@ -23,6 +23,11 @@ class StunRequest; const int kAllRequests = 0; +// Total max timeouts: 39.75 seconds +// For years, this was 9.5 seconds, but for networks that experience moments of +// high RTT (such as 40s on 2G networks), this doesn't work well. +const int STUN_TOTAL_TIMEOUT = 39750; // milliseconds + // Manages a set of STUN requests, sending and resending until we receive a // response or determine that the request has timed out. class StunRequestManager { diff --git a/include/webrtc/p2p/base/stunserver.h b/include/webrtc/p2p/base/stunserver.h index 9d1c169..c9ae86a 100644 --- a/include/webrtc/p2p/base/stunserver.h +++ b/include/webrtc/p2p/base/stunserver.h @@ -25,7 +25,7 @@ class StunServer : public sigslot::has_slots<> { // Creates a STUN server, which will listen on the given socket. explicit StunServer(rtc::AsyncUDPSocket* socket); // Removes the STUN server from the socket and deletes the socket. - ~StunServer(); + ~StunServer() override; protected: // Slot for AsyncSocket.PacketRead: diff --git a/include/webrtc/p2p/base/tcpport.h b/include/webrtc/p2p/base/tcpport.h index 77bbd09..76a73f8 100644 --- a/include/webrtc/p2p/base/tcpport.h +++ b/include/webrtc/p2p/base/tcpport.h @@ -61,6 +61,8 @@ class TCPPort : public Port { return protocol == TCP_PROTOCOL_NAME || protocol == SSLTCP_PROTOCOL_NAME; } + ProtocolType GetProtocol() const override { return PROTO_TCP; } + protected: TCPPort(rtc::Thread* thread, rtc::PacketSocketFactory* factory, diff --git a/include/webrtc/p2p/base/testturnserver.h b/include/webrtc/p2p/base/testturnserver.h index 8660ae1..9cd8203 100644 --- a/include/webrtc/p2p/base/testturnserver.h +++ b/include/webrtc/p2p/base/testturnserver.h @@ -52,10 +52,10 @@ class TestTurnServer : public TurnAuthInterface { const rtc::SocketAddress& int_addr, const rtc::SocketAddress& udp_ext_addr, ProtocolType int_protocol = PROTO_UDP) - : server_(thread) { + : server_(thread), thread_(thread) { AddInternalSocket(int_addr, int_protocol); - server_.SetExternalSocketFactory(new rtc::BasicPacketSocketFactory(), - udp_ext_addr); + server_.SetExternalSocketFactory(new rtc::BasicPacketSocketFactory(thread), + udp_ext_addr); server_.set_realm(kTestRealm); server_.set_software(kTestSoftware); server_.set_auth_hook(this); @@ -71,17 +71,21 @@ class TestTurnServer : public TurnAuthInterface { server_.set_redirect_hook(redirect_hook); } + void set_enable_permission_checks(bool enable) { + server_.set_enable_permission_checks(enable); + } + void AddInternalSocket(const rtc::SocketAddress& int_addr, ProtocolType proto) { - rtc::Thread* thread = rtc::Thread::Current(); if (proto == cricket::PROTO_UDP) { - server_.AddInternalSocket(rtc::AsyncUDPSocket::Create( - thread->socketserver(), int_addr), proto); + server_.AddInternalSocket( + rtc::AsyncUDPSocket::Create(thread_->socketserver(), int_addr), + proto); } else if (proto == cricket::PROTO_TCP) { // For TCP we need to create a server socket which can listen for incoming // new connections. rtc::AsyncSocket* socket = - thread->socketserver()->CreateAsyncSocket(SOCK_STREAM); + thread_->socketserver()->CreateAsyncSocket(SOCK_STREAM); socket->Bind(int_addr); socket->Listen(5); server_.AddInternalServerSocket(socket, proto); @@ -95,7 +99,7 @@ class TestTurnServer : public TurnAuthInterface { for (TurnServer::AllocationMap::const_iterator it = map.begin(); it != map.end(); ++it) { if (src == it->first.src()) { - return it->second; + return it->second.get(); } } return NULL; @@ -110,6 +114,7 @@ class TestTurnServer : public TurnAuthInterface { } TurnServer server_; + rtc::Thread* thread_; }; } // namespace cricket diff --git a/include/webrtc/p2p/base/transport.h b/include/webrtc/p2p/base/transport.h index e31d37a..0921a41 100644 --- a/include/webrtc/p2p/base/transport.h +++ b/include/webrtc/p2p/base/transport.h @@ -1,5 +1,5 @@ /* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * Copyright 2016 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -8,359 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -// A Transport manages a set of named channels of the same type. -// -// Subclasses choose the appropriate class to instantiate for each channel; -// however, this base class keeps track of the channels by name, watches their -// state changes (in order to update the manager's state), and forwards -// requests to begin connecting or to reset to each of the channels. -// -// On Threading: Transport performs work solely on the worker thread, and so -// its methods should only be called on the worker thread. -// -// Note: Subclasses must call DestroyChannels() in their own destructors. -// It is not possible to do so here because the subclass destructor will -// already have run. +// Most of the contents of this header have moved to jseptransport.h. +// TODO(deadbeef): Delete this file when downstream dependents are updated. #ifndef WEBRTC_P2P_BASE_TRANSPORT_H_ #define WEBRTC_P2P_BASE_TRANSPORT_H_ -#include -#include -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/p2p/base/candidate.h" -#include "webrtc/p2p/base/p2pconstants.h" -#include "webrtc/p2p/base/sessiondescription.h" -#include "webrtc/p2p/base/transportinfo.h" -#include "webrtc/base/messagequeue.h" -#include "webrtc/base/rtccertificate.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/base/sslstreamadapter.h" - -namespace cricket { - -class PortAllocator; -class TransportChannel; -class TransportChannelImpl; - -typedef std::vector Candidates; - -// TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState -// once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming -// style. -enum IceConnectionState { - kIceConnectionConnecting = 0, - kIceConnectionFailed, - kIceConnectionConnected, // Writable, but still checking one or more - // connections - kIceConnectionCompleted, -}; - -enum DtlsTransportState { - // Haven't started negotiating. - DTLS_TRANSPORT_NEW = 0, - // Have started negotiating. - DTLS_TRANSPORT_CONNECTING, - // Negotiated, and has a secure connection. - DTLS_TRANSPORT_CONNECTED, - // Transport is closed. - DTLS_TRANSPORT_CLOSED, - // Failed due to some error in the handshake process. - DTLS_TRANSPORT_FAILED, -}; - -// TODO(deadbeef): Unify with PeerConnectionInterface::IceConnectionState -// once /talk/ and /webrtc/ are combined, and also switch to ENUM_NAME naming -// style. -enum IceGatheringState { - kIceGatheringNew = 0, - kIceGatheringGathering, - kIceGatheringComplete, -}; - -// Stats that we can return about the connections for a transport channel. -// TODO(hta): Rename to ConnectionStats -struct ConnectionInfo { - ConnectionInfo() - : best_connection(false), - writable(false), - receiving(false), - timeout(false), - new_connection(false), - rtt(0), - sent_total_bytes(0), - sent_bytes_second(0), - sent_discarded_packets(0), - sent_total_packets(0), - recv_total_bytes(0), - recv_bytes_second(0), - key(NULL) {} - - bool best_connection; // Is this the best connection we have? - bool writable; // Has this connection received a STUN response? - bool receiving; // Has this connection received anything? - bool timeout; // Has this connection timed out? - bool new_connection; // Is this a newly created connection? - size_t rtt; // The STUN RTT for this connection. - size_t sent_total_bytes; // Total bytes sent on this connection. - size_t sent_bytes_second; // Bps over the last measurement interval. - size_t sent_discarded_packets; // Number of outgoing packets discarded due to - // socket errors. - size_t sent_total_packets; // Number of total outgoing packets attempted for - // sending. - - size_t recv_total_bytes; // Total bytes received on this connection. - size_t recv_bytes_second; // Bps over the last measurement interval. - Candidate local_candidate; // The local candidate for this connection. - Candidate remote_candidate; // The remote candidate for this connection. - void* key; // A static value that identifies this conn. -}; - -// Information about all the connections of a channel. -typedef std::vector ConnectionInfos; - -// Information about a specific channel -struct TransportChannelStats { - int component = 0; - ConnectionInfos connection_infos; - int srtp_crypto_suite = rtc::SRTP_INVALID_CRYPTO_SUITE; - int ssl_cipher_suite = rtc::TLS_NULL_WITH_NULL_NULL; -}; - -// Information about all the channels of a transport. -// TODO(hta): Consider if a simple vector is as good as a map. -typedef std::vector TransportChannelStatsList; - -// Information about the stats of a transport. -struct TransportStats { - std::string transport_name; - TransportChannelStatsList channel_stats; -}; - -// Information about ICE configuration. -struct IceConfig { - // The ICE connection receiving timeout value in milliseconds. - int receiving_timeout = -1; - // Time interval in milliseconds to ping a backup connection when the ICE - // channel is strongly connected. - int backup_connection_ping_interval = -1; - // If true, the most recent port allocator session will keep on running. - bool gather_continually = false; - - // Whether we should prioritize Relay/Relay candidate when nothing - // is writable yet. - bool prioritize_most_likely_candidate_pairs = false; - - // If the current best connection is both writable and receiving, - // then we will also try hard to make sure it is pinged at this rate - // (Default value is a little less than 2 * STRONG_PING_INTERVAL). - int max_strong_interval = -1; - - IceConfig() {} - IceConfig(int receiving_timeout_ms, - int backup_connection_ping_interval, - bool gather_continually, - bool prioritize_most_likely_candidate_pairs, - int max_strong_interval_ms) - : receiving_timeout(receiving_timeout_ms), - backup_connection_ping_interval(backup_connection_ping_interval), - gather_continually(gather_continually), - prioritize_most_likely_candidate_pairs( - prioritize_most_likely_candidate_pairs), - max_strong_interval(max_strong_interval_ms) {} -}; - -bool BadTransportDescription(const std::string& desc, std::string* err_desc); - -bool IceCredentialsChanged(const std::string& old_ufrag, - const std::string& old_pwd, - const std::string& new_ufrag, - const std::string& new_pwd); - -class Transport : public sigslot::has_slots<> { - public: - Transport(const std::string& name, PortAllocator* allocator); - virtual ~Transport(); - - // Returns the name of this transport. - const std::string& name() const { return name_; } - - // Returns the port allocator object for this transport. - PortAllocator* port_allocator() { return allocator_; } - - bool ready_for_remote_candidates() const { - return local_description_set_ && remote_description_set_; - } - - // Returns whether the client has requested the channels to connect. - bool connect_requested() const { return connect_requested_; } - - void SetIceRole(IceRole role); - IceRole ice_role() const { return ice_role_; } - - void SetIceTiebreaker(uint64_t IceTiebreaker) { tiebreaker_ = IceTiebreaker; } - uint64_t IceTiebreaker() { return tiebreaker_; } - - void SetIceConfig(const IceConfig& config); - - // Must be called before applying local session description. - virtual void SetLocalCertificate( - const rtc::scoped_refptr& certificate) {} - - // Get a copy of the local certificate provided by SetLocalCertificate. - virtual bool GetLocalCertificate( - rtc::scoped_refptr* certificate) { - return false; - } - - // Get a copy of the remote certificate in use by the specified channel. - std::unique_ptr GetRemoteSSLCertificate(); - - // Create, destroy, and lookup the channels of this type by their components. - TransportChannelImpl* CreateChannel(int component); - - TransportChannelImpl* GetChannel(int component); - - bool HasChannel(int component) { - return (NULL != GetChannel(component)); - } - bool HasChannels(); - - void DestroyChannel(int component); - - // Set the local TransportDescription to be used by TransportChannels. - bool SetLocalTransportDescription(const TransportDescription& description, - ContentAction action, - std::string* error_desc); - - // Set the remote TransportDescription to be used by TransportChannels. - bool SetRemoteTransportDescription(const TransportDescription& description, - ContentAction action, - std::string* error_desc); - - // Tells all current and future channels to start connecting. - void ConnectChannels(); - - // Tells channels to start gathering candidates if necessary. - // Should be called after ConnectChannels() has been called at least once, - // which will happen in SetLocalTransportDescription. - void MaybeStartGathering(); - - // Resets all of the channels back to their initial state. They are no - // longer connecting. - void ResetChannels(); - - // Destroys every channel created so far. - void DestroyAllChannels(); - - bool GetStats(TransportStats* stats); - - // Called when one or more candidates are ready from the remote peer. - bool AddRemoteCandidates(const std::vector& candidates, - std::string* error); - bool RemoveRemoteCandidates(const std::vector& candidates, - std::string* error); - - virtual bool GetSslRole(rtc::SSLRole* ssl_role) const { return false; } - - // Must be called before channel is starting to connect. - virtual bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) { - return false; - } - - protected: - // These are called by Create/DestroyChannel above in order to create or - // destroy the appropriate type of channel. - virtual TransportChannelImpl* CreateTransportChannel(int component) = 0; - virtual void DestroyTransportChannel(TransportChannelImpl* channel) = 0; - - // The current local transport description, for use by derived classes - // when performing transport description negotiation. - const TransportDescription* local_description() const { - return local_description_.get(); - } - - // The current remote transport description, for use by derived classes - // when performing transport description negotiation. - const TransportDescription* remote_description() const { - return remote_description_.get(); - } - - // Pushes down the transport parameters from the local description, such - // as the ICE ufrag and pwd. - // Derived classes can override, but must call the base as well. - virtual bool ApplyLocalTransportDescription(TransportChannelImpl* channel, - std::string* error_desc); - - // Pushes down remote ice credentials from the remote description to the - // transport channel. - virtual bool ApplyRemoteTransportDescription(TransportChannelImpl* ch, - std::string* error_desc); - - // Negotiates the transport parameters based on the current local and remote - // transport description, such as the ICE role to use, and whether DTLS - // should be activated. - // Derived classes can negotiate their specific parameters here, but must call - // the base as well. - virtual bool NegotiateTransportDescription(ContentAction local_role, - std::string* error_desc); - - // Pushes down the transport parameters obtained via negotiation. - // Derived classes can set their specific parameters here, but must call the - // base as well. - virtual bool ApplyNegotiatedTransportDescription( - TransportChannelImpl* channel, - std::string* error_desc); - - // Returns false if the certificate's identity does not match the fingerprint, - // or either is NULL. - virtual bool VerifyCertificateFingerprint( - const rtc::RTCCertificate* certificate, - const rtc::SSLFingerprint* fingerprint, - std::string* error_desc) const; - - // Negotiates the SSL role based off the offer and answer as specified by - // RFC 4145, section-4.1. Returns false if the SSL role cannot be determined - // from the local description and remote description. - virtual bool NegotiateRole(ContentAction local_role, - rtc::SSLRole* ssl_role, - std::string* error_desc) const; - - private: - // If a candidate is not acceptable, returns false and sets error. - // Call this before calling OnRemoteCandidates. - bool VerifyCandidate(const Candidate& candidate, std::string* error); - bool VerifyCandidates(const Candidates& candidates, std::string* error); - - // Candidate component => TransportChannelImpl* - typedef std::map ChannelMap; - - // Helper function that invokes the given function on every channel. - typedef void (TransportChannelImpl::* TransportChannelFunc)(); - void CallChannels(TransportChannelFunc func); - - const std::string name_; - PortAllocator* const allocator_; - bool channels_destroyed_ = false; - bool connect_requested_ = false; - IceRole ice_role_ = ICEROLE_UNKNOWN; - uint64_t tiebreaker_ = 0; - IceMode remote_ice_mode_ = ICEMODE_FULL; - IceConfig ice_config_; - std::unique_ptr local_description_; - std::unique_ptr remote_description_; - bool local_description_set_ = false; - bool remote_description_set_ = false; - - ChannelMap channels_; - - RTC_DISALLOW_COPY_AND_ASSIGN(Transport); -}; - - -} // namespace cricket +#include "webrtc/p2p/base/transport.h" #endif // WEBRTC_P2P_BASE_TRANSPORT_H_ diff --git a/include/webrtc/p2p/base/transportchannel.h b/include/webrtc/p2p/base/transportchannel.h deleted file mode 100644 index 87ed9fd..0000000 --- a/include/webrtc/p2p/base/transportchannel.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_BASE_TRANSPORTCHANNEL_H_ -#define WEBRTC_P2P_BASE_TRANSPORTCHANNEL_H_ - -#include -#include -#include - -#include "webrtc/base/constructormagic.h" -#include "webrtc/p2p/base/candidate.h" -#include "webrtc/p2p/base/candidatepairinterface.h" -#include "webrtc/p2p/base/transport.h" -#include "webrtc/p2p/base/transportdescription.h" -#include "webrtc/base/asyncpacketsocket.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/base/dscp.h" -#include "webrtc/base/sigslot.h" -#include "webrtc/base/socket.h" -#include "webrtc/base/sslidentity.h" -#include "webrtc/base/sslstreamadapter.h" - -namespace cricket { - -class Candidate; - -// Flags for SendPacket/SignalReadPacket. -enum PacketFlags { - PF_NORMAL = 0x00, // A normal packet. - PF_SRTP_BYPASS = 0x01, // An encrypted SRTP packet; bypass any additional - // crypto provided by the transport (e.g. DTLS) -}; - -// Used to indicate channel's connection state. -enum TransportChannelState { - STATE_INIT, - STATE_CONNECTING, // Will enter this state once a connection is created - STATE_COMPLETED, - STATE_FAILED -}; - -// A TransportChannel represents one logical stream of packets that are sent -// between the two sides of a session. -// TODO(deadbeef): This interface currently represents the unity of an ICE -// transport and a DTLS transport. They need to be separated apart. -class TransportChannel : public sigslot::has_slots<> { - public: - TransportChannel(const std::string& transport_name, int component) - : transport_name_(transport_name), - component_(component), - writable_(false), - receiving_(false) {} - virtual ~TransportChannel() {} - - // TODO(guoweis) - Make this pure virtual once all subclasses of - // TransportChannel have this defined. - virtual TransportChannelState GetState() const { - return TransportChannelState::STATE_CONNECTING; - } - - // TODO(mallinath) - Remove this API, as it's no longer useful. - // Returns the session id of this channel. - virtual const std::string SessionId() const { return std::string(); } - - const std::string& transport_name() const { return transport_name_; } - int component() const { return component_; } - - // Returns the states of this channel. Each time one of these states changes, - // a signal is raised. These states are aggregated by the TransportManager. - bool writable() const { return writable_; } - bool receiving() const { return receiving_; } - DtlsTransportState dtls_state() const { return dtls_state_; } - sigslot::signal1 SignalWritableState; - // Emitted when the TransportChannel's ability to send has changed. - sigslot::signal1 SignalReadyToSend; - sigslot::signal1 SignalReceivingState; - // Emitted whenever DTLS-SRTP is setup which will require setting up a new - // SRTP context. - sigslot::signal2 SignalDtlsState; - - // Attempts to send the given packet. The return value is < 0 on failure. - // TODO: Remove the default argument once channel code is updated. - virtual int SendPacket(const char* data, size_t len, - const rtc::PacketOptions& options, - int flags = 0) = 0; - - // Sets a socket option on this channel. Note that not all options are - // supported by all transport types. - virtual int SetOption(rtc::Socket::Option opt, int value) = 0; - // TODO(pthatcher): Once Chrome's MockTransportChannel implments - // this, remove the default implementation. - virtual bool GetOption(rtc::Socket::Option opt, int* value) { return false; } - - // Returns the most recent error that occurred on this channel. - virtual int GetError() = 0; - - // Returns the current stats for this connection. - virtual bool GetStats(ConnectionInfos* infos) = 0; - - // Is DTLS active? - virtual bool IsDtlsActive() const = 0; - - // Default implementation. - virtual bool GetSslRole(rtc::SSLRole* role) const = 0; - - // Sets up the ciphers to use for DTLS-SRTP. TODO(guoweis): Make this pure - // virtual once all dependencies have implementation. - virtual bool SetSrtpCryptoSuites(const std::vector& ciphers); - - // Keep the original one for backward compatibility until all dependencies - // move away. TODO(guoweis): Remove this function. - virtual bool SetSrtpCiphers(const std::vector& ciphers); - - // Finds out which DTLS-SRTP cipher was negotiated. - // TODO(guoweis): Remove this once all dependencies implement this. - virtual bool GetSrtpCryptoSuite(int* cipher) { return false; } - - // Finds out which DTLS cipher was negotiated. - // TODO(guoweis): Remove this once all dependencies implement this. - virtual bool GetSslCipherSuite(int* cipher) { return false; } - - // Gets the local RTCCertificate used for DTLS. - virtual rtc::scoped_refptr - GetLocalCertificate() const = 0; - - // Gets a copy of the remote side's SSL certificate. - virtual std::unique_ptr GetRemoteSSLCertificate() - const = 0; - - // Allows key material to be extracted for external encryption. - virtual bool ExportKeyingMaterial(const std::string& label, - const uint8_t* context, - size_t context_len, - bool use_context, - uint8_t* result, - size_t result_len) = 0; - - // Signalled each time a packet is received on this channel. - sigslot::signal5 SignalReadPacket; - - // Signalled each time a packet is sent on this channel. - sigslot::signal2 SignalSentPacket; - - // Deprecated by SignalSelectedCandidatePairChanged - // This signal occurs when there is a change in the way that packets are - // being routed, i.e. to a different remote location. The candidate - // indicates where and how we are currently sending media. - sigslot::signal2 SignalRouteChange; - - // Signalled when the current selected candidate pair has changed. - // The first parameter is the transport channel that signals the event. - // The second parameter is the new selected candidate pair. The third - // parameter is the last packet id sent on the previous candidate pair. - sigslot::signal3 - SignalSelectedCandidatePairChanged; - - // Invoked when the channel is being destroyed. - sigslot::signal1 SignalDestroyed; - - // Debugging description of this transport channel. - std::string ToString() const; - - protected: - // Sets the writable state, signaling if necessary. - void set_writable(bool writable); - - // Sets the receiving state, signaling if necessary. - void set_receiving(bool receiving); - - // Sets the DTLS state, signaling if necessary. - void set_dtls_state(DtlsTransportState state); - - private: - // Used mostly for debugging. - std::string transport_name_; - int component_; - bool writable_; - bool receiving_; - DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW; - - RTC_DISALLOW_COPY_AND_ASSIGN(TransportChannel); -}; - -} // namespace cricket - -#endif // WEBRTC_P2P_BASE_TRANSPORTCHANNEL_H_ diff --git a/include/webrtc/p2p/base/transportchannelimpl.h b/include/webrtc/p2p/base/transportchannelimpl.h index f548aa0..f72cb2d 100644 --- a/include/webrtc/p2p/base/transportchannelimpl.h +++ b/include/webrtc/p2p/base/transportchannelimpl.h @@ -14,20 +14,17 @@ #include #include "webrtc/base/constructormagic.h" +#include "webrtc/p2p/base/icetransportinternal.h" #include "webrtc/p2p/base/transportchannel.h" -namespace buzz { class XmlElement; } +namespace webrtc { +class MetricsObserverInterface; +} namespace cricket { class Candidate; -// TODO(pthatcher): Remove this once it's no longer used in -// remoting/protocol/libjingle_transport_factory.cc -enum IceProtocolType { - ICEPROTO_RFC5245 // Standard RFC 5245 version of ICE. -}; - // Base class for real implementations of TransportChannel. This includes some // methods called only by Transport, which do not need to be exposed to the // client. @@ -44,28 +41,39 @@ class TransportChannelImpl : public TransportChannel { // TODO(pthatcher): Remove this once it's no longer called in // remoting/protocol/libjingle_transport_factory.cc virtual void SetIceProtocolType(IceProtocolType type) {} - // SetIceCredentials only need to be implemented by the ICE - // transport channels. Non-ICE transport channels can just ignore. - // The ufrag and pwd should be set before the Connect() is called. + // TODO(honghaiz): Remove this once the call in chromoting is removed. virtual void SetIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) = 0; - // SetRemoteIceCredentials only need to be implemented by the ICE - // transport channels. Non-ICE transport channels can just ignore. + const std::string& ice_pwd) { + SetIceParameters(IceParameters(ice_ufrag, ice_pwd, false)); + } + // TODO(honghaiz): Remove this once the call in chromoting is removed. virtual void SetRemoteIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) = 0; + const std::string& ice_pwd) { + SetRemoteIceParameters(IceParameters(ice_ufrag, ice_pwd, false)); + } + + // SetIceParameters only needs to be implemented by the ICE transport + // channels. Non-ICE transport channels should pass them down to the inner + // ICE transport channel. The ufrag and pwd in |ice_params| must be set + // before candidate gathering can start. + virtual void SetIceParameters(const IceParameters& ice_params) = 0; + // SetRemoteIceParameters only needs to be implemented by the ICE transport + // channels. Non-ICE transport channels should pass them down to the inner + // ICE transport channel. + virtual void SetRemoteIceParameters(const IceParameters& ice_params) = 0; // SetRemoteIceMode must be implemented only by the ICE transport channels. virtual void SetRemoteIceMode(IceMode mode) = 0; virtual void SetIceConfig(const IceConfig& config) = 0; - // Begins the process of attempting to make a connection to the other client. - virtual void Connect() = 0; - // Start gathering candidates if not already started, or if an ICE restart // occurred. virtual void MaybeStartGathering() = 0; + virtual void SetMetricsObserver( + webrtc::MetricsObserverInterface* observer) = 0; + sigslot::signal1 SignalGatheringState; // Handles sending and receiving of candidates. The Transport @@ -100,9 +108,11 @@ class TransportChannelImpl : public TransportChannel { // agents. sigslot::signal1 SignalRoleConflict; - // Emitted whenever the number of connections available to the transport - // channel decreases. - sigslot::signal1 SignalConnectionRemoved; + // Emitted whenever the transport channel state changed. + sigslot::signal1 SignalStateChanged; + + // Emitted whenever the Dtls handshake failed on some transport channel. + sigslot::signal1 SignalDtlsHandshakeError; private: RTC_DISALLOW_COPY_AND_ASSIGN(TransportChannelImpl); diff --git a/include/webrtc/p2p/base/transportcontroller.h b/include/webrtc/p2p/base/transportcontroller.h index cc16a76..091e70e 100644 --- a/include/webrtc/p2p/base/transportcontroller.h +++ b/include/webrtc/p2p/base/transportcontroller.h @@ -17,13 +17,21 @@ #include #include "webrtc/base/asyncinvoker.h" +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/refcountedobject.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/sslstreamadapter.h" #include "webrtc/p2p/base/candidate.h" -#include "webrtc/p2p/base/transport.h" +#include "webrtc/p2p/base/dtlstransportchannel.h" +#include "webrtc/p2p/base/jseptransport.h" +#include "webrtc/p2p/base/p2ptransportchannel.h" namespace rtc { class Thread; +class PacketTransportInternal; +} +namespace webrtc { +class MetricsObserverInterface; } namespace cricket { @@ -31,6 +39,14 @@ namespace cricket { class TransportController : public sigslot::has_slots<>, public rtc::MessageHandler { public: + // If |redetermine_role_on_ice_restart| is true, ICE role is redetermined + // upon setting a local transport description that indicates an ICE restart. + // For the constructor that doesn't take this parameter, it defaults to true. + TransportController(rtc::Thread* signaling_thread, + rtc::Thread* network_thread, + PortAllocator* port_allocator, + bool redetermine_role_on_ice_restart); + TransportController(rtc::Thread* signaling_thread, rtc::Thread* network_thread, PortAllocator* port_allocator); @@ -50,7 +66,17 @@ class TransportController : public sigslot::has_slots<>, void SetIceConfig(const IceConfig& config); void SetIceRole(IceRole ice_role); - bool GetSslRole(const std::string& transport_name, rtc::SSLRole* role); + // Set the "needs-ice-restart" flag as described in JSEP. After the flag is + // set, offers should generate new ufrags/passwords until an ICE restart + // occurs. + void SetNeedsIceRestartFlag(); + // Returns true if the ICE restart flag above was set, and no ICE restart has + // occurred yet for this transport (by applying a local description with + // changed ufrag/password). If the transport has been deleted as a result of + // bundling, returns false. + bool NeedsIceRestart(const std::string& transport_name) const; + + bool GetSslRole(const std::string& transport_name, rtc::SSLRole* role) const; // Specifies the identity to use in this session. // Can only be called once. @@ -58,10 +84,11 @@ class TransportController : public sigslot::has_slots<>, const rtc::scoped_refptr& certificate); bool GetLocalCertificate( const std::string& transport_name, - rtc::scoped_refptr* certificate); - // Caller owns returned certificate + rtc::scoped_refptr* certificate) const; + // Caller owns returned certificate. This method mainly exists for stats + // reporting. std::unique_ptr GetRemoteSSLCertificate( - const std::string& transport_name); + const std::string& transport_name) const; bool SetLocalTransportDescription(const std::string& transport_name, const TransportDescription& tdesc, ContentAction action, @@ -77,23 +104,42 @@ class TransportController : public sigslot::has_slots<>, const Candidates& candidates, std::string* err); bool RemoveRemoteCandidates(const Candidates& candidates, std::string* err); - bool ReadyForRemoteCandidates(const std::string& transport_name); + bool ReadyForRemoteCandidates(const std::string& transport_name) const; + // TODO(deadbeef): GetStats isn't const because all the way down to + // OpenSSLStreamAdapter, + // GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not const. Fix this. bool GetStats(const std::string& transport_name, TransportStats* stats); + void SetMetricsObserver(webrtc::MetricsObserverInterface* metrics_observer); // Creates a channel if it doesn't exist. Otherwise, increments a reference // count and returns an existing channel. - virtual TransportChannel* CreateTransportChannel_n( + DtlsTransportInternal* CreateDtlsTransport(const std::string& transport_name, + int component); + virtual DtlsTransportInternal* CreateDtlsTransport_n( const std::string& transport_name, int component); // Decrements a channel's reference count, and destroys the channel if // nothing is referencing it. - virtual void DestroyTransportChannel_n(const std::string& transport_name, - int component); + virtual void DestroyDtlsTransport(const std::string& transport_name, + int component); + virtual void DestroyDtlsTransport_n(const std::string& transport_name, + int component); void use_quic() { quic_ = true; } bool quic() const { return quic_; } + // TODO(deadbeef): Remove all for_testing methods! + const rtc::scoped_refptr& certificate_for_testing() + const { + return certificate_; + } + std::vector transport_names_for_testing(); + std::vector channels_for_testing(); + DtlsTransportInternal* get_channel_for_testing( + const std::string& transport_name, + int component); + // All of these signals are fired on the signalling thread. // If any transport failed => failed, @@ -116,62 +162,57 @@ class TransportController : public sigslot::has_slots<>, sigslot::signal1 SignalCandidatesRemoved; - // for unit test - const rtc::scoped_refptr& certificate_for_testing(); + sigslot::signal1 SignalDtlsHandshakeError; protected: - // Protected and virtual so we can override it in unit tests. - virtual Transport* CreateTransport_n(const std::string& transport_name); - - // For unit tests - const std::map& transports() { return transports_; } - Transport* GetTransport_n(const std::string& transport_name); + // TODO(deadbeef): Get rid of these virtual methods. Used by + // FakeTransportController currently, but FakeTransportController shouldn't + // even be functioning by subclassing TransportController. + virtual IceTransportInternal* CreateIceTransportChannel_n( + const std::string& transport_name, + int component); + virtual DtlsTransportInternal* CreateDtlsTransportChannel_n( + const std::string& transport_name, + int component, + IceTransportInternal* ice); private: void OnMessage(rtc::Message* pmsg) override; - // It's the Transport that's currently responsible for creating/destroying - // channels, but the TransportController keeps track of how many external - // objects (BaseChannels) reference each channel. - struct RefCountedChannel { - RefCountedChannel() : impl_(nullptr), ref_(0) {} - explicit RefCountedChannel(TransportChannelImpl* impl) - : impl_(impl), ref_(0) {} - - void AddRef() { ++ref_; } - void DecRef() { - ASSERT(ref_ > 0); - --ref_; - } - int ref() const { return ref_; } - - TransportChannelImpl* get() const { return impl_; } - TransportChannelImpl* operator->() const { return impl_; } - - private: - TransportChannelImpl* impl_; - int ref_; - }; - - std::vector::iterator FindChannel_n( + class ChannelPair; + typedef rtc::RefCountedObject RefCountedChannel; + + // Helper functions to get a channel or transport, or iterator to it (in case + // it needs to be erased). + std::vector::iterator GetChannelIterator_n( const std::string& transport_name, int component); - - Transport* GetOrCreateTransport_n(const std::string& transport_name); - void DestroyTransport_n(const std::string& transport_name); - void DestroyAllTransports_n(); + std::vector::const_iterator GetChannelIterator_n( + const std::string& transport_name, + int component) const; + const JsepTransport* GetJsepTransport( + const std::string& transport_name) const; + JsepTransport* GetJsepTransport(const std::string& transport_name); + const RefCountedChannel* GetChannel_n(const std::string& transport_name, + int component) const; + RefCountedChannel* GetChannel_n(const std::string& transport_name, + int component); + + JsepTransport* GetOrCreateJsepTransport(const std::string& transport_name); + void DestroyAllChannels_n(); bool SetSslMaxProtocolVersion_n(rtc::SSLProtocolVersion version); void SetIceConfig_n(const IceConfig& config); void SetIceRole_n(IceRole ice_role); - bool GetSslRole_n(const std::string& transport_name, rtc::SSLRole* role); + bool GetSslRole_n(const std::string& transport_name, + rtc::SSLRole* role) const; bool SetLocalCertificate_n( const rtc::scoped_refptr& certificate); bool GetLocalCertificate_n( const std::string& transport_name, - rtc::scoped_refptr* certificate); + rtc::scoped_refptr* certificate) const; std::unique_ptr GetRemoteSSLCertificate_n( - const std::string& transport_name); + const std::string& transport_name) const; bool SetLocalTransportDescription_n(const std::string& transport_name, const TransportDescription& tdesc, ContentAction action, @@ -185,48 +226,51 @@ class TransportController : public sigslot::has_slots<>, const Candidates& candidates, std::string* err); bool RemoveRemoteCandidates_n(const Candidates& candidates, std::string* err); - bool ReadyForRemoteCandidates_n(const std::string& transport_name); + bool ReadyForRemoteCandidates_n(const std::string& transport_name) const; bool GetStats_n(const std::string& transport_name, TransportStats* stats); + void SetMetricsObserver_n(webrtc::MetricsObserverInterface* metrics_observer); // Handlers for signals from Transport. - void OnChannelWritableState_n(TransportChannel* channel); - void OnChannelReceivingState_n(TransportChannel* channel); - void OnChannelGatheringState_n(TransportChannelImpl* channel); - void OnChannelCandidateGathered_n(TransportChannelImpl* channel, + void OnChannelWritableState_n(rtc::PacketTransportInternal* transport); + void OnChannelReceivingState_n(rtc::PacketTransportInternal* transport); + void OnChannelGatheringState_n(IceTransportInternal* channel); + void OnChannelCandidateGathered_n(IceTransportInternal* channel, const Candidate& candidate); void OnChannelCandidatesRemoved(const Candidates& candidates); - void OnChannelCandidatesRemoved_n(TransportChannelImpl* channel, + void OnChannelCandidatesRemoved_n(IceTransportInternal* channel, const Candidates& candidates); - void OnChannelRoleConflict_n(TransportChannelImpl* channel); - void OnChannelConnectionRemoved_n(TransportChannelImpl* channel); + void OnChannelRoleConflict_n(IceTransportInternal* channel); + void OnChannelStateChanged_n(IceTransportInternal* channel); void UpdateAggregateStates_n(); + void OnDtlsHandshakeError(rtc::SSLHandshakeError error); + rtc::Thread* const signaling_thread_ = nullptr; rtc::Thread* const network_thread_ = nullptr; - typedef std::map TransportMap; - TransportMap transports_; - - std::vector channels_; - PortAllocator* const port_allocator_ = nullptr; - rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; + + std::map> transports_; + std::vector channels_; // Aggregate state for TransportChannelImpls. IceConnectionState connection_state_ = kIceConnectionConnecting; bool receiving_ = false; IceGatheringState gathering_state_ = kIceGatheringNew; - // TODO(deadbeef): Move the fields below down to the transports themselves IceConfig ice_config_; IceRole ice_role_ = ICEROLE_CONTROLLING; - // Flag which will be set to true after the first role switch - bool ice_role_switch_ = false; + bool redetermine_role_on_ice_restart_; uint64_t ice_tiebreaker_ = rtc::CreateRandomId64(); + rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12; rtc::scoped_refptr certificate_; rtc::AsyncInvoker invoker_; // True if QUIC is used instead of DTLS. bool quic_ = false; + + webrtc::MetricsObserverInterface* metrics_observer_ = nullptr; + + RTC_DISALLOW_COPY_AND_ASSIGN(TransportController); }; } // namespace cricket diff --git a/include/webrtc/p2p/base/transportdescription.h b/include/webrtc/p2p/base/transportdescription.h index 42e45a6..e7f9263 100644 --- a/include/webrtc/p2p/base/transportdescription.h +++ b/include/webrtc/p2p/base/transportdescription.h @@ -28,6 +28,8 @@ namespace cricket { // SEC_ENABLED: Crypto in outgoing offer and answer (if supplied in offer). // SEC_REQUIRED: Crypto in outgoing offer and answer. Fail any offer with absent // or unsupported crypto. +// TODO(deadbeef): Remove this or rename it to something more appropriate, like +// SdesPolicy. enum SecurePolicy { SEC_DISABLED, SEC_ENABLED, @@ -60,11 +62,33 @@ enum ConnectionRole { CONNECTIONROLE_HOLDCONN, }; +struct IceParameters { + // TODO(honghaiz): Include ICE mode in this structure to match the ORTC + // struct: + // http://ortc.org/wp-content/uploads/2016/03/ortc.html#idl-def-RTCIceParameters + std::string ufrag; + std::string pwd; + bool renomination = false; + IceParameters() = default; + IceParameters(const std::string& ice_ufrag, + const std::string& ice_pwd, + bool ice_renomination) + : ufrag(ice_ufrag), pwd(ice_pwd), renomination(ice_renomination) {} + + bool operator==(const IceParameters& other) { + return ufrag == other.ufrag && pwd == other.pwd && + renomination == other.renomination; + } + bool operator!=(const IceParameters& other) { return !(*this == other); } +}; + extern const char CONNECTIONROLE_ACTIVE_STR[]; extern const char CONNECTIONROLE_PASSIVE_STR[]; extern const char CONNECTIONROLE_ACTPASS_STR[]; extern const char CONNECTIONROLE_HOLDCONN_STR[]; +constexpr auto ICE_RENOMINATION_STR = "renomination"; + bool StringToConnectionRole(const std::string& role_str, ConnectionRole* role); bool ConnectionRoleToString(const ConnectionRole& role, std::string* role_str); @@ -125,6 +149,10 @@ struct TransportDescription { } bool secure() const { return identity_fingerprint != NULL; } + IceParameters GetIceParameters() { + return IceParameters(ice_ufrag, ice_pwd, HasOption(ICE_RENOMINATION_STR)); + } + static rtc::SSLFingerprint* CopyFingerprint( const rtc::SSLFingerprint* from) { if (!from) diff --git a/include/webrtc/p2p/base/transportdescriptionfactory.h b/include/webrtc/p2p/base/transportdescriptionfactory.h index 828aa6d..ac04f04 100644 --- a/include/webrtc/p2p/base/transportdescriptionfactory.h +++ b/include/webrtc/p2p/base/transportdescriptionfactory.h @@ -21,9 +21,11 @@ class SSLIdentity; namespace cricket { struct TransportOptions { - TransportOptions() : ice_restart(false), prefer_passive_role(false) {} - bool ice_restart; - bool prefer_passive_role; + bool ice_restart = false; + bool prefer_passive_role = false; + // If true, ICE renomination is supported and will be used if it is also + // supported by the remote side. + bool enable_ice_renomination = false; }; // Creates transport descriptions according to the supplied configuration. @@ -51,9 +53,16 @@ class TransportDescriptionFactory { TransportDescription* CreateOffer(const TransportOptions& options, const TransportDescription* current_description) const; // Create a transport description that is a response to an offer. + // + // If |require_transport_attributes| is true, then TRANSPORT category + // attributes are expected to be present in |offer|, as defined by + // sdp-mux-attributes, and null will be returned otherwise. It's expected + // that this will be set to false for an m= section that's in a BUNDLE group + // but isn't the first m= section in the group. TransportDescription* CreateAnswer( const TransportDescription* offer, const TransportOptions& options, + bool require_transport_attributes, const TransportDescription* current_description) const; private: diff --git a/include/webrtc/p2p/base/turnport.h b/include/webrtc/p2p/base/turnport.h index 461fc13..e5f384f 100644 --- a/include/webrtc/p2p/base/turnport.h +++ b/include/webrtc/p2p/base/turnport.h @@ -38,7 +38,9 @@ class TurnPort : public Port { STATE_CONNECTING, // Initial state, cannot send any packets. STATE_CONNECTED, // Socket connected, ready to send stun requests. STATE_READY, // Received allocate success, can send any packets. - STATE_DISCONNECTED, // TCP connection died, cannot send any packets. + STATE_RECEIVEONLY, // Had REFRESH_REQUEST error, cannot send any packets. + STATE_DISCONNECTED, // TCP connection died, cannot send/receive any + // packets. }; static TurnPort* Create(rtc::Thread* thread, rtc::PacketSocketFactory* factory, @@ -83,6 +85,14 @@ class TurnPort : public Port { } const RelayCredentials& credentials() const { return credentials_; } + virtual ProtocolType GetProtocol() const { return server_address_.proto; } + + virtual TlsCertPolicy GetTlsCertPolicy() const { return tls_cert_policy_; } + + virtual void SetTlsCertPolicy(TlsCertPolicy tls_cert_policy) { + tls_cert_policy_ = tls_cert_policy; + } + virtual void PrepareAddress(); virtual Connection* CreateConnection( const Candidate& c, PortInterface::CandidateOrigin origin); @@ -190,6 +200,7 @@ class TurnPort : public Port { typedef std::set AttemptedServerSet; virtual void OnMessage(rtc::Message* pmsg); + virtual void HandleConnectionDestroyed(Connection* conn); bool CreateTurnClientSocket(); @@ -201,7 +212,8 @@ class TurnPort : public Port { } } - void OnTurnRefreshError(); + void OnRefreshError(); + void HandleRefreshError(); bool SetAlternateServer(const rtc::SocketAddress& address); void ResolveTurnAddress(const rtc::SocketAddress& address); void OnResolveResult(rtc::AsyncResolverInterface* resolver); @@ -243,13 +255,16 @@ class TurnPort : public Port { void DestroyEntryIfNotCancelled(TurnEntry* entry, int64_t timestamp); void ScheduleEntryDestruction(TurnEntry* entry); void CancelEntryDestruction(TurnEntry* entry); - void OnConnectionDestroyed(Connection* conn); - // Destroys the connection with remote address |address|. Returns true if - // a connection is found and destroyed. - bool DestroyConnection(const rtc::SocketAddress& address); + // Marks the connection with remote address |address| failed and + // pruned (a.k.a. write-timed-out). Returns true if a connection is found. + bool FailAndPruneConnection(const rtc::SocketAddress& address); + + // Reconstruct the URL of the server which the candidate is gathered from. + std::string ReconstructedServerUrl(); ProtocolAddress server_address_; + TlsCertPolicy tls_cert_policy_ = TlsCertPolicy::TLS_CERT_POLICY_SECURE; RelayCredentials credentials_; AttemptedServerSet attempted_server_addresses_; diff --git a/include/webrtc/p2p/base/turnserver.h b/include/webrtc/p2p/base/turnserver.h index 2bc3650..608e043 100644 --- a/include/webrtc/p2p/base/turnserver.h +++ b/include/webrtc/p2p/base/turnserver.h @@ -16,8 +16,10 @@ #include #include #include +#include #include "webrtc/p2p/base/portinterface.h" +#include "webrtc/base/asyncinvoker.h" #include "webrtc/base/asyncpacketsocket.h" #include "webrtc/base/messagequeue.h" #include "webrtc/base/sigslot.h" @@ -161,7 +163,8 @@ class TurnRedirectInterface { // Not yet wired up: TCP support. class TurnServer : public sigslot::has_slots<> { public: - typedef std::map AllocationMap; + typedef std::map> + AllocationMap; explicit TurnServer(rtc::Thread* thread); ~TurnServer(); @@ -190,6 +193,10 @@ class TurnServer : public sigslot::has_slots<> { reject_private_addresses_ = filter; } + void set_enable_permission_checks(bool enable) { + enable_permission_checks_ = enable; + } + // Starts listening for packets from internal clients. void AddInternalSocket(rtc::AsyncPacketSocket* socket, ProtocolType proto); @@ -253,6 +260,9 @@ class TurnServer : public sigslot::has_slots<> { void OnAllocationDestroyed(TurnServerAllocation* allocation); void DestroyInternalSocket(rtc::AsyncPacketSocket* socket); + // Just clears |sockets_to_delete_|; called asynchronously. + void FreeSockets(); + typedef std::map InternalSocketMap; typedef std::map { // sees the same nonce in next transaction. bool enable_otu_nonce_; bool reject_private_addresses_ = false; + // Check for permission when receiving an external packet. + bool enable_permission_checks_ = true; InternalSocketMap server_sockets_; ServerSocketMap server_listen_sockets_; + // Used when we need to delete a socket asynchronously. + std::vector> sockets_to_delete_; std::unique_ptr external_socket_factory_; rtc::SocketAddress external_addr_; AllocationMap allocations_; + rtc::AsyncInvoker invoker_; + // For testing only. If this is non-zero, the next NONCE will be generated // from this value, and it will be reset to 0 after generating the NONCE. int64_t ts_for_next_nonce_ = 0; diff --git a/include/webrtc/p2p/base/udptransport.h b/include/webrtc/p2p/base/udptransport.h new file mode 100644 index 0000000..1cf8e42 --- /dev/null +++ b/include/webrtc/p2p/base/udptransport.h @@ -0,0 +1,89 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_P2P_BASE_UDPTRANSPORT_H_ +#define WEBRTC_P2P_BASE_UDPTRANSPORT_H_ + +#include +#include + +#include "webrtc/api/ortc/udptransportinterface.h" +#include "webrtc/base/asyncpacketsocket.h" // For PacketOptions. +#include "webrtc/base/optional.h" +#include "webrtc/base/thread_checker.h" +#include "webrtc/p2p/base/packettransportinternal.h" + +namespace rtc { +class AsyncPacketSocket; +struct PacketTime; +struct SentPacket; +class SocketAddress; +} + +namespace cricket { + +// Implementation of UdpTransportInterface. +// Used by OrtcFactory. +class UdpTransport : public rtc::PacketTransportInternal, + public webrtc::UdpTransportInterface { + public: + // |transport_name| is only used for identification/logging. + // |socket| must be non-null. + UdpTransport(const std::string& transport_name, + std::unique_ptr socket); + ~UdpTransport(); + + // Overrides of UdpTransportInterface, used by the API consumer. + rtc::SocketAddress GetLocalAddress() const override; + bool SetRemoteAddress(const rtc::SocketAddress& addr) override; + rtc::SocketAddress GetRemoteAddress() const override; + + // Overrides of PacketTransportInternal, used by webrtc internally. + std::string debug_name() const override { return transport_name_; } + + bool receiving() const override { + // TODO(johan): Implement method and signal. + return true; + } + + bool writable() const override; + + int SendPacket(const char* data, + size_t len, + const rtc::PacketOptions& options, + int flags) override; + + int SetOption(rtc::Socket::Option opt, int value) override { return 0; } + + int GetError() override { return send_error_; } + + protected: + PacketTransportInternal* GetInternal() override { return this; } + + private: + void OnSocketReadPacket(rtc::AsyncPacketSocket* socket, + const char* data, + size_t len, + const rtc::SocketAddress& remote_addr, + const rtc::PacketTime& packet_time); + void OnSocketSentPacket(rtc::AsyncPacketSocket* socket, + const rtc::SentPacket& packet); + bool IsLocalConsistent(); + std::string transport_name_; + int send_error_ = 0; + std::unique_ptr socket_; + // If not set, will be an "nil" address ("IsNil" returns true). + rtc::SocketAddress remote_address_; + rtc::ThreadChecker network_thread_checker_; +}; + +} // namespace cricket + +#endif // WEBRTC_P2P_BASE_UDPTRANSPORT_H_ diff --git a/include/webrtc/p2p/client/autoportallocator.h b/include/webrtc/p2p/client/autoportallocator.h deleted file mode 100644 index 7856510..0000000 --- a/include/webrtc/p2p/client/autoportallocator.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_CLIENT_AUTOPORTALLOCATOR_H_ -#define WEBRTC_P2P_CLIENT_AUTOPORTALLOCATOR_H_ - -#include -#include - -#include "webrtc/p2p/client/httpportallocator.h" -#include "webrtc/base/sigslot.h" - -// This class sets the relay and stun servers using XmppClient. -// It enables the client to traverse Proxy and NAT. -class AutoPortAllocator : public cricket::HttpPortAllocator { - public: - AutoPortAllocator(rtc::NetworkManager* network_manager, - const std::string& user_agent) - : cricket::HttpPortAllocator(network_manager, user_agent) { - } - - // Creates and initiates a task to get relay token from XmppClient and set - // it appropriately. - void SetXmppClient(buzz::XmppClient* client) { - // The JingleInfoTask is freed by the task-runner. - buzz::JingleInfoTask* jit = new buzz::JingleInfoTask(client); - jit->SignalJingleInfo.connect(this, &AutoPortAllocator::OnJingleInfo); - jit->Start(); - jit->RefreshJingleInfoNow(); - } - - private: - void OnJingleInfo( - const std::string& token, - const std::vector& relay_hosts, - const std::vector& stun_hosts) { - SetRelayToken(token); - SetStunHosts(stun_hosts); - SetRelayHosts(relay_hosts); - } -}; - -#endif // WEBRTC_P2P_CLIENT_AUTOPORTALLOCATOR_H_ diff --git a/include/webrtc/p2p/client/basicportallocator.h b/include/webrtc/p2p/client/basicportallocator.h index fd189c1..cd178f9 100644 --- a/include/webrtc/p2p/client/basicportallocator.h +++ b/include/webrtc/p2p/client/basicportallocator.h @@ -16,6 +16,7 @@ #include #include "webrtc/p2p/base/portallocator.h" +#include "webrtc/base/checks.h" #include "webrtc/base/messagequeue.h" #include "webrtc/base/network.h" #include "webrtc/base/thread.h" @@ -47,7 +48,7 @@ class BasicPortAllocator : public PortAllocator { int network_ignore_mask() const { return network_ignore_mask_; } - rtc::NetworkManager* network_manager() { return network_manager_; } + rtc::NetworkManager* network_manager() const { return network_manager_; } // If socket_factory() is set to NULL each PortAllocatorSession // creates its own socket factory. @@ -65,6 +66,9 @@ class BasicPortAllocator : public PortAllocator { private: void Construct(); + void OnIceRegathering(PortAllocatorSession* session, + IceRegatheringReason reason); + rtc::NetworkManager* network_manager_; rtc::PacketSocketFactory* socket_factory_; bool allow_tcp_listen_; @@ -74,6 +78,14 @@ class BasicPortAllocator : public PortAllocator { struct PortConfiguration; class AllocationSequence; +enum class SessionState { + GATHERING, // Actively allocating ports and gathering candidates. + CLEARED, // Current allocation process has been stopped but may start + // new ones. + STOPPED // This session has completely stopped, no new allocation + // process will be started. +}; + class BasicPortAllocatorSession : public PortAllocatorSession, public rtc::MessageHandler { public: @@ -88,14 +100,19 @@ class BasicPortAllocatorSession : public PortAllocatorSession, rtc::Thread* network_thread() { return network_thread_; } rtc::PacketSocketFactory* socket_factory() { return socket_factory_; } + void SetCandidateFilter(uint32_t filter) override; void StartGettingPorts() override; void StopGettingPorts() override; void ClearGettingPorts() override; - bool IsGettingPorts() override { return running_; } + bool IsGettingPorts() override { return state_ == SessionState::GATHERING; } + bool IsCleared() const override { return state_ == SessionState::CLEARED; } + bool IsStopped() const override { return state_ == SessionState::STOPPED; } // These will all be cricket::Ports. std::vector ReadyPorts() const override; std::vector ReadyCandidates() const override; bool CandidatesAllocationDone() const override; + void RegatherOnFailedNetworks() override; + void PruneAllPorts() override; protected: void UpdateIceParametersInternal() override; @@ -113,36 +130,55 @@ class BasicPortAllocatorSession : public PortAllocatorSession, private: class PortData { public: - PortData() : port_(NULL), sequence_(NULL), state_(STATE_INIT) {} + PortData() {} PortData(Port* port, AllocationSequence* seq) - : port_(port), sequence_(seq), state_(STATE_INIT) { - } + : port_(port), sequence_(seq) {} Port* port() const { return port_; } AllocationSequence* sequence() const { return sequence_; } - bool ready() const { return state_ == STATE_READY; } + bool has_pairable_candidate() const { return has_pairable_candidate_; } bool complete() const { return state_ == STATE_COMPLETE; } bool error() const { return state_ == STATE_ERROR; } - - void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; } + bool pruned() const { return state_ == STATE_PRUNED; } + bool inprogress() const { return state_ == STATE_INPROGRESS; } + // Returns true if this port is ready to be used. + bool ready() const { + return has_pairable_candidate_ && state_ != STATE_ERROR && + state_ != STATE_PRUNED; + } + // Sets the state to "PRUNED" and prunes the Port. + void Prune() { + state_ = STATE_PRUNED; + if (port()) { + port()->Prune(); + } + } + void set_has_pairable_candidate(bool has_pairable_candidate) { + if (has_pairable_candidate) { + RTC_DCHECK(state_ == STATE_INPROGRESS); + } + has_pairable_candidate_ = has_pairable_candidate; + } void set_complete() { state_ = STATE_COMPLETE; } void set_error() { - ASSERT(state_ == STATE_INIT || state_ == STATE_READY); + RTC_DCHECK(state_ == STATE_INPROGRESS); state_ = STATE_ERROR; } private: enum State { - STATE_INIT, // No candidates allocated yet. - STATE_READY, // At least one candidate is ready for process. - STATE_COMPLETE, // All candidates allocated and ready for process. - STATE_ERROR // Error in gathering candidates. + STATE_INPROGRESS, // Still gathering candidates. + STATE_COMPLETE, // All candidates allocated and ready for process. + STATE_ERROR, // Error in gathering candidates. + STATE_PRUNED // Pruned by higher priority ports on the same network + // interface. Only TURN ports may be pruned. }; - Port* port_; - AllocationSequence* sequence_; - State state_; + Port* port_ = nullptr; + AllocationSequence* sequence_ = nullptr; + bool has_pairable_candidate_ = false; + State state_ = STATE_INPROGRESS; }; void OnConfigReady(PortConfiguration* config); @@ -162,13 +198,31 @@ class BasicPortAllocatorSession : public PortAllocatorSession, void OnPortError(Port* port); void OnProtocolEnabled(AllocationSequence* seq, ProtocolType proto); void OnPortDestroyed(PortInterface* port); - void OnShake(); void MaybeSignalCandidatesAllocationDone(); void OnPortAllocationComplete(AllocationSequence* seq); PortData* FindPort(Port* port); - void GetNetworks(std::vector* networks); + std::vector GetNetworks(); + std::vector GetFailedNetworks(); bool CheckCandidateFilter(const Candidate& c) const; + bool CandidatePairable(const Candidate& c, const Port* port) const; + // Clear the related address according to the flags and candidate filter + // in order to avoid leaking any information. + Candidate SanitizeRelatedAddress(const Candidate& c) const; + + std::vector GetUnprunedPorts( + const std::vector& networks); + // Prunes ports and signal the remote side to remove the candidates that + // were previously signaled from these ports. + void PrunePortsAndRemoveCandidates( + const std::vector& port_data_list); + // Gets filtered and sanitized candidates generated from a port and + // append to |candidates|. + void GetCandidatesFromPort(const PortData& data, + std::vector* candidates) const; + Port* GetBestTurnPortForNetwork(const std::string& network_name) const; + // Returns true if at least one TURN port is pruned. + bool PruneTurnPorts(Port* newly_pairable_turn_port); BasicPortAllocator* allocator_; rtc::Thread* network_thread_; @@ -176,11 +230,14 @@ class BasicPortAllocatorSession : public PortAllocatorSession, rtc::PacketSocketFactory* socket_factory_; bool allocation_started_; bool network_manager_started_; - bool running_; // set when StartGetAllPorts is called bool allocation_sequences_created_; std::vector configs_; std::vector sequences_; std::vector ports_; + uint32_t candidate_filter_ = CF_ALL; + // Whether to prune low-priority ports, taken from the port allocator. + bool prune_turn_ports_; + SessionState state_ = SessionState::CLEARED; friend class AllocationSequence; }; @@ -244,13 +301,15 @@ class AllocationSequence : public rtc::MessageHandler, PortConfiguration* config, uint32_t flags); ~AllocationSequence(); - bool Init(); + void Init(); void Clear(); - void OnNetworkRemoved(); + void OnNetworkFailed(); State state() const { return state_; } - const rtc::Network* network() const { return network_; } - bool network_removed() const { return network_removed_; } + rtc::Network* network() const { return network_; } + + bool network_failed() const { return network_failed_; } + void set_network_failed() { network_failed_ = true; } // Disables the phases for a new sequence that this one already covers for an // equivalent network setup. @@ -300,7 +359,7 @@ class AllocationSequence : public rtc::MessageHandler, void OnPortDestroyed(PortInterface* port); BasicPortAllocatorSession* session_; - bool network_removed_ = false; + bool network_failed_ = false; rtc::Network* network_; rtc::IPAddress ip_; PortConfiguration* config_; diff --git a/include/webrtc/p2p/client/httpportallocator.h b/include/webrtc/p2p/client/httpportallocator.h deleted file mode 100644 index e527659..0000000 --- a/include/webrtc/p2p/client/httpportallocator.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_P2P_CLIENT_HTTPPORTALLOCATOR_H_ -#define WEBRTC_P2P_CLIENT_HTTPPORTALLOCATOR_H_ - -#include -#include -#include - -#include "webrtc/p2p/client/basicportallocator.h" - -class HttpPortAllocatorTest_TestSessionRequestUrl_Test; - -namespace rtc { -class AsyncHttpRequest; -class SignalThread; -} - -namespace cricket { - -// TODO(pthatcher): Remove this. It's only used by chromoting, so we -// should just move this code there. It's used in these places in -// chromium: -// src/remoting/protocol/chromium_port_allocator.cc -// src/remoting/client/plugin/pepper_port_allocator.cc -// src/remoting/protocol/libjingle_transport_factory.cc -class HttpPortAllocatorBase : public BasicPortAllocator { - public: - // The number of HTTP requests we should attempt before giving up. - static const int kNumRetries; - - // Records the URL that we will GET in order to create a session. - static const char kCreateSessionURL[]; - - HttpPortAllocatorBase(rtc::NetworkManager* network_manager, - const std::string& user_agent); - HttpPortAllocatorBase(rtc::NetworkManager* network_manager, - rtc::PacketSocketFactory* socket_factory, - const std::string& user_agent); - virtual ~HttpPortAllocatorBase(); - - // CreateSession is defined in BasicPortAllocator but is - // redefined here as pure virtual. - virtual PortAllocatorSession* CreateSessionInternal( - const std::string& content_name, - int component, - const std::string& ice_ufrag, - const std::string& ice_pwd) = 0; - - void SetStunHosts(const std::vector& hosts) { - if (!hosts.empty()) { - stun_hosts_ = hosts; - } - } - void SetRelayHosts(const std::vector& hosts) { - if (!hosts.empty()) { - relay_hosts_ = hosts; - } - } - void SetRelayToken(const std::string& relay) { relay_token_ = relay; } - - const std::vector& stun_hosts() const { - return stun_hosts_; - } - - const std::vector& relay_hosts() const { - return relay_hosts_; - } - - const std::string& relay_token() const { - return relay_token_; - } - - const std::string& user_agent() const { - return agent_; - } - - private: - std::vector stun_hosts_; - std::vector relay_hosts_; - std::string relay_token_; - std::string agent_; -}; - -class RequestData; - -class HttpPortAllocatorSessionBase : public BasicPortAllocatorSession { - public: - HttpPortAllocatorSessionBase( - HttpPortAllocatorBase* allocator, - const std::string& content_name, - int component, - const std::string& ice_ufrag, - const std::string& ice_pwd, - const std::vector& stun_hosts, - const std::vector& relay_hosts, - const std::string& relay, - const std::string& agent); - virtual ~HttpPortAllocatorSessionBase(); - - const std::string& relay_token() const { - return relay_token_; - } - - const std::string& user_agent() const { - return agent_; - } - - virtual void SendSessionRequest(const std::string& host, int port) = 0; - virtual void ReceiveSessionResponse(const std::string& response); - - // Made public for testing. Should be protected. - std::string GetSessionRequestUrl(); - - protected: - virtual void GetPortConfigurations(); - void TryCreateRelaySession(); - virtual HttpPortAllocatorBase* allocator() { - return static_cast( - BasicPortAllocatorSession::allocator()); - } - - private: - std::vector relay_hosts_; - std::vector stun_hosts_; - std::string relay_token_; - std::string agent_; - int attempts_; -}; - -} // namespace cricket - -#endif // WEBRTC_P2P_CLIENT_HTTPPORTALLOCATOR_H_ diff --git a/include/webrtc/p2p/client/socketmonitor.h b/include/webrtc/p2p/client/socketmonitor.h index eb11516..b13be74 100644 --- a/include/webrtc/p2p/client/socketmonitor.h +++ b/include/webrtc/p2p/client/socketmonitor.h @@ -16,7 +16,7 @@ #include "webrtc/base/criticalsection.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" -#include "webrtc/p2p/base/transport.h" // for ConnectionInfos +#include "webrtc/p2p/base/jseptransport.h" // for ConnectionInfos // TODO(pthatcher): Move these to connectionmonitor.h and // connectionmonitor.cc, or just move them into channel.cc @@ -33,7 +33,7 @@ class ConnectionMonitor : public rtc::MessageHandler, public sigslot::has_slots<> { public: ConnectionMonitor(ConnectionStatsGetter* stats_getter, - rtc::Thread* worker_thread, + rtc::Thread* network_thread, rtc::Thread* monitoring_thread); ~ConnectionMonitor(); @@ -50,7 +50,7 @@ class ConnectionMonitor : public rtc::MessageHandler, std::vector connection_infos_; ConnectionStatsGetter* stats_getter_; - rtc::Thread* worker_thread_; + rtc::Thread* network_thread_; rtc::Thread* monitoring_thread_; rtc::CriticalSection crit_; uint32_t rate_; diff --git a/include/webrtc/p2p/quic/quictransport.h b/include/webrtc/p2p/quic/quictransport.h index 14bd13f..5e834e0 100644 --- a/include/webrtc/p2p/quic/quictransport.h +++ b/include/webrtc/p2p/quic/quictransport.h @@ -15,7 +15,7 @@ #include #include -#include "webrtc/p2p/base/transport.h" +#include "webrtc/p2p/base/jseptransport.h" #include "webrtc/p2p/quic/quictransportchannel.h" namespace cricket { @@ -23,7 +23,11 @@ namespace cricket { class P2PTransportChannel; class PortAllocator; -// TODO(mikescarlett): Refactor to avoid code duplication with DtlsTransport. +// TODO(deadbeef): To get QUIC working with TransportController again, would +// need to merge this class with Transport (or make separate DTLS/QUIC +// subclasses). The only difference between the two (as of typing this) is that +// the QUIC channel *requires* a fingerprint, whereas the DTLS channel can +// operate in a passthrough mode when SDES is used. class QuicTransport : public Transport { public: QuicTransport(const std::string& name, diff --git a/include/webrtc/p2p/quic/quictransportchannel.h b/include/webrtc/p2p/quic/quictransportchannel.h index dec24d2..0e5af88 100644 --- a/include/webrtc/p2p/quic/quictransportchannel.h +++ b/include/webrtc/p2p/quic/quictransportchannel.h @@ -142,13 +142,11 @@ class QuicTransportChannel : public TransportChannelImpl, void SetIceTiebreaker(uint64_t tiebreaker) override { channel_->SetIceTiebreaker(tiebreaker); } - void SetIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - channel_->SetIceCredentials(ice_ufrag, ice_pwd); + void SetIceParameters(const IceParameters& ice_params) override { + channel_->SetIceParameters(ice_params); } - void SetRemoteIceCredentials(const std::string& ice_ufrag, - const std::string& ice_pwd) override { - channel_->SetRemoteIceCredentials(ice_ufrag, ice_pwd); + void SetRemoteIceParameters(const IceParameters& ice_params) override { + channel_->SetRemoteIceParameters(ice_params); } void SetRemoteIceMode(IceMode mode) override { channel_->SetRemoteIceMode(mode); @@ -166,9 +164,6 @@ class QuicTransportChannel : public TransportChannelImpl, void SetIceConfig(const IceConfig& config) override { channel_->SetIceConfig(config); } - void Connect() override { - channel_->Connect(); - } // QuicPacketWriter overrides. // Called from net::QuicConnection when |quic_| has packets to write. @@ -204,6 +199,10 @@ class QuicTransportChannel : public TransportChannelImpl, void OnProofVerifyDetailsAvailable( const net::ProofVerifyDetails& verify_details) override; + void SetMetricsObserver(webrtc::MetricsObserverInterface* observer) override { + channel_->SetMetricsObserver(observer); + } + // Returns true if |quic_| has queued data which wasn't written due // to |channel_| being write blocked. bool HasDataToWrite() const; @@ -214,6 +213,8 @@ class QuicTransportChannel : public TransportChannelImpl, // Creates a new QUIC stream that can send data. ReliableQuicStream* CreateQuicStream(); + TransportChannelImpl* ice_transport_channel() { return channel_.get(); } + // Emitted when |quic_| creates a QUIC stream to receive data from the remote // peer, when the stream did not exist previously. sigslot::signal1 SignalIncomingStream; @@ -246,8 +247,9 @@ class QuicTransportChannel : public TransportChannelImpl, void OnSelectedCandidatePairChanged( TransportChannel* channel, CandidatePairInterface* selected_candidate_pair, - int last_sent_packet_id); - void OnConnectionRemoved(TransportChannelImpl* channel); + int last_sent_packet_id, + bool ready_to_send); + void OnChannelStateChanged(TransportChannelImpl* channel); // Callbacks for |quic_|. // Called when |quic_| has established the crypto handshake. @@ -269,7 +271,7 @@ class QuicTransportChannel : public TransportChannelImpl, void set_quic_state(QuicTransportState state); // Everything should occur on this thread. - rtc::Thread* worker_thread_; + rtc::Thread* network_thread_; // Underlying channel which is responsible for connecting with the remote peer // and sending/receiving packets across the network. std::unique_ptr channel_; diff --git a/include/webrtc/api/audiotrack.h b/include/webrtc/pc/audiotrack.h similarity index 92% rename from include/webrtc/api/audiotrack.h rename to include/webrtc/pc/audiotrack.h index 096caf9..33f4b1f 100644 --- a/include/webrtc/api/audiotrack.h +++ b/include/webrtc/pc/audiotrack.h @@ -8,17 +8,17 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_AUDIOTRACK_H_ -#define WEBRTC_API_AUDIOTRACK_H_ +#ifndef WEBRTC_PC_AUDIOTRACK_H_ +#define WEBRTC_PC_AUDIOTRACK_H_ #include #include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/mediastreamtrack.h" #include "webrtc/api/notifier.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread_checker.h" +#include "webrtc/pc/mediastreamtrack.h" namespace webrtc { @@ -56,4 +56,4 @@ class AudioTrack : public MediaStreamTrack, } // namespace webrtc -#endif // WEBRTC_API_AUDIOTRACK_H_ +#endif // WEBRTC_PC_AUDIOTRACK_H_ diff --git a/include/webrtc/pc/channel.h b/include/webrtc/pc/channel.h index d9f5fd6..6ff0556 100644 --- a/include/webrtc/pc/channel.h +++ b/include/webrtc/pc/channel.h @@ -18,7 +18,7 @@ #include #include -#include "webrtc/audio_sink.h" +#include "webrtc/api/call/audio_sink.h" #include "webrtc/base/asyncinvoker.h" #include "webrtc/base/asyncudpsocket.h" #include "webrtc/base/criticalsection.h" @@ -30,6 +30,8 @@ #include "webrtc/media/base/streamparams.h" #include "webrtc/media/base/videosinkinterface.h" #include "webrtc/media/base/videosourceinterface.h" +#include "webrtc/p2p/base/dtlstransportinternal.h" +#include "webrtc/p2p/base/packettransportinternal.h" #include "webrtc/p2p/base/transportcontroller.h" #include "webrtc/p2p/client/socketmonitor.h" #include "webrtc/pc/audiomonitor.h" @@ -48,15 +50,16 @@ namespace cricket { struct CryptoParams; class MediaContentDescription; -// BaseChannel contains logic common to voice and video, including -// enable, marshaling calls to a worker and network threads, and -// connection and media monitors. +// BaseChannel contains logic common to voice and video, including enable, +// marshaling calls to a worker and network threads, and connection and media +// monitors. +// // BaseChannel assumes signaling and other threads are allowed to make // synchronous calls to the worker thread, the worker thread makes synchronous // calls only to the network thread, and the network thread can't be blocked by // other threads. // All methods with _n suffix must be called on network thread, -// methods with _w suffix - on worker thread +// methods with _w suffix on worker thread // and methods with _s suffix on signaling thread. // Network and worker threads may be the same thread. // @@ -70,14 +73,20 @@ class BaseChannel public MediaChannel::NetworkInterface, public ConnectionStatsGetter { public: + // If |srtp_required| is true, the channel will not send or receive any + // RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP). BaseChannel(rtc::Thread* worker_thread, rtc::Thread* network_thread, + rtc::Thread* signaling_thread, MediaChannel* channel, - TransportController* transport_controller, const std::string& content_name, - bool rtcp); + bool rtcp_mux_required, + bool srtp_required); virtual ~BaseChannel(); - bool Init_w(const std::string* bundle_transport_name); + bool Init_w(DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport); // Deinit may be called multiple times and is simply ignored if it's already // done. void Deinit(); @@ -85,6 +94,7 @@ class BaseChannel rtc::Thread* worker_thread() const { return worker_thread_; } rtc::Thread* network_thread() const { return network_thread_; } const std::string& content_name() const { return content_name_; } + // TODO(deadbeef): This is redundant; remove this. const std::string& transport_name() const { return transport_name_; } bool enabled() const { return enabled_; } @@ -94,17 +104,21 @@ class BaseChannel // DTLS-based keying. If you turned off SRTP later, however // you could have secure() == false and dtls_secure() == true. bool secure_dtls() const { return dtls_keyed_; } - // This function returns true if we require secure channel for call setup. - bool secure_required() const { return secure_required_; } bool writable() const { return writable_; } - // Activate RTCP mux, regardless of the state so far. Once - // activated, it can not be deactivated, and if the remote - // description doesn't support RTCP mux, setting the remote - // description will fail. - void ActivateRtcpMux(); - bool SetTransport(const std::string& transport_name); + // Set the transport(s), and update writability and "ready-to-send" state. + // |rtp_transport| must be non-null. + // |rtcp_transport| must be supplied if NeedsRtcpTransport() is true (meaning + // RTCP muxing is not fully active yet). + // |rtp_transport| and |rtcp_transport| must share the same transport name as + // well. + // Can not start with "rtc::PacketTransportInternal" and switch to + // "DtlsTransportInternal", or vice-versa. + void SetTransports(DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport); + void SetTransports(rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport); bool PushdownLocalDescription(const SessionDescription* local_desc, ContentAction action, std::string* error_desc); @@ -142,24 +156,41 @@ class BaseChannel return remote_streams_; } - sigslot::signal2 SignalDtlsSetupFailure; - void SignalDtlsSetupFailure_n(bool rtcp); - void SignalDtlsSetupFailure_s(bool rtcp); + sigslot::signal2 SignalDtlsSrtpSetupFailure; + void SignalDtlsSrtpSetupFailure_n(bool rtcp); + void SignalDtlsSrtpSetupFailure_s(bool rtcp); // Used for latency measurements. sigslot::signal1 SignalFirstPacketReceived; - // Forward TransportChannel SignalSentPacket to worker thread. + // Forward SignalSentPacket to worker thread. sigslot::signal1 SignalSentPacket; + // Emitted whenever rtcp-mux is fully negotiated and the rtcp-transport can + // be destroyed. + // Fired on the network thread. + sigslot::signal1 SignalRtcpMuxFullyActive; + // Only public for unit tests. Otherwise, consider private. - TransportChannel* transport_channel() const { return transport_channel_; } - TransportChannel* rtcp_transport_channel() const { - return rtcp_transport_channel_; + DtlsTransportInternal* rtp_dtls_transport() const { + return rtp_dtls_transport_; + } + DtlsTransportInternal* rtcp_dtls_transport() const { + return rtcp_dtls_transport_; } + bool NeedsRtcpTransport(); + // Made public for easier testing. - void SetReadyToSend(bool rtcp, bool ready); + // + // Updates "ready to send" for an individual channel, and informs the media + // channel that the transport is ready to send if each channel (in use) is + // ready to send. This is more specific than just "writable"; it means the + // last send didn't return ENOTCONN. + // + // This should be called whenever a channel's ready-to-send state changes, + // or when RTCP muxing becomes active/inactive. + void SetTransportChannelReadyToSend(bool rtcp, bool ready); // Only public for unit tests. Otherwise, consider protected. int SetOption(SocketType type, rtc::Socket::Option o, int val) @@ -168,15 +199,26 @@ class BaseChannel SrtpFilter* srtp_filter() { return &srtp_filter_; } + virtual cricket::MediaType media_type() = 0; + + bool SetCryptoOptions(const rtc::CryptoOptions& crypto_options); + + // This function returns true if we require SRTP for call setup. + bool srtp_required_for_testing() const { return srtp_required_; } + protected: virtual MediaChannel* media_channel() const { return media_channel_; } - // Sets the |transport_channel_| (and |rtcp_transport_channel_|, if |rtcp_| is - // true). Gets the transport channels from |transport_controller_|. - bool SetTransport_n(const std::string& transport_name); - void SetTransportChannel_n(TransportChannel* transport); - void SetRtcpTransportChannel_n(TransportChannel* transport, - bool update_writablity); + void SetTransports_n(DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport); + + // This does not update writability or "ready-to-send" state; it just + // disconnects from the old channel and connects to the new one. + void SetTransport_n(bool rtcp, + DtlsTransportInternal* new_dtls_transport, + rtc::PacketTransportInternal* new_packet_transport); bool was_ever_writable() const { return was_ever_writable_; } void set_local_content_direction(MediaContentDirection direction) { @@ -185,18 +227,24 @@ class BaseChannel void set_remote_content_direction(MediaContentDirection direction) { remote_content_direction_ = direction; } - void set_secure_required(bool secure_required) { - secure_required_ = secure_required; - } - bool IsReadyToReceive_w() const; - bool IsReadyToSend_w() const; - rtc::Thread* signaling_thread() { - return transport_controller_->signaling_thread(); - } - bool rtcp_transport_enabled() const { return rtcp_transport_enabled_; } - - void ConnectToTransportChannel(TransportChannel* tc); - void DisconnectFromTransportChannel(TransportChannel* tc); + // These methods verify that: + // * The required content description directions have been set. + // * The channel is enabled. + // * And for sending: + // - The SRTP filter is active if it's needed. + // - The transport has been writable before, meaning it should be at least + // possible to succeed in sending a packet. + // + // When any of these properties change, UpdateMediaSendRecvState_w should be + // called. + bool IsReadyToReceiveMedia_w() const; + bool IsReadyToSendMedia_w() const; + rtc::Thread* signaling_thread() { return signaling_thread_; } + + void ConnectToDtlsTransport(DtlsTransportInternal* transport); + void DisconnectFromDtlsTransport(DtlsTransportInternal* transport); + void ConnectToPacketTransport(rtc::PacketTransportInternal* transport); + void DisconnectFromPacketTransport(rtc::PacketTransportInternal* transport); void FlushRtcpMessages_n(); @@ -207,28 +255,30 @@ class BaseChannel const rtc::PacketOptions& options) override; // From TransportChannel - void OnWritableState(TransportChannel* channel); - virtual void OnChannelRead(TransportChannel* channel, - const char* data, - size_t len, - const rtc::PacketTime& packet_time, - int flags); - void OnReadyToSend(TransportChannel* channel); + void OnWritableState(rtc::PacketTransportInternal* transport); + virtual void OnPacketRead(rtc::PacketTransportInternal* transport, + const char* data, + size_t len, + const rtc::PacketTime& packet_time, + int flags); + void OnReadyToSend(rtc::PacketTransportInternal* transport); - void OnDtlsState(TransportChannel* channel, DtlsTransportState state); + void OnDtlsState(DtlsTransportInternal* transport, DtlsTransportState state); void OnSelectedCandidatePairChanged( - TransportChannel* channel, + IceTransportInternal* ice_transport, CandidatePairInterface* selected_candidate_pair, - int last_sent_packet_id); + int last_sent_packet_id, + bool ready_to_send); - bool PacketIsRtcp(const TransportChannel* channel, const char* data, + bool PacketIsRtcp(const rtc::PacketTransportInternal* transport, + const char* data, size_t len); bool SendPacket(bool rtcp, rtc::CopyOnWriteBuffer* packet, const rtc::PacketOptions& options); - virtual bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet); + bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet); void HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time); void OnPacketReceived(bool rtcp, @@ -237,23 +287,31 @@ class BaseChannel void EnableMedia_w(); void DisableMedia_w(); + + // Performs actions if the RTP/RTCP writable state changed. This should + // be called whenever a channel's writable state changes or when RTCP muxing + // becomes active/inactive. void UpdateWritableState_n(); void ChannelWritable_n(); void ChannelNotWritable_n(); + bool AddRecvStream_w(const StreamParams& sp); bool RemoveRecvStream_w(uint32_t ssrc); bool AddSendStream_w(const StreamParams& sp); bool RemoveSendStream_w(uint32_t ssrc); - virtual bool ShouldSetupDtlsSrtp_n() const; + bool ShouldSetupDtlsSrtp_n() const; // Do the DTLS key expansion and impose it on the SRTP/SRTCP filters. // |rtcp_channel| indicates whether to set up the RTP or RTCP filter. - bool SetupDtlsSrtp_n(bool rtcp_channel); + bool SetupDtlsSrtp_n(bool rtcp); void MaybeSetupDtlsSrtp_n(); // Set the DTLS-SRTP cipher policy on this channel as appropriate. - bool SetDtlsSrtpCryptoSuites_n(TransportChannel* tc, bool rtcp); + bool SetDtlsSrtpCryptoSuites_n(DtlsTransportInternal* transport, bool rtcp); - void ChangeState(); - virtual void ChangeState_w() = 0; + // Should be called whenever the conditions for + // IsReadyToReceiveMedia/IsReadyToSendMedia are satisfied (or unsatisfied). + // Updates the send/recv state of the media channel. + void UpdateMediaSendRecvState(); + virtual void UpdateMediaSendRecvState_w() = 0; // Gets the content info appropriate to the channel (audio or video). virtual const ContentInfo* GetFirstContent( @@ -282,7 +340,7 @@ class BaseChannel // Helper method to get RTP Absoulute SendTime extension header id if // present in remote supported extensions list. void MaybeCacheRtpAbsSendTimeHeaderExtension_w( - const std::vector& extensions); + const std::vector& extensions); bool CheckSrtpConfig_n(const std::vector& cryptos, bool* dtls, @@ -291,7 +349,6 @@ class BaseChannel ContentAction action, ContentSource src, std::string* error_desc); - void ActivateRtcpMux_n(); bool SetRtcpMux_n(bool enable, ContentAction action, ContentSource src, @@ -300,6 +357,10 @@ class BaseChannel // From MessageHandler void OnMessage(rtc::Message* pmsg) override; + const rtc::CryptoOptions& crypto_options() const { + return crypto_options_; + } + // Handled in derived classes // Get the SRTP crypto suites to use for RTP media virtual void GetSrtpCryptoSuites_n(std::vector* crypto_suites) const = 0; @@ -308,57 +369,73 @@ class BaseChannel // Helper function for invoking bool-returning methods on the worker thread. template - bool InvokeOnWorker(const FunctorT& functor) { - return worker_thread_->Invoke(functor); + bool InvokeOnWorker(const rtc::Location& posted_from, + const FunctorT& functor) { + return worker_thread_->Invoke(posted_from, functor); } private: - bool InitNetwork_n(const std::string* bundle_transport_name); + bool InitNetwork_n(DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport); void DisconnectTransportChannels_n(); - void DestroyTransportChannels_n(); - void SignalSentPacket_n(TransportChannel* channel, + void SignalSentPacket_n(rtc::PacketTransportInternal* transport, const rtc::SentPacket& sent_packet); void SignalSentPacket_w(const rtc::SentPacket& sent_packet); - bool IsTransportReadyToSend_n() const; + bool IsReadyToSendMedia_n() const; void CacheRtpAbsSendTimeHeaderExtension_n(int rtp_abs_sendtime_extn_id); + int GetTransportOverheadPerPacket() const; + void UpdateTransportOverhead(); rtc::Thread* const worker_thread_; rtc::Thread* const network_thread_; + rtc::Thread* const signaling_thread_; rtc::AsyncInvoker invoker_; const std::string content_name_; std::unique_ptr connection_monitor_; - // Transport related members that should be accessed from network thread. - TransportController* const transport_controller_; + // Won't be set when using raw packet transports. SDP-specific thing. std::string transport_name_; - bool rtcp_transport_enabled_; - TransportChannel* transport_channel_; + // True if RTCP-multiplexing is required. In other words, no standalone RTCP + // transport will ever be used for this channel. + const bool rtcp_mux_required_; + + // Separate DTLS/non-DTLS pointers to support using BaseChannel without DTLS. + // Temporary measure until more refactoring is done. + // If non-null, "X_dtls_transport_" will always equal "X_packet_transport_". + DtlsTransportInternal* rtp_dtls_transport_ = nullptr; + DtlsTransportInternal* rtcp_dtls_transport_ = nullptr; + rtc::PacketTransportInternal* rtp_packet_transport_ = nullptr; + rtc::PacketTransportInternal* rtcp_packet_transport_ = nullptr; std::vector > socket_options_; - TransportChannel* rtcp_transport_channel_; std::vector > rtcp_socket_options_; SrtpFilter srtp_filter_; RtcpMuxFilter rtcp_mux_filter_; BundleFilter bundle_filter_; - bool rtp_ready_to_send_; - bool rtcp_ready_to_send_; - bool writable_; - bool was_ever_writable_; - bool has_received_packet_; - bool dtls_keyed_; - bool secure_required_; - int rtp_abs_sendtime_extn_id_; - - // MediaChannel related members that should be access from worker thread. + bool rtp_ready_to_send_ = false; + bool rtcp_ready_to_send_ = false; + bool writable_ = false; + bool was_ever_writable_ = false; + bool has_received_packet_ = false; + bool dtls_keyed_ = false; + const bool srtp_required_ = true; + rtc::CryptoOptions crypto_options_; + int rtp_abs_sendtime_extn_id_ = -1; + + // MediaChannel related members that should be accessed from the worker + // thread. MediaChannel* const media_channel_; - // Currently enabled_ flag accessed from signaling thread too, but it can - // be changed only when signaling thread does sunchronious call to worker - // thread, so it should be safe. - bool enabled_; + // Currently the |enabled_| flag is accessed from the signaling thread as + // well, but it can be changed only when signaling thread does a synchronous + // call to the worker thread, so it should be safe. + bool enabled_ = false; std::vector local_streams_; std::vector remote_streams_; - MediaContentDirection local_content_direction_; - MediaContentDirection remote_content_direction_; + MediaContentDirection local_content_direction_ = MD_INACTIVE; + MediaContentDirection remote_content_direction_ = MD_INACTIVE; + CandidatePairInterface* selected_candidate_pair_; }; // VoiceChannel is a specialization that adds support for early media, DTMF, @@ -367,13 +444,13 @@ class VoiceChannel : public BaseChannel { public: VoiceChannel(rtc::Thread* worker_thread, rtc::Thread* network_thread, + rtc::Thread* signaling_thread, MediaEngineInterface* media_engine, VoiceMediaChannel* channel, - TransportController* transport_controller, const std::string& content_name, - bool rtcp); + bool rtcp_mux_required, + bool srtp_required); ~VoiceChannel(); - bool Init_w(const std::string* bundle_transport_name); // Configure sending media on the stream with SSRC |ssrc| // If there is only one sending stream SSRC 0 can be used. @@ -435,15 +512,16 @@ class VoiceChannel : public BaseChannel { webrtc::RtpParameters GetRtpReceiveParameters_w(uint32_t ssrc) const; bool SetRtpReceiveParameters_w(uint32_t ssrc, webrtc::RtpParameters parameters); + cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_AUDIO; } private: // overrides from BaseChannel - void OnChannelRead(TransportChannel* channel, - const char* data, - size_t len, - const rtc::PacketTime& packet_time, - int flags) override; - void ChangeState_w() override; + void OnPacketRead(rtc::PacketTransportInternal* transport, + const char* data, + size_t len, + const rtc::PacketTime& packet_time, + int flags) override; + void UpdateMediaSendRecvState_w() override; const ContentInfo* GetFirstContent(const SessionDescription* sdesc) override; bool SetLocalContent_w(const MediaContentDescription* content, ContentAction action, @@ -483,24 +561,21 @@ class VoiceChannel : public BaseChannel { class VideoChannel : public BaseChannel { public: VideoChannel(rtc::Thread* worker_thread, - rtc::Thread* netwokr_thread, + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, VideoMediaChannel* channel, - TransportController* transport_controller, const std::string& content_name, - bool rtcp); + bool rtcp_mux_required, + bool srtp_required); ~VideoChannel(); - bool Init_w(const std::string* bundle_transport_name); // downcasts a MediaChannel VideoMediaChannel* media_channel() const override { return static_cast(BaseChannel::media_channel()); } - bool SetSink(uint32_t ssrc, rtc::VideoSinkInterface* sink); - // Register a source. The |ssrc| must correspond to a registered - // send stream. - void SetSource(uint32_t ssrc, - rtc::VideoSourceInterface* source); + bool SetSink(uint32_t ssrc, + rtc::VideoSinkInterface* sink); // Get statistics about the current media session. bool GetStats(VideoMediaInfo* stats); @@ -511,17 +586,23 @@ class VideoChannel : public BaseChannel { void StopMediaMonitor(); sigslot::signal2 SignalMediaMonitor; - bool SetVideoSend(uint32_t ssrc, bool enable, const VideoOptions* options); + // Register a source and set options. + // The |ssrc| must correspond to a registered send stream. + bool SetVideoSend(uint32_t ssrc, + bool enable, + const VideoOptions* options, + rtc::VideoSourceInterface* source); webrtc::RtpParameters GetRtpSendParameters(uint32_t ssrc) const; bool SetRtpSendParameters(uint32_t ssrc, const webrtc::RtpParameters& parameters); webrtc::RtpParameters GetRtpReceiveParameters(uint32_t ssrc) const; bool SetRtpReceiveParameters(uint32_t ssrc, const webrtc::RtpParameters& parameters); + cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_VIDEO; } private: // overrides from BaseChannel - void ChangeState_w() override; + void UpdateMediaSendRecvState_w() override; const ContentInfo* GetFirstContent(const SessionDescription* sdesc) override; bool SetLocalContent_w(const MediaContentDescription* content, ContentAction action, @@ -554,17 +635,21 @@ class VideoChannel : public BaseChannel { VideoRecvParameters last_recv_params_; }; -// DataChannel is a specialization for data. -class DataChannel : public BaseChannel { +// RtpDataChannel is a specialization for data. +class RtpDataChannel : public BaseChannel { public: - DataChannel(rtc::Thread* worker_thread, - rtc::Thread* network_thread, - DataMediaChannel* media_channel, - TransportController* transport_controller, - const std::string& content_name, - bool rtcp); - ~DataChannel(); - bool Init_w(const std::string* bundle_transport_name); + RtpDataChannel(rtc::Thread* worker_thread, + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + DataMediaChannel* channel, + const std::string& content_name, + bool rtcp_mux_required, + bool srtp_required); + ~RtpDataChannel(); + bool Init_w(DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport); virtual bool SendData(const SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, @@ -578,17 +663,17 @@ class DataChannel : public BaseChannel { return ready_to_send_data_; } - sigslot::signal2 SignalMediaMonitor; - sigslot::signal2&> + sigslot::signal2 SignalMediaMonitor; + sigslot::signal2&> SignalConnectionMonitor; - sigslot::signal3 SignalDataReceived; + + sigslot::signal2 + SignalDataReceived; // Signal for notifying when the channel becomes ready to send data. // That occurs when the channel is enabled, the transport is writable, // both local and remote descriptions are set, and the channel is unblocked. sigslot::signal1 SignalReadyToSendData; - // Signal for notifying that the remote side has closed the DataChannel. - sigslot::signal1 SignalStreamClosedRemotely; + cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_DATA; } protected: // downcasts a MediaChannel. @@ -630,23 +715,16 @@ class DataChannel : public BaseChannel { // overrides from BaseChannel const ContentInfo* GetFirstContent(const SessionDescription* sdesc) override; - // If data_channel_type_ is DCT_NONE, set it. Otherwise, check that - // it's the same as what was set previously. Returns false if it's - // set to one type one type and changed to another type later. - bool SetDataChannelType(DataChannelType new_data_channel_type, - std::string* error_desc); - // Same as SetDataChannelType, but extracts the type from the - // DataContentDescription. - bool SetDataChannelTypeFromContent(const DataContentDescription* content, - std::string* error_desc); + // Checks that data channel type is RTP. + bool CheckDataChannelTypeFromContent(const DataContentDescription* content, + std::string* error_desc); bool SetLocalContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) override; bool SetRemoteContent_w(const MediaContentDescription* content, ContentAction action, std::string* error_desc) override; - void ChangeState_w() override; - bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) override; + void UpdateMediaSendRecvState_w() override; void OnMessage(rtc::Message* pmsg) override; void GetSrtpCryptoSuites_n(std::vector* crypto_suites) const override; @@ -655,18 +733,13 @@ class DataChannel : public BaseChannel { const std::vector& infos) override; void OnMediaMonitorUpdate(DataMediaChannel* media_channel, const DataMediaInfo& info); - bool ShouldSetupDtlsSrtp_n() const override; void OnDataReceived( const ReceiveDataParams& params, const char* data, size_t len); void OnDataChannelError(uint32_t ssrc, DataMediaChannel::Error error); void OnDataChannelReadyToSend(bool writable); - void OnStreamClosedRemotely(uint32_t sid); std::unique_ptr media_monitor_; - // TODO(pthatcher): Make a separate SctpDataChannel and - // RtpDataChannel instead of using this. - DataChannelType data_channel_type_; - bool ready_to_send_data_; + bool ready_to_send_data_ = false; // Last DataSendParameters sent down to the media_channel() via // SetSendParameters. diff --git a/include/webrtc/pc/channelmanager.h b/include/webrtc/pc/channelmanager.h index 3b0c0e9..b763fa1 100644 --- a/include/webrtc/pc/channelmanager.h +++ b/include/webrtc/pc/channelmanager.h @@ -38,13 +38,12 @@ class VoiceChannel; class ChannelManager { public: // For testing purposes. Allows the media engine and data media - // engine and dev manager to be mocks. The ChannelManager takes - // ownership of these objects. - ChannelManager(MediaEngineInterface* me, - DataEngineInterface* dme, + // engine and dev manager to be mocks. + ChannelManager(std::unique_ptr me, + std::unique_ptr dme, rtc::Thread* worker_and_network); // Same as above, but gives an easier default DataEngine. - ChannelManager(MediaEngineInterface* me, + ChannelManager(std::unique_ptr me, rtc::Thread* worker, rtc::Thread* network); ~ChannelManager(); @@ -72,7 +71,8 @@ class ChannelManager { // Retrieves the list of supported audio & video codec types. // Can be called before starting the media engine. - void GetSupportedAudioCodecs(std::vector* codecs) const; + void GetSupportedAudioSendCodecs(std::vector* codecs) const; + void GetSupportedAudioReceiveCodecs(std::vector* codecs) const; void GetSupportedAudioRtpHeaderExtensions(RtpHeaderExtensions* ext) const; void GetSupportedVideoCodecs(std::vector* codecs) const; void GetSupportedVideoRtpHeaderExtensions(RtpHeaderExtensions* ext) const; @@ -89,10 +89,20 @@ class ChannelManager { // Creates a voice channel, to be associated with the specified session. VoiceChannel* CreateVoiceChannel( webrtc::MediaControllerInterface* media_controller, - TransportController* transport_controller, + DtlsTransportInternal* rtp_transport, + DtlsTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, + bool srtp_required, + const AudioOptions& options); + // Version of the above that takes PacketTransportInternal. + VoiceChannel* CreateVoiceChannel( + webrtc::MediaControllerInterface* media_controller, + rtc::PacketTransportInternal* rtp_transport, + rtc::PacketTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, + const std::string& content_name, + bool srtp_required, const AudioOptions& options); // Destroys a voice channel created with the Create API. void DestroyVoiceChannel(VoiceChannel* voice_channel); @@ -100,32 +110,46 @@ class ChannelManager { // associated with the specified session. VideoChannel* CreateVideoChannel( webrtc::MediaControllerInterface* media_controller, - TransportController* transport_controller, + DtlsTransportInternal* rtp_transport, + DtlsTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, + const std::string& content_name, + bool srtp_required, + const VideoOptions& options); + // Version of the above that takes PacketTransportInternal. + VideoChannel* CreateVideoChannel( + webrtc::MediaControllerInterface* media_controller, + rtc::PacketTransportInternal* rtp_transport, + rtc::PacketTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, + bool srtp_required, const VideoOptions& options); // Destroys a video channel created with the Create API. void DestroyVideoChannel(VideoChannel* video_channel); - DataChannel* CreateDataChannel(TransportController* transport_controller, - const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, - DataChannelType data_channel_type); + RtpDataChannel* CreateRtpDataChannel( + webrtc::MediaControllerInterface* media_controller, + DtlsTransportInternal* rtp_transport, + DtlsTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, + const std::string& content_name, + bool srtp_required); // Destroys a data channel created with the Create API. - void DestroyDataChannel(DataChannel* data_channel); + void DestroyRtpDataChannel(RtpDataChannel* data_channel); // Indicates whether any channels exist. bool has_channels() const { return (!voice_channels_.empty() || !video_channels_.empty()); } - bool GetOutputVolume(int* level); - bool SetOutputVolume(int level); // RTX will be enabled/disabled in engines that support it. The supporting // engines will start offering an RTX codec. Must be called before Init(). bool SetVideoRtxEnabled(bool enable); + // Define crypto options to set on newly created channels. Doesn't change + // options on already created channels. + bool SetCryptoOptions(const rtc::CryptoOptions& crypto_options); + // Starts/stops the local microphone and enables polling of the input level. bool capturing() const { return capturing_; } @@ -139,46 +163,49 @@ class ChannelManager { // Stops recording AEC dump. void StopAecDump(); - // Starts RtcEventLog using existing file. - bool StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes); - - // Stops logging RtcEventLog. - void StopRtcEventLog(); - private: typedef std::vector VoiceChannels; typedef std::vector VideoChannels; - typedef std::vector DataChannels; + typedef std::vector RtpDataChannels; - void Construct(MediaEngineInterface* me, - DataEngineInterface* dme, + void Construct(std::unique_ptr me, + std::unique_ptr dme, rtc::Thread* worker_thread, rtc::Thread* network_thread); bool InitMediaEngine_w(); void DestructorDeletes_w(); void Terminate_w(); + bool SetCryptoOptions_w(const rtc::CryptoOptions& crypto_options); VoiceChannel* CreateVoiceChannel_w( webrtc::MediaControllerInterface* media_controller, - TransportController* transport_controller, + DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport, + rtc::Thread* signaling_thread, const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, + bool srtp_required, const AudioOptions& options); void DestroyVoiceChannel_w(VoiceChannel* voice_channel); VideoChannel* CreateVideoChannel_w( webrtc::MediaControllerInterface* media_controller, - TransportController* transport_controller, + DtlsTransportInternal* rtp_dtls_transport, + DtlsTransportInternal* rtcp_dtls_transport, + rtc::PacketTransportInternal* rtp_packet_transport, + rtc::PacketTransportInternal* rtcp_packet_transport, + rtc::Thread* signaling_thread, const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, + bool srtp_required, const VideoOptions& options); void DestroyVideoChannel_w(VideoChannel* video_channel); - DataChannel* CreateDataChannel_w(TransportController* transport_controller, - const std::string& content_name, - const std::string* bundle_transport_name, - bool rtcp, - DataChannelType data_channel_type); - void DestroyDataChannel_w(DataChannel* data_channel); + RtpDataChannel* CreateRtpDataChannel_w( + webrtc::MediaControllerInterface* media_controller, + DtlsTransportInternal* rtp_transport, + DtlsTransportInternal* rtcp_transport, + rtc::Thread* signaling_thread, + const std::string& content_name, + bool srtp_required); + void DestroyRtpDataChannel_w(RtpDataChannel* data_channel); std::unique_ptr media_engine_; std::unique_ptr data_media_engine_; @@ -189,10 +216,10 @@ class ChannelManager { VoiceChannels voice_channels_; VideoChannels video_channels_; - DataChannels data_channels_; + RtpDataChannels data_channels_; - int audio_output_volume_; bool enable_rtx_; + rtc::CryptoOptions crypto_options_; bool capturing_; }; diff --git a/include/webrtc/pc/currentspeakermonitor.h b/include/webrtc/pc/currentspeakermonitor.h index 730ded0..14ed876 100644 --- a/include/webrtc/pc/currentspeakermonitor.h +++ b/include/webrtc/pc/currentspeakermonitor.h @@ -14,9 +14,10 @@ #ifndef WEBRTC_PC_CURRENTSPEAKERMONITOR_H_ #define WEBRTC_PC_CURRENTSPEAKERMONITOR_H_ +#include + #include -#include "webrtc/base/basictypes.h" #include "webrtc/base/sigslot.h" namespace cricket { diff --git a/include/webrtc/pc/datachannel.h b/include/webrtc/pc/datachannel.h new file mode 100644 index 0000000..2619a85 --- /dev/null +++ b/include/webrtc/pc/datachannel.h @@ -0,0 +1,298 @@ +/* + * Copyright 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_DATACHANNEL_H_ +#define WEBRTC_PC_DATACHANNEL_H_ + +#include +#include +#include + +#include "webrtc/api/datachannelinterface.h" +#include "webrtc/api/proxy.h" +#include "webrtc/base/messagehandler.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/media/base/mediachannel.h" +#include "webrtc/pc/channel.h" + +namespace webrtc { + +class DataChannel; + +class DataChannelProviderInterface { + public: + // Sends the data to the transport. + virtual bool SendData(const cricket::SendDataParams& params, + const rtc::CopyOnWriteBuffer& payload, + cricket::SendDataResult* result) = 0; + // Connects to the transport signals. + virtual bool ConnectDataChannel(DataChannel* data_channel) = 0; + // Disconnects from the transport signals. + virtual void DisconnectDataChannel(DataChannel* data_channel) = 0; + // Adds the data channel SID to the transport for SCTP. + virtual void AddSctpDataStream(int sid) = 0; + // Removes the data channel SID from the transport for SCTP. + virtual void RemoveSctpDataStream(int sid) = 0; + // Returns true if the transport channel is ready to send data. + virtual bool ReadyToSendData() const = 0; + + protected: + virtual ~DataChannelProviderInterface() {} +}; + +struct InternalDataChannelInit : public DataChannelInit { + enum OpenHandshakeRole { + kOpener, + kAcker, + kNone + }; + // The default role is kOpener because the default |negotiated| is false. + InternalDataChannelInit() : open_handshake_role(kOpener) {} + explicit InternalDataChannelInit(const DataChannelInit& base) + : DataChannelInit(base), open_handshake_role(kOpener) { + // If the channel is externally negotiated, do not send the OPEN message. + if (base.negotiated) { + open_handshake_role = kNone; + } + } + + OpenHandshakeRole open_handshake_role; +}; + +// Helper class to allocate unique IDs for SCTP DataChannels +class SctpSidAllocator { + public: + // Gets the first unused odd/even id based on the DTLS role. If |role| is + // SSL_CLIENT, the allocated id starts from 0 and takes even numbers; + // otherwise, the id starts from 1 and takes odd numbers. + // Returns false if no id can be allocated. + bool AllocateSid(rtc::SSLRole role, int* sid); + + // Attempts to reserve a specific sid. Returns false if it's unavailable. + bool ReserveSid(int sid); + + // Indicates that |sid| isn't in use any more, and is thus available again. + void ReleaseSid(int sid); + + private: + // Checks if |sid| is available to be assigned to a new SCTP data channel. + bool IsSidAvailable(int sid) const; + + std::set used_sids_; +}; + +// DataChannel is a an implementation of the DataChannelInterface based on +// libjingle's data engine. It provides an implementation of unreliable or +// reliabledata channels. Currently this class is specifically designed to use +// both RtpDataEngine and SctpDataEngine. + +// DataChannel states: +// kConnecting: The channel has been created the transport might not yet be +// ready. +// kOpen: The channel have a local SSRC set by a call to UpdateSendSsrc +// and a remote SSRC set by call to UpdateReceiveSsrc and the transport +// has been writable once. +// kClosing: DataChannelInterface::Close has been called or UpdateReceiveSsrc +// has been called with SSRC==0 +// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with +// SSRC==0. +class DataChannel : public DataChannelInterface, + public sigslot::has_slots<>, + public rtc::MessageHandler { + public: + static rtc::scoped_refptr Create( + DataChannelProviderInterface* provider, + cricket::DataChannelType dct, + const std::string& label, + const InternalDataChannelInit& config); + + virtual void RegisterObserver(DataChannelObserver* observer); + virtual void UnregisterObserver(); + + virtual std::string label() const { return label_; } + virtual bool reliable() const; + virtual bool ordered() const { return config_.ordered; } + virtual uint16_t maxRetransmitTime() const { + return config_.maxRetransmitTime; + } + virtual uint16_t maxRetransmits() const { return config_.maxRetransmits; } + virtual std::string protocol() const { return config_.protocol; } + virtual bool negotiated() const { return config_.negotiated; } + virtual int id() const { return config_.id; } + virtual uint64_t buffered_amount() const; + virtual void Close(); + virtual DataState state() const { return state_; } + virtual uint32_t messages_sent() const { return messages_sent_; } + virtual uint64_t bytes_sent() const { return bytes_sent_; } + virtual uint32_t messages_received() const { return messages_received_; } + virtual uint64_t bytes_received() const { return bytes_received_; } + virtual bool Send(const DataBuffer& buffer); + + // rtc::MessageHandler override. + virtual void OnMessage(rtc::Message* msg); + + // Called when the channel's ready to use. That can happen when the + // underlying DataMediaChannel becomes ready, or when this channel is a new + // stream on an existing DataMediaChannel, and we've finished negotiation. + void OnChannelReady(bool writable); + + // Slots for provider to connect signals to. + void OnDataReceived(const cricket::ReceiveDataParams& params, + const rtc::CopyOnWriteBuffer& payload); + void OnStreamClosedRemotely(int sid); + + // The remote peer request that this channel should be closed. + void RemotePeerRequestClose(); + + // The following methods are for SCTP only. + + // Sets the SCTP sid and adds to transport layer if not set yet. Should only + // be called once. + void SetSctpSid(int sid); + // Called when the transport channel is created. + // Only needs to be called for SCTP data channels. + void OnTransportChannelCreated(); + // Called when the transport channel is destroyed. + // This method makes sure the DataChannel is disconnected and changes state + // to kClosed. + void OnTransportChannelDestroyed(); + + // The following methods are for RTP only. + + // Set the SSRC this channel should use to send data on the + // underlying data engine. |send_ssrc| == 0 means that the channel is no + // longer part of the session negotiation. + void SetSendSsrc(uint32_t send_ssrc); + // Set the SSRC this channel should use to receive data from the + // underlying data engine. + void SetReceiveSsrc(uint32_t receive_ssrc); + + cricket::DataChannelType data_channel_type() const { + return data_channel_type_; + } + + // Emitted when state transitions to kOpen. + sigslot::signal1 SignalOpened; + // Emitted when state transitions to kClosed. + // In the case of SCTP channels, this signal can be used to tell when the + // channel's sid is free. + sigslot::signal1 SignalClosed; + + protected: + DataChannel(DataChannelProviderInterface* client, + cricket::DataChannelType dct, + const std::string& label); + virtual ~DataChannel(); + + private: + // A packet queue which tracks the total queued bytes. Queued packets are + // owned by this class. + class PacketQueue { + public: + PacketQueue(); + ~PacketQueue(); + + size_t byte_count() const { + return byte_count_; + } + + bool Empty() const; + + DataBuffer* Front(); + + void Pop(); + + void Push(DataBuffer* packet); + + void Clear(); + + void Swap(PacketQueue* other); + + private: + std::deque packets_; + size_t byte_count_; + }; + + // The OPEN(_ACK) signaling state. + enum HandshakeState { + kHandshakeInit, + kHandshakeShouldSendOpen, + kHandshakeShouldSendAck, + kHandshakeWaitingForAck, + kHandshakeReady + }; + + bool Init(const InternalDataChannelInit& config); + void DoClose(); + void UpdateState(); + void SetState(DataState state); + void DisconnectFromProvider(); + + void DeliverQueuedReceivedData(); + + void SendQueuedDataMessages(); + bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked); + bool QueueSendDataMessage(const DataBuffer& buffer); + + void SendQueuedControlMessages(); + void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer); + bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer); + + std::string label_; + InternalDataChannelInit config_; + DataChannelObserver* observer_; + DataState state_; + uint32_t messages_sent_; + uint64_t bytes_sent_; + uint32_t messages_received_; + uint64_t bytes_received_; + cricket::DataChannelType data_channel_type_; + DataChannelProviderInterface* provider_; + HandshakeState handshake_state_; + bool connected_to_provider_; + bool send_ssrc_set_; + bool receive_ssrc_set_; + bool writable_; + uint32_t send_ssrc_; + uint32_t receive_ssrc_; + // Control messages that always have to get sent out before any queued + // data. + PacketQueue queued_control_data_; + PacketQueue queued_received_data_; + PacketQueue queued_send_data_; +}; + +// Define proxy for DataChannelInterface. +BEGIN_SIGNALING_PROXY_MAP(DataChannel) + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) + PROXY_METHOD0(void, UnregisterObserver) + PROXY_CONSTMETHOD0(std::string, label) + PROXY_CONSTMETHOD0(bool, reliable) + PROXY_CONSTMETHOD0(bool, ordered) + PROXY_CONSTMETHOD0(uint16_t, maxRetransmitTime) + PROXY_CONSTMETHOD0(uint16_t, maxRetransmits) + PROXY_CONSTMETHOD0(std::string, protocol) + PROXY_CONSTMETHOD0(bool, negotiated) + PROXY_CONSTMETHOD0(int, id) + PROXY_CONSTMETHOD0(DataState, state) + PROXY_CONSTMETHOD0(uint32_t, messages_sent) + PROXY_CONSTMETHOD0(uint64_t, bytes_sent) + PROXY_CONSTMETHOD0(uint32_t, messages_received) + PROXY_CONSTMETHOD0(uint64_t, bytes_received) + PROXY_CONSTMETHOD0(uint64_t, buffered_amount) + PROXY_METHOD0(void, Close) + PROXY_METHOD1(bool, Send, const DataBuffer&) +END_PROXY_MAP() + +} // namespace webrtc + +#endif // WEBRTC_PC_DATACHANNEL_H_ diff --git a/include/webrtc/api/dtmfsender.h b/include/webrtc/pc/dtmfsender.h similarity index 86% rename from include/webrtc/api/dtmfsender.h rename to include/webrtc/pc/dtmfsender.h index c85557f..5eab055 100644 --- a/include/webrtc/api/dtmfsender.h +++ b/include/webrtc/pc/dtmfsender.h @@ -8,15 +8,14 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_DTMFSENDER_H_ -#define WEBRTC_API_DTMFSENDER_H_ +#ifndef WEBRTC_PC_DTMFSENDER_H_ +#define WEBRTC_PC_DTMFSENDER_H_ #include #include "webrtc/api/dtmfsenderinterface.h" #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/proxy.h" -#include "webrtc/base/common.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/messagehandler.h" #include "webrtc/base/refcount.h" @@ -35,14 +34,13 @@ namespace webrtc { // to send DTMF. class DtmfProviderInterface { public: - // Returns true if the audio track with given id (|track_id|) is capable - // of sending DTMF. Otherwise returns false. - virtual bool CanInsertDtmf(const std::string& track_id) = 0; - // Sends DTMF |code| via the audio track with given id (|track_id|). + // Returns true if the audio sender is capable of sending DTMF. Otherwise + // returns false. + virtual bool CanInsertDtmf() = 0; + // Sends DTMF |code|. // The |duration| indicates the length of the DTMF tone in ms. // Returns true on success and false on failure. - virtual bool InsertDtmf(const std::string& track_id, - int code, int duration) = 0; + virtual bool InsertDtmf(int code, int duration) = 0; // Returns a |sigslot::signal0<>| signal. The signal should fire before // the provider is destroyed. virtual sigslot::signal0<>* GetOnDestroyedSignal() = 0; @@ -56,6 +54,8 @@ class DtmfSender public sigslot::has_slots<>, public rtc::MessageHandler { public: + // |track| is only there for backwards compatibility, since there's a track + // accessor method. static rtc::scoped_refptr Create( AudioTrackInterface* track, rtc::Thread* signaling_thread, @@ -105,6 +105,7 @@ class DtmfSender // Define proxy for DtmfSenderInterface. BEGIN_SIGNALING_PROXY_MAP(DtmfSender) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD1(void, RegisterObserver, DtmfSenderObserverInterface*) PROXY_METHOD0(void, UnregisterObserver) PROXY_METHOD0(bool, CanInsertDtmf) @@ -113,11 +114,11 @@ BEGIN_SIGNALING_PROXY_MAP(DtmfSender) PROXY_CONSTMETHOD0(std::string, tones) PROXY_CONSTMETHOD0(int, duration) PROXY_CONSTMETHOD0(int, inter_tone_gap) -END_SIGNALING_PROXY() +END_PROXY_MAP() // Get DTMF code from the DTMF event character. bool GetDtmfCode(char tone, int* code); } // namespace webrtc -#endif // WEBRTC_API_DTMFSENDER_H_ +#endif // WEBRTC_PC_DTMFSENDER_H_ diff --git a/include/webrtc/pc/externalhmac.h b/include/webrtc/pc/externalhmac.h index edca74d..2666d90 100644 --- a/include/webrtc/pc/externalhmac.h +++ b/include/webrtc/pc/externalhmac.h @@ -20,25 +20,23 @@ // How will libsrtp select this module? // Libsrtp defines authentication function types identified by an unsigned -// integer, e.g. HMAC_SHA1 is 3. Using authentication ids, the application -// can plug any desired authentication modules into libsrtp. +// integer, e.g. SRTP_HMAC_SHA1 is 3. Using authentication ids, the +// application can plug any desired authentication modules into libsrtp. // libsrtp also provides a mechanism to select different auth functions for // individual streams. This can be done by setting the right value in // the auth_type of srtp_policy_t. The application must first register auth // functions and the corresponding authentication id using // crypto_kernel_replace_auth_type function. -#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH) -#include "webrtc/base/basictypes.h" -extern "C" { -#ifdef SRTP_RELATIVE_PATH -#include "auth.h" // NOLINT -#else -#include "third_party/libsrtp/srtp/crypto/include/auth.h" -#endif // SRTP_RELATIVE_PATH -} +#include + +#ifdef HAVE_SRTP +#include "third_party/libsrtp/crypto/include/auth.h" +#endif // HAVE_SRTP + +#if defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH) -#define EXTERNAL_HMAC_SHA1 HMAC_SHA1 + 1 +#define EXTERNAL_HMAC_SHA1 SRTP_HMAC_SHA1 + 1 #define HMAC_KEY_LENGTH 20 // The HMAC context structure used to store authentication keys. @@ -49,27 +47,29 @@ typedef struct { int key_length; } ExternalHmacContext; -err_status_t external_hmac_alloc(auth_t** a, int key_len, int out_len); +srtp_err_status_t external_hmac_alloc(srtp_auth_t** a, + int key_len, + int out_len); -err_status_t external_hmac_dealloc(auth_t* a); +srtp_err_status_t external_hmac_dealloc(srtp_auth_t* a); -err_status_t external_hmac_init(ExternalHmacContext* state, - const uint8_t* key, - int key_len); +srtp_err_status_t external_hmac_init(ExternalHmacContext* state, + const uint8_t* key, + int key_len); -err_status_t external_hmac_start(ExternalHmacContext* state); +srtp_err_status_t external_hmac_start(ExternalHmacContext* state); -err_status_t external_hmac_update(ExternalHmacContext* state, - const uint8_t* message, - int msg_octets); +srtp_err_status_t external_hmac_update(ExternalHmacContext* state, + const uint8_t* message, + int msg_octets); -err_status_t external_hmac_compute(ExternalHmacContext* state, - const void* message, - int msg_octets, - int tag_len, - uint8_t* result); +srtp_err_status_t external_hmac_compute(ExternalHmacContext* state, + const void* message, + int msg_octets, + int tag_len, + uint8_t* result); -err_status_t external_crypto_init(); +srtp_err_status_t external_crypto_init(); #endif // defined(HAVE_SRTP) && defined(ENABLE_EXTERNAL_AUTH) #endif // WEBRTC_PC_EXTERNALHMAC_H_ diff --git a/include/webrtc/api/fakemediacontroller.h b/include/webrtc/pc/fakemediacontroller.h similarity index 88% rename from include/webrtc/api/fakemediacontroller.h rename to include/webrtc/pc/fakemediacontroller.h index bc3f3e2..6d639ed 100644 --- a/include/webrtc/api/fakemediacontroller.h +++ b/include/webrtc/pc/fakemediacontroller.h @@ -8,12 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_FAKEMEDIACONTROLLER_H_ -#define WEBRTC_API_FAKEMEDIACONTROLLER_H_ +#ifndef WEBRTC_PC_FAKEMEDIACONTROLLER_H_ +#define WEBRTC_PC_FAKEMEDIACONTROLLER_H_ -#include "webrtc/api/mediacontroller.h" #include "webrtc/base/checks.h" #include "webrtc/media/base/mediachannel.h" +#include "webrtc/pc/mediacontroller.h" namespace cricket { @@ -39,4 +39,4 @@ class FakeMediaController : public webrtc::MediaControllerInterface { webrtc::Call* call_; }; } // namespace cricket -#endif // WEBRTC_API_FAKEMEDIACONTROLLER_H_ +#endif // WEBRTC_PC_FAKEMEDIACONTROLLER_H_ diff --git a/include/webrtc/api/localaudiosource.h b/include/webrtc/pc/localaudiosource.h similarity index 72% rename from include/webrtc/api/localaudiosource.h rename to include/webrtc/pc/localaudiosource.h index e1c023e..ffa465d 100644 --- a/include/webrtc/api/localaudiosource.h +++ b/include/webrtc/pc/localaudiosource.h @@ -8,12 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_LOCALAUDIOSOURCE_H_ -#define WEBRTC_API_LOCALAUDIOSOURCE_H_ +#ifndef WEBRTC_PC_LOCALAUDIOSOURCE_H_ +#define WEBRTC_PC_LOCALAUDIOSOURCE_H_ #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/notifier.h" -#include "webrtc/api/peerconnectioninterface.h" #include "webrtc/media/base/mediachannel.h" // LocalAudioSource implements AudioSourceInterface. @@ -27,11 +26,9 @@ class LocalAudioSource : public Notifier { public: // Creates an instance of LocalAudioSource. static rtc::scoped_refptr Create( - const PeerConnectionFactoryInterface::Options& options, const MediaConstraintsInterface* constraints); static rtc::scoped_refptr Create( - const PeerConnectionFactoryInterface::Options& options, const cricket::AudioOptions* audio_options); SourceState state() const override { return kLive; } @@ -47,14 +44,12 @@ class LocalAudioSource : public Notifier { ~LocalAudioSource() override {} private: - void Initialize(const PeerConnectionFactoryInterface::Options& options, - const MediaConstraintsInterface* constraints); - void Initialize(const PeerConnectionFactoryInterface::Options& options, - const cricket::AudioOptions* audio_options); + void Initialize(const MediaConstraintsInterface* constraints); + void Initialize(const cricket::AudioOptions* audio_options); cricket::AudioOptions options_; }; } // namespace webrtc -#endif // WEBRTC_API_LOCALAUDIOSOURCE_H_ +#endif // WEBRTC_PC_LOCALAUDIOSOURCE_H_ diff --git a/include/webrtc/pc/mediacontroller.h b/include/webrtc/pc/mediacontroller.h new file mode 100644 index 0000000..f5a9034 --- /dev/null +++ b/include/webrtc/pc/mediacontroller.h @@ -0,0 +1,46 @@ +/* + * Copyright 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_MEDIACONTROLLER_H_ +#define WEBRTC_PC_MEDIACONTROLLER_H_ + +#include "webrtc/base/thread.h" + +namespace cricket { +class ChannelManager; +struct MediaConfig; +} // namespace cricket + +namespace webrtc { +class Call; +class VoiceEngine; +class RtcEventLog; + +// The MediaController currently owns shared state between media channels. +// Abstract interface is defined here such that it can be faked/mocked for +// tests, but no other real reason. +class MediaControllerInterface { + public: + // Will never return nullptr. + static MediaControllerInterface* Create( + const cricket::MediaConfig& config, + rtc::Thread* worker_thread, + cricket::ChannelManager* channel_manager, + webrtc::RtcEventLog* event_log); + + virtual ~MediaControllerInterface() {} + virtual void Close() = 0; + virtual webrtc::Call* call_w() = 0; + virtual cricket::ChannelManager* channel_manager() const = 0; + virtual const cricket::MediaConfig& config() const = 0; +}; +} // namespace webrtc + +#endif // WEBRTC_PC_MEDIACONTROLLER_H_ diff --git a/include/webrtc/pc/mediasession.h b/include/webrtc/pc/mediasession.h index 22291c4..a901e1d 100644 --- a/include/webrtc/pc/mediasession.h +++ b/include/webrtc/pc/mediasession.h @@ -18,6 +18,7 @@ #include #include +#include "webrtc/api/mediatypes.h" #include "webrtc/media/base/codec.h" #include "webrtc/media/base/cryptoparams.h" #include "webrtc/media/base/mediachannel.h" @@ -25,7 +26,7 @@ #include "webrtc/media/base/mediaengine.h" // For DataChannelType #include "webrtc/media/base/streamparams.h" #include "webrtc/p2p/base/sessiondescription.h" -#include "webrtc/p2p/base/transport.h" +#include "webrtc/p2p/base/jseptransport.h" #include "webrtc/p2p/base/transportdescriptionfactory.h" namespace cricket { @@ -35,15 +36,7 @@ typedef std::vector AudioCodecs; typedef std::vector VideoCodecs; typedef std::vector DataCodecs; typedef std::vector CryptoParamsVec; -typedef std::vector RtpHeaderExtensions; - -enum MediaType { - MEDIA_TYPE_AUDIO, - MEDIA_TYPE_VIDEO, - MEDIA_TYPE_DATA -}; - -std::string MediaTypeToString(MediaType type); +typedef std::vector RtpHeaderExtensions; enum MediaContentDirection { MD_INACTIVE, @@ -52,6 +45,8 @@ enum MediaContentDirection { MD_SENDRECV }; +std::string MediaContentDirectionToString(MediaContentDirection direction); + enum CryptoType { CT_NONE, CT_SDES, @@ -79,6 +74,34 @@ const int kBufferedModeDisabled = 0; // Default RTCP CNAME for unit tests. const char kDefaultRtcpCname[] = "DefaultRtcpCname"; +struct RtpTransceiverDirection { + bool send; + bool recv; + + RtpTransceiverDirection(bool send, bool recv) : send(send), recv(recv) {} + + bool operator==(const RtpTransceiverDirection& o) const { + return send == o.send && recv == o.recv; + } + + bool operator!=(const RtpTransceiverDirection& o) const { + return !(*this == o); + } + + static RtpTransceiverDirection FromMediaContentDirection( + MediaContentDirection md); + + MediaContentDirection ToMediaContentDirection() const; + + RtpTransceiverDirection Reversed() const { + return RtpTransceiverDirection(recv, send); + } +}; + +RtpTransceiverDirection +NegotiateRtpTransceiverDirection(RtpTransceiverDirection offer, + RtpTransceiverDirection wants); + struct MediaSessionOptions { MediaSessionOptions() : recv_audio(true), @@ -134,9 +157,11 @@ struct MediaSessionOptions { // bps. -1 == auto. int video_bandwidth; int data_bandwidth; + bool enable_ice_renomination = false; // content name ("mid") => options. std::map transport_options; std::string rtcp_cname; + rtc::CryptoOptions crypto_options; struct Stream { Stream(MediaType type, @@ -205,10 +230,17 @@ class MediaContentDescription : public ContentDescription { rtp_header_extensions_ = extensions; rtp_header_extensions_set_ = true; } - void AddRtpHeaderExtension(const RtpHeaderExtension& ext) { + void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) { rtp_header_extensions_.push_back(ext); rtp_header_extensions_set_ = true; } + void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) { + webrtc::RtpExtension webrtc_extension; + webrtc_extension.uri = ext.uri; + webrtc_extension.id = ext.id; + rtp_header_extensions_.push_back(webrtc_extension); + rtp_header_extensions_set_ = true; + } void ClearRtpHeaderExtensions() { rtp_header_extensions_.clear(); rtp_header_extensions_set_ = true; @@ -284,7 +316,7 @@ class MediaContentDescription : public ContentDescription { std::string protocol_; std::vector cryptos_; CryptoType crypto_required_ = CT_NONE; - std::vector rtp_header_extensions_; + std::vector rtp_header_extensions_; bool rtp_header_extensions_set_ = false; bool multistream_ = false; StreamParamsVec streams_; @@ -373,10 +405,18 @@ class VideoContentDescription : public MediaContentDescriptionImpl { class DataContentDescription : public MediaContentDescriptionImpl { public: + DataContentDescription() {} + virtual ContentDescription* Copy() const { return new DataContentDescription(*this); } virtual MediaType type() const { return MEDIA_TYPE_DATA; } + + bool use_sctpmap() const { return use_sctpmap_; } + void set_use_sctpmap(bool enable) { use_sctpmap_ = enable; } + + private: + bool use_sctpmap_ = true; }; // Creates media session descriptions according to the supplied codecs and @@ -395,8 +435,11 @@ class MediaSessionDescriptionFactory { MediaSessionDescriptionFactory(ChannelManager* cmanager, const TransportDescriptionFactory* factory); - const AudioCodecs& audio_codecs() const { return audio_codecs_; } - void set_audio_codecs(const AudioCodecs& codecs) { audio_codecs_ = codecs; } + const AudioCodecs& audio_sendrecv_codecs() const; + const AudioCodecs& audio_send_codecs() const; + const AudioCodecs& audio_recv_codecs() const; + void set_audio_codecs(const AudioCodecs& send_codecs, + const AudioCodecs& recv_codecs); void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) { audio_rtp_extensions_ = extensions; } @@ -425,12 +468,20 @@ class MediaSessionDescriptionFactory { const MediaSessionOptions& options, const SessionDescription* current_description) const; SessionDescription* CreateAnswer( - const SessionDescription* offer, - const MediaSessionOptions& options, - const SessionDescription* current_description) const; + const SessionDescription* offer, + const MediaSessionOptions& options, + const SessionDescription* current_description) const; private: + const AudioCodecs& GetAudioCodecsForOffer( + const RtpTransceiverDirection& direction) const; + const AudioCodecs& GetAudioCodecsForAnswer( + const RtpTransceiverDirection& offer, + const RtpTransceiverDirection& answer) const; void GetCodecsToOffer(const SessionDescription* current_description, + const AudioCodecs& supported_audio_codecs, + const VideoCodecs& supported_video_codecs, + const DataCodecs& supported_data_codecs, AudioCodecs* audio_codecs, VideoCodecs* video_codecs, DataCodecs* data_codecs) const; @@ -447,7 +498,8 @@ class MediaSessionDescriptionFactory { const std::string& content_name, const SessionDescription* offer_desc, const TransportOptions& transport_options, - const SessionDescription* current_desc) const; + const SessionDescription* current_desc, + bool require_transport_attributes) const; bool AddTransportAnswer( const std::string& content_name, @@ -481,28 +533,30 @@ class MediaSessionDescriptionFactory { StreamParamsVec* current_streams, SessionDescription* desc) const; - bool AddAudioContentForAnswer( - const SessionDescription* offer, - const MediaSessionOptions& options, - const SessionDescription* current_description, - StreamParamsVec* current_streams, - SessionDescription* answer) const; - - bool AddVideoContentForAnswer( - const SessionDescription* offer, - const MediaSessionOptions& options, - const SessionDescription* current_description, - StreamParamsVec* current_streams, - SessionDescription* answer) const; - - bool AddDataContentForAnswer( - const SessionDescription* offer, - const MediaSessionOptions& options, - const SessionDescription* current_description, - StreamParamsVec* current_streams, - SessionDescription* answer) const; - - AudioCodecs audio_codecs_; + bool AddAudioContentForAnswer(const SessionDescription* offer, + const MediaSessionOptions& options, + const SessionDescription* current_description, + const TransportInfo* bundle_transport, + StreamParamsVec* current_streams, + SessionDescription* answer) const; + + bool AddVideoContentForAnswer(const SessionDescription* offer, + const MediaSessionOptions& options, + const SessionDescription* current_description, + const TransportInfo* bundle_transport, + StreamParamsVec* current_streams, + SessionDescription* answer) const; + + bool AddDataContentForAnswer(const SessionDescription* offer, + const MediaSessionOptions& options, + const SessionDescription* current_description, + const TransportInfo* bundle_transport, + StreamParamsVec* current_streams, + SessionDescription* answer) const; + + AudioCodecs audio_send_codecs_; + AudioCodecs audio_recv_codecs_; + AudioCodecs audio_sendrecv_codecs_; RtpHeaderExtensions audio_rtp_extensions_; VideoCodecs video_codecs_; RtpHeaderExtensions video_rtp_extensions_; @@ -548,17 +602,21 @@ VideoContentDescription* GetFirstVideoContentDescription( DataContentDescription* GetFirstDataContentDescription( SessionDescription* sdesc); -void GetSupportedAudioCryptoSuites(std::vector* crypto_suites); -void GetSupportedVideoCryptoSuites(std::vector* crypto_suites); -void GetSupportedDataCryptoSuites(std::vector* crypto_suites); -void GetDefaultSrtpCryptoSuites(std::vector* crypto_suites); -void GetSupportedAudioCryptoSuiteNames( +void GetSupportedAudioCryptoSuites(const rtc::CryptoOptions& crypto_options, + std::vector* crypto_suites); +void GetSupportedVideoCryptoSuites(const rtc::CryptoOptions& crypto_options, + std::vector* crypto_suites); +void GetSupportedDataCryptoSuites(const rtc::CryptoOptions& crypto_options, + std::vector* crypto_suites); +void GetDefaultSrtpCryptoSuites(const rtc::CryptoOptions& crypto_options, + std::vector* crypto_suites); +void GetSupportedAudioCryptoSuiteNames(const rtc::CryptoOptions& crypto_options, std::vector* crypto_suite_names); -void GetSupportedVideoCryptoSuiteNames( +void GetSupportedVideoCryptoSuiteNames(const rtc::CryptoOptions& crypto_options, std::vector* crypto_suite_names); -void GetSupportedDataCryptoSuiteNames( +void GetSupportedDataCryptoSuiteNames(const rtc::CryptoOptions& crypto_options, std::vector* crypto_suite_names); -void GetDefaultSrtpCryptoSuiteNames( +void GetDefaultSrtpCryptoSuiteNames(const rtc::CryptoOptions& crypto_options, std::vector* crypto_suite_names); } // namespace cricket diff --git a/include/webrtc/pc/mediasink.h b/include/webrtc/pc/mediasink.h deleted file mode 100644 index 01bd3fa..0000000 --- a/include/webrtc/pc/mediasink.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2004 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_PC_MEDIASINK_H_ -#define WEBRTC_PC_MEDIASINK_H_ - -namespace cricket { - -// MediaSinkInterface is a sink to handle RTP and RTCP packets that are sent or -// received by a channel. -class MediaSinkInterface { - public: - virtual ~MediaSinkInterface() {} - - virtual void SetMaxSize(size_t size) = 0; - virtual bool Enable(bool enable) = 0; - virtual bool IsEnabled() const = 0; - virtual void OnPacket(const void* data, size_t size, bool rtcp) = 0; - virtual void set_packet_filter(int filter) = 0; -}; - -} // namespace cricket - -#endif // WEBRTC_PC_MEDIASINK_H_ diff --git a/include/webrtc/pc/mediastream.h b/include/webrtc/pc/mediastream.h new file mode 100644 index 0000000..56fbed9 --- /dev/null +++ b/include/webrtc/pc/mediastream.h @@ -0,0 +1,58 @@ +/* + * Copyright 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains the implementation of MediaStreamInterface interface. + +#ifndef WEBRTC_PC_MEDIASTREAM_H_ +#define WEBRTC_PC_MEDIASTREAM_H_ + +#include +#include + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/notifier.h" + +namespace webrtc { + +class MediaStream : public Notifier { + public: + static rtc::scoped_refptr Create(const std::string& label); + + std::string label() const override { return label_; } + + bool AddTrack(AudioTrackInterface* track) override; + bool AddTrack(VideoTrackInterface* track) override; + bool RemoveTrack(AudioTrackInterface* track) override; + bool RemoveTrack(VideoTrackInterface* track) override; + rtc::scoped_refptr + FindAudioTrack(const std::string& track_id) override; + rtc::scoped_refptr + FindVideoTrack(const std::string& track_id) override; + + AudioTrackVector GetAudioTracks() override { return audio_tracks_; } + VideoTrackVector GetVideoTracks() override { return video_tracks_; } + + protected: + explicit MediaStream(const std::string& label); + + private: + template + bool AddTrack(TrackVector* Tracks, Track* track); + template + bool RemoveTrack(TrackVector* Tracks, MediaStreamTrackInterface* track); + + std::string label_; + AudioTrackVector audio_tracks_; + VideoTrackVector video_tracks_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_MEDIASTREAM_H_ diff --git a/include/webrtc/api/mediastreamobserver.h b/include/webrtc/pc/mediastreamobserver.h similarity index 91% rename from include/webrtc/api/mediastreamobserver.h rename to include/webrtc/pc/mediastreamobserver.h index 3179976..5d9012b 100644 --- a/include/webrtc/api/mediastreamobserver.h +++ b/include/webrtc/pc/mediastreamobserver.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_MEDIASTREAMOBSERVER_H_ -#define WEBRTC_API_MEDIASTREAMOBSERVER_H_ +#ifndef WEBRTC_PC_MEDIASTREAMOBSERVER_H_ +#define WEBRTC_PC_MEDIASTREAMOBSERVER_H_ #include "webrtc/api/mediastreaminterface.h" #include "webrtc/base/scoped_ref_ptr.h" @@ -45,4 +45,4 @@ class MediaStreamObserver : public ObserverInterface { } // namespace webrtc -#endif // WEBRTC_API_MEDIASTREAMOBSERVER_H_ +#endif // WEBRTC_PC_MEDIASTREAMOBSERVER_H_ diff --git a/include/webrtc/pc/mediastreamtrack.h b/include/webrtc/pc/mediastreamtrack.h new file mode 100644 index 0000000..0fb2de2 --- /dev/null +++ b/include/webrtc/pc/mediastreamtrack.h @@ -0,0 +1,62 @@ +/* + * Copyright 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_MEDIASTREAMTRACK_H_ +#define WEBRTC_PC_MEDIASTREAMTRACK_H_ + +#include + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/notifier.h" + +namespace webrtc { + +// MediaTrack implements the interface common to AudioTrackInterface and +// VideoTrackInterface. +template +class MediaStreamTrack : public Notifier { + public: + typedef typename T::TrackState TypedTrackState; + + std::string id() const override { return id_; } + MediaStreamTrackInterface::TrackState state() const override { + return state_; + } + bool enabled() const override { return enabled_; } + bool set_enabled(bool enable) override { + bool fire_on_change = (enable != enabled_); + enabled_ = enable; + if (fire_on_change) { + Notifier::FireOnChanged(); + } + return fire_on_change; + } + + protected: + explicit MediaStreamTrack(const std::string& id) + : enabled_(true), id_(id), state_(MediaStreamTrackInterface::kLive) {} + + bool set_state(MediaStreamTrackInterface::TrackState new_state) { + bool fire_on_change = (state_ != new_state); + state_ = new_state; + if (fire_on_change) + Notifier::FireOnChanged(); + return true; + } + + private: + bool enabled_; + std::string id_; + MediaStreamTrackInterface::TrackState state_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_MEDIASTREAMTRACK_H_ diff --git a/include/webrtc/api/peerconnection.h b/include/webrtc/pc/peerconnection.h similarity index 82% rename from include/webrtc/api/peerconnection.h rename to include/webrtc/pc/peerconnection.h index 8ba7e58..ac8f33c 100644 --- a/include/webrtc/api/peerconnection.h +++ b/include/webrtc/pc/peerconnection.h @@ -8,27 +8,28 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_PEERCONNECTION_H_ -#define WEBRTC_API_PEERCONNECTION_H_ +#ifndef WEBRTC_PC_PEERCONNECTION_H_ +#define WEBRTC_PC_PEERCONNECTION_H_ #include #include #include #include -#include "webrtc/api/dtlsidentitystore.h" -#include "webrtc/api/peerconnectionfactory.h" #include "webrtc/api/peerconnectioninterface.h" -#include "webrtc/api/rtpreceiverinterface.h" -#include "webrtc/api/rtpsenderinterface.h" -#include "webrtc/api/statscollector.h" -#include "webrtc/api/streamcollection.h" -#include "webrtc/api/webrtcsession.h" +#include "webrtc/pc/peerconnectionfactory.h" +#include "webrtc/pc/rtcstatscollector.h" +#include "webrtc/pc/rtpreceiver.h" +#include "webrtc/pc/rtpsender.h" +#include "webrtc/pc/statscollector.h" +#include "webrtc/pc/streamcollection.h" +#include "webrtc/pc/webrtcsession.h" namespace webrtc { class MediaStreamObserver; class VideoRtpReceiver; +class RtcEventLog; // Populates |session_options| from |rtc_options|, and returns true if options // are valid. @@ -53,10 +54,12 @@ bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, cricket::MediaSessionOptions* session_options); // Parses the URLs for each server in |servers| to build |stun_servers| and -// |turn_servers|. -bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, - cricket::ServerAddresses* stun_servers, - std::vector* turn_servers); +// |turn_servers|. Can return SYNTAX_ERROR if the URL is malformed, or +// INVALID_PARAMETER if a TURN server is missing |username| or |password|. +RTCErrorType ParseIceServers( + const PeerConnectionInterface::IceServers& servers, + cricket::ServerAddresses* stun_servers, + std::vector* turn_servers); // PeerConnection implements the PeerConnectionInterface interface. // It uses WebRtcSession to implement the PeerConnection functionality. @@ -70,7 +73,7 @@ class PeerConnection : public PeerConnectionInterface, bool Initialize( const PeerConnectionInterface::RTCConfiguration& configuration, std::unique_ptr allocator, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, PeerConnectionObserver* observer); rtc::scoped_refptr local_streams() override; @@ -103,16 +106,21 @@ class PeerConnection : public PeerConnectionInterface, bool GetStats(StatsObserver* observer, webrtc::MediaStreamTrackInterface* track, StatsOutputLevel level) override; + void GetStats(RTCStatsCollectorCallback* callback) override; SignalingState signaling_state() override; - // TODO(bemasc): Remove ice_state() when callers are removed. - IceState ice_state() override; IceConnectionState ice_connection_state() override; IceGatheringState ice_gathering_state() override; const SessionDescriptionInterface* local_description() const override; const SessionDescriptionInterface* remote_description() const override; + const SessionDescriptionInterface* current_local_description() const override; + const SessionDescriptionInterface* current_remote_description() + const override; + const SessionDescriptionInterface* pending_local_description() const override; + const SessionDescriptionInterface* pending_remote_description() + const override; // JSEP01 // Deprecated, use version without constraints. @@ -129,16 +137,28 @@ class PeerConnection : public PeerConnectionInterface, SessionDescriptionInterface* desc) override; void SetRemoteDescription(SetSessionDescriptionObserver* observer, SessionDescriptionInterface* desc) override; + PeerConnectionInterface::RTCConfiguration GetConfiguration() override; bool SetConfiguration( - const PeerConnectionInterface::RTCConfiguration& configuration) override; + const PeerConnectionInterface::RTCConfiguration& configuration, + RTCError* error) override; + bool SetConfiguration( + const PeerConnectionInterface::RTCConfiguration& configuration) override { + return SetConfiguration(configuration, nullptr); + } bool AddIceCandidate(const IceCandidateInterface* candidate) override; bool RemoveIceCandidates( const std::vector& candidates) override; void RegisterUMAObserver(UMAObserver* observer) override; + bool StartRtcEventLog(rtc::PlatformFile file, + int64_t max_size_bytes) override; + void StopRtcEventLog() override; + void Close() override; + sigslot::signal1 SignalDataChannelCreated; + // Virtual for unit tests. virtual const std::vector>& sctp_data_channels() const { @@ -175,7 +195,6 @@ class PeerConnection : public PeerConnectionInterface, void CreateVideoReceiver(MediaStreamInterface* stream, const std::string& track_id, uint32_t ssrc); - void StopReceivers(cricket::MediaType media_type); void DestroyReceiver(const std::string& track_id); void DestroyAudioSender(MediaStreamInterface* stream, AudioTrackInterface* audio_track, @@ -209,7 +228,7 @@ class PeerConnection : public PeerConnectionInterface, return factory_->signaling_thread(); } - rtc::Thread* worker_thread() const { return factory_->worker_thread(); } + rtc::Thread* network_thread() const { return factory_->network_thread(); } void PostSetSessionDescriptionFailure(SetSessionDescriptionObserver* observer, const std::string& error); @@ -237,6 +256,9 @@ class PeerConnection : public PeerConnectionInterface, const RTCOfferAnswerOptions& options, cricket::MediaSessionOptions* session_options); + void InitializeOptionsForAnswer( + cricket::MediaSessionOptions* session_options); + // Helper function for options processing. // Deprecated. virtual void FinishOptionsForAnswer( @@ -326,7 +348,9 @@ class PeerConnection : public PeerConnectionInterface, void OnSctpDataChannelClosed(DataChannel* channel); // Notifications from WebRtcSession relating to BaseChannels. + void OnVoiceChannelCreated(); void OnVoiceChannelDestroyed(); + void OnVideoChannelCreated(); void OnVideoChannelDestroyed(); void OnDataChannelCreated(); void OnDataChannelDestroyed(); @@ -335,11 +359,13 @@ class PeerConnection : public PeerConnectionInterface, void OnDataChannelOpenMessage(const std::string& label, const InternalDataChannelInit& config); - RtpSenderInterface* FindSenderById(const std::string& id); + RtpSenderInternal* FindSenderById(const std::string& id); - std::vector>::iterator + std::vector>>::iterator FindSenderForTrack(MediaStreamTrackInterface* track); - std::vector>::iterator + std::vector>>::iterator FindReceiverForTrack(const std::string& track_id); TrackInfos* GetRemoteTracks(cricket::MediaType media_type); @@ -353,10 +379,22 @@ class PeerConnection : public PeerConnectionInterface, DataChannel* FindDataChannelBySid(int sid) const; // Called when first configuring the port allocator. - bool InitializePortAllocator_w(const RTCConfiguration& configuration); - // Called when SetConfiguration is called. Only a subset of the configuration - // is applied. - bool ReconfigurePortAllocator_w(const RTCConfiguration& configuration); + bool InitializePortAllocator_n(const RTCConfiguration& configuration); + // Called when SetConfiguration is called to apply the supported subset + // of the configuration on the network thread. + bool ReconfigurePortAllocator_n( + const cricket::ServerAddresses& stun_servers, + const std::vector& turn_servers, + IceTransportsType type, + int candidate_pool_size, + bool prune_turn_ports); + + // Starts recording an Rtc EventLog using the supplied platform file. + // This function should only be called from the worker thread. + bool StartRtcEventLog_w(rtc::PlatformFile file, int64_t max_size_bytes); + // Starts recording an Rtc EventLog using the supplied platform file. + // This function should only be called from the worker thread. + void StopRtcEventLog_w(); // Storing the factory as a scoped reference pointer ensures that the memory // in the PeerConnectionFactoryImpl remains available as long as the @@ -368,12 +406,13 @@ class PeerConnection : public PeerConnectionInterface, PeerConnectionObserver* observer_; UMAObserver* uma_observer_; SignalingState signaling_state_; - // TODO(bemasc): Remove ice_state_. - IceState ice_state_; IceConnectionState ice_connection_state_; IceGatheringState ice_gathering_state_; + PeerConnectionInterface::RTCConfiguration configuration_; std::unique_ptr port_allocator_; + // The EventLog needs to outlive the media controller. + std::unique_ptr event_log_; std::unique_ptr media_controller_; // One PeerConnection has only one RTCP CNAME. @@ -401,13 +440,16 @@ class PeerConnection : public PeerConnectionInterface, bool remote_peer_supports_msid_ = false; - std::vector> senders_; - std::vector> receivers_; - + std::vector>> + senders_; + std::vector< + rtc::scoped_refptr>> + receivers_; std::unique_ptr session_; std::unique_ptr stats_; + rtc::scoped_refptr stats_collector_; }; } // namespace webrtc -#endif // WEBRTC_API_PEERCONNECTION_H_ +#endif // WEBRTC_PC_PEERCONNECTION_H_ diff --git a/include/webrtc/api/peerconnectionfactory.h b/include/webrtc/pc/peerconnectionfactory.h similarity index 66% rename from include/webrtc/api/peerconnectionfactory.h rename to include/webrtc/pc/peerconnectionfactory.h index 21165cf..53c6745 100644 --- a/include/webrtc/api/peerconnectionfactory.h +++ b/include/webrtc/pc/peerconnectionfactory.h @@ -8,19 +8,19 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_PEERCONNECTIONFACTORY_H_ -#define WEBRTC_API_PEERCONNECTIONFACTORY_H_ +#ifndef WEBRTC_PC_PEERCONNECTIONFACTORY_H_ +#define WEBRTC_PC_PEERCONNECTIONFACTORY_H_ #include #include -#include "webrtc/api/dtlsidentitystore.h" -#include "webrtc/api/mediacontroller.h" #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread.h" +#include "webrtc/base/rtccertificategenerator.h" #include "webrtc/pc/channelmanager.h" +#include "webrtc/pc/mediacontroller.h" namespace rtc { class BasicNetworkManager; @@ -29,27 +29,30 @@ class BasicPacketSocketFactory; namespace webrtc { -typedef rtc::RefCountedObject - RefCountedDtlsIdentityStore; +class RtcEventLog; class PeerConnectionFactory : public PeerConnectionFactoryInterface { public: - void SetOptions(const Options& options) override { - options_ = options; - } + // Use the overloads of CreateVideoSource that take raw VideoCapturer + // pointers from PeerConnectionFactoryInterface. + // TODO(deadbeef): Remove this using statement once those overloads are + // removed. + using PeerConnectionFactoryInterface::CreateVideoSource; + + void SetOptions(const Options& options) override; // Deprecated, use version without constraints. rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, const MediaConstraintsInterface* constraints, std::unique_ptr allocator, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, PeerConnectionObserver* observer) override; virtual rtc::scoped_refptr CreatePeerConnection( const PeerConnectionInterface::RTCConfiguration& configuration, std::unique_ptr allocator, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, PeerConnectionObserver* observer) override; bool Initialize(); @@ -64,13 +67,13 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { const MediaConstraintsInterface* constraints) override; virtual rtc::scoped_refptr CreateVideoSource( - cricket::VideoCapturer* capturer) override; + std::unique_ptr capturer) override; // This version supports filtering on width, height and frame rate. // For the "constraints=null" case, use the version without constraints. // TODO(hta): Design a version without MediaConstraintsInterface. // https://bugs.chromium.org/p/webrtc/issues/detail?id=5617 rtc::scoped_refptr CreateVideoSource( - cricket::VideoCapturer* capturer, + std::unique_ptr capturer, const MediaConstraintsInterface* constraints) override; rtc::scoped_refptr CreateVideoTrack( @@ -83,33 +86,45 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { bool StartAecDump(rtc::PlatformFile file, int64_t max_size_bytes) override; void StopAecDump() override; - bool StartRtcEventLog(rtc::PlatformFile file) override { - return StartRtcEventLog(file, -1); - } + // TODO(ivoc) Remove after Chrome is updated. + bool StartRtcEventLog(rtc::PlatformFile file) override { return false; } + // TODO(ivoc) Remove after Chrome is updated. bool StartRtcEventLog(rtc::PlatformFile file, - int64_t max_size_bytes) override; - void StopRtcEventLog() override; + int64_t max_size_bytes) override { + return false; + } + // TODO(ivoc) Remove after Chrome is updated. + void StopRtcEventLog() override {} virtual webrtc::MediaControllerInterface* CreateMediaController( - const cricket::MediaConfig& config) const; + const cricket::MediaConfig& config, + RtcEventLog* event_log) const; + virtual cricket::TransportController* CreateTransportController( + cricket::PortAllocator* port_allocator, + bool redetermine_role_on_ice_restart); virtual rtc::Thread* signaling_thread(); virtual rtc::Thread* worker_thread(); virtual rtc::Thread* network_thread(); const Options& options() const { return options_; } protected: - PeerConnectionFactory(); + PeerConnectionFactory( + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory); PeerConnectionFactory( rtc::Thread* network_thread, rtc::Thread* worker_thread, rtc::Thread* signaling_thread, AudioDeviceModule* default_adm, + rtc::scoped_refptr audio_encoder_factory, + rtc::scoped_refptr audio_decoder_factory, cricket::WebRtcVideoEncoderFactory* video_encoder_factory, - cricket::WebRtcVideoDecoderFactory* video_decoder_factory); + cricket::WebRtcVideoDecoderFactory* video_decoder_factory, + rtc::scoped_refptr audio_mixer); virtual ~PeerConnectionFactory(); private: - cricket::MediaEngineInterface* CreateMediaEngine_w(); + std::unique_ptr CreateMediaEngine_w(); bool owns_ptrs_; bool wraps_current_thread_; @@ -119,6 +134,7 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { Options options_; // External Audio device used for audio playback. rtc::scoped_refptr default_adm_; + rtc::scoped_refptr audio_decoder_factory_; std::unique_ptr channel_manager_; // External Video encoder factory. This can be NULL if the client has not // injected any. In that case, video engine will use the internal SW encoder. @@ -128,10 +144,11 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { std::unique_ptr video_decoder_factory_; std::unique_ptr default_network_manager_; std::unique_ptr default_socket_factory_; - - rtc::scoped_refptr dtls_identity_store_; + // External audio mixer. This can be NULL. In that case, internal audio mixer + // will be created and used. + rtc::scoped_refptr external_audio_mixer_; }; } // namespace webrtc -#endif // WEBRTC_API_PEERCONNECTIONFACTORY_H_ +#endif // WEBRTC_PC_PEERCONNECTIONFACTORY_H_ diff --git a/include/webrtc/api/quicdatachannel.h b/include/webrtc/pc/quicdatachannel.h similarity index 95% rename from include/webrtc/api/quicdatachannel.h rename to include/webrtc/pc/quicdatachannel.h index a6b987b..2f6288b 100644 --- a/include/webrtc/api/quicdatachannel.h +++ b/include/webrtc/pc/quicdatachannel.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_QUICDATACHANNEL_H_ -#define WEBRTC_API_QUICDATACHANNEL_H_ +#ifndef WEBRTC_PC_QUICDATACHANNEL_H_ +#define WEBRTC_PC_QUICDATACHANNEL_H_ #include #include @@ -88,6 +88,7 @@ class QuicDataChannel : public rtc::RefCountedObject, QuicDataChannel(rtc::Thread* signaling_thread, rtc::Thread* worker_thread, + rtc::Thread* network_thread, const std::string& label, const DataChannelInit& config); ~QuicDataChannel() override; @@ -155,11 +156,13 @@ class QuicDataChannel : public rtc::RefCountedObject, void OnReadyToSend(cricket::TransportChannel* channel); void OnConnectionClosed(); - // Worker thread methods. + // Network thread methods. // Sends the data buffer to the remote peer using an outgoing QUIC stream. // Returns true if the data buffer can be successfully sent, or if it is // queued to be sent later. - bool Send_w(const DataBuffer& buffer); + bool Send_n(const DataBuffer& buffer); + + // Worker thread methods. // Connects the |quic_transport_channel_| signals to this QuicDataChannel, // then returns the new QuicDataChannel state. DataState SetTransportChannel_w(); @@ -185,8 +188,10 @@ class QuicDataChannel : public rtc::RefCountedObject, cricket::QuicTransportChannel* quic_transport_channel_ = nullptr; // Signaling thread for DataChannelInterface methods. rtc::Thread* const signaling_thread_; - // Worker thread for sending data and |quic_transport_channel_| callbacks. + // Worker thread for |quic_transport_channel_| callbacks. rtc::Thread* const worker_thread_; + // Network thread for sending data and |quic_transport_channel_| callbacks. + rtc::Thread* const network_thread_; rtc::AsyncInvoker invoker_; // Map of QUIC stream ID => ReliableQuicStream* for write blocked QUIC // streams. @@ -212,4 +217,4 @@ class QuicDataChannel : public rtc::RefCountedObject, } // namespace webrtc -#endif // WEBRTC_API_QUICDATACHANNEL_H_ +#endif // WEBRTC_PC_QUICDATACHANNEL_H_ diff --git a/include/webrtc/api/quicdatatransport.h b/include/webrtc/pc/quicdatatransport.h similarity index 72% rename from include/webrtc/api/quicdatatransport.h rename to include/webrtc/pc/quicdatatransport.h index f0c427d..6b35a10 100644 --- a/include/webrtc/api/quicdatatransport.h +++ b/include/webrtc/pc/quicdatatransport.h @@ -8,17 +8,18 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_QUICDATATRANSPORT_H_ -#define WEBRTC_API_QUICDATATRANSPORT_H_ +#ifndef WEBRTC_PC_QUICDATATRANSPORT_H_ +#define WEBRTC_PC_QUICDATATRANSPORT_H_ #include #include #include "webrtc/api/datachannelinterface.h" -#include "webrtc/api/quicdatachannel.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/thread.h" +#include "webrtc/p2p/base/transportcontroller.h" +#include "webrtc/pc/quicdatachannel.h" namespace cricket { class QuicTransportChannel; @@ -36,14 +37,19 @@ namespace webrtc { // exists, it sends the QUIC stream to the QuicDataChannel. class QuicDataTransport : public sigslot::has_slots<> { public: - QuicDataTransport(rtc::Thread* signaling_thread, rtc::Thread* worker_thread); + QuicDataTransport(rtc::Thread* signaling_thread, + rtc::Thread* worker_thread, + rtc::Thread* network_thread, + cricket::TransportController* transport_controller); ~QuicDataTransport() override; - // Sets the QUIC transport channel for the QuicDataChannels and the - // QuicDataTransport. Returns false if a different QUIC transport channel is - // already set, the QUIC transport channel cannot be set for any of the - // QuicDataChannels, or |channel| is NULL. - bool SetTransportChannel(cricket::QuicTransportChannel* channel); + // The QuicDataTransport acts like a BaseChannel with these functions. + bool SetTransport(const std::string& transport_name); + const std::string& transport_name() const { return transport_name_; } + const std::string& content_name() const { return content_name_; } + void set_content_name(const std::string& content_name) { + content_name_ = content_name; + } // Creates a QuicDataChannel that uses this QuicDataTransport. rtc::scoped_refptr CreateDataChannel( @@ -60,7 +66,17 @@ class QuicDataTransport : public sigslot::has_slots<> { // True if the QuicDataTransport has data channels. bool HasDataChannels() const; + cricket::QuicTransportChannel* quic_transport_channel() { + return quic_transport_channel_; + } + private: + // Sets the QUIC transport channel for the QuicDataChannels and the + // QuicDataTransport. Returns false if a different QUIC transport channel is + // already set, the QUIC transport channel cannot be set for any of the + // QuicDataChannels, or |channel| is NULL. + bool SetTransportChannel(cricket::QuicTransportChannel* channel); + // Called from the QuicTransportChannel when a ReliableQuicStream is created // to receive incoming data. void OnIncomingStream(cricket::ReliableQuicStream* stream); @@ -72,6 +88,10 @@ class QuicDataTransport : public sigslot::has_slots<> { const char* data, size_t len); + cricket::QuicTransportChannel* CreateTransportChannel( + const std::string& transport_name); + void DestroyTransportChannel(cricket::TransportChannel* transport_channel); + // Map of data channel ID => QUIC data channel values. std::unordered_map> data_channel_by_id_; @@ -80,11 +100,16 @@ class QuicDataTransport : public sigslot::has_slots<> { quic_stream_by_id_; // QuicTransportChannel for sending/receiving data. cricket::QuicTransportChannel* quic_transport_channel_ = nullptr; - // Signaling and worker threads for the QUIC data channel. + // Threads for the QUIC data channel. rtc::Thread* const signaling_thread_; rtc::Thread* const worker_thread_; + rtc::Thread* const network_thread_; + + cricket::TransportController* transport_controller_; + std::string content_name_; + std::string transport_name_; }; } // namespace webrtc -#endif // WEBRTC_API_QUICDATATRANSPORT_H_ +#endif // WEBRTC_PC_QUICDATATRANSPORT_H_ diff --git a/include/webrtc/api/remoteaudiosource.h b/include/webrtc/pc/remoteaudiosource.h similarity index 84% rename from include/webrtc/api/remoteaudiosource.h rename to include/webrtc/pc/remoteaudiosource.h index abb55f6..b84a016 100644 --- a/include/webrtc/api/remoteaudiosource.h +++ b/include/webrtc/pc/remoteaudiosource.h @@ -8,16 +8,16 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_REMOTEAUDIOSOURCE_H_ -#define WEBRTC_API_REMOTEAUDIOSOURCE_H_ +#ifndef WEBRTC_PC_REMOTEAUDIOSOURCE_H_ +#define WEBRTC_PC_REMOTEAUDIOSOURCE_H_ #include #include -#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/call/audio_sink.h" #include "webrtc/api/notifier.h" -#include "webrtc/audio_sink.h" #include "webrtc/base/criticalsection.h" +#include "webrtc/pc/channel.h" namespace rtc { struct Message; @@ -26,15 +26,13 @@ class Thread; namespace webrtc { -class AudioProviderInterface; - // This class implements the audio source used by the remote audio track. class RemoteAudioSource : public Notifier { public: // Creates an instance of RemoteAudioSource. static rtc::scoped_refptr Create( uint32_t ssrc, - AudioProviderInterface* provider); + cricket::VoiceChannel* channel); // MediaSourceInterface implementation. MediaSourceInterface::SourceState state() const override; @@ -49,7 +47,7 @@ class RemoteAudioSource : public Notifier { // Post construction initialize where we can do things like save a reference // to ourselves (need to be fully constructed). - void Initialize(uint32_t ssrc, AudioProviderInterface* provider); + void Initialize(uint32_t ssrc, cricket::VoiceChannel* channel); private: typedef std::list AudioObserverList; @@ -61,7 +59,7 @@ class RemoteAudioSource : public Notifier { class Sink; void OnData(const AudioSinkInterface::Data& audio); - void OnAudioProviderGone(); + void OnAudioChannelGone(); class MessageHandler; void OnMessage(rtc::Message* msg); @@ -75,4 +73,4 @@ class RemoteAudioSource : public Notifier { } // namespace webrtc -#endif // WEBRTC_API_REMOTEAUDIOSOURCE_H_ +#endif // WEBRTC_PC_REMOTEAUDIOSOURCE_H_ diff --git a/include/webrtc/pc/rtcpmuxfilter.h b/include/webrtc/pc/rtcpmuxfilter.h index 94dc41d..bdd8a35 100644 --- a/include/webrtc/pc/rtcpmuxfilter.h +++ b/include/webrtc/pc/rtcpmuxfilter.h @@ -11,7 +11,6 @@ #ifndef WEBRTC_PC_RTCPMUXFILTER_H_ #define WEBRTC_PC_RTCPMUXFILTER_H_ -#include "webrtc/base/basictypes.h" #include "webrtc/p2p/base/sessiondescription.h" namespace cricket { @@ -21,10 +20,20 @@ class RtcpMuxFilter { public: RtcpMuxFilter(); - // Whether the filter is active, i.e. has RTCP mux been properly negotiated. + // Whether RTCP mux has been negotiated with a final answer (not provisional). + bool IsFullyActive() const; + + // Whether RTCP mux has been negotiated with a provisional answer; this means + // a later answer could disable RTCP mux, and so the RTCP transport should + // not be disposed yet. + bool IsProvisionallyActive() const; + + // Whether the filter is active, i.e. has RTCP mux been properly negotiated, + // either with a final or provisional answer. bool IsActive() const; - // Make the filter active, regardless of the current state. + // Make the filter active (fully, not provisionally) regardless of the + // current state. This should be used when an endpoint *requires* RTCP mux. void SetActive(); // Specifies whether the offer indicates the use of RTCP mux. diff --git a/include/webrtc/pc/rtcstatscollector.h b/include/webrtc/pc/rtcstatscollector.h new file mode 100644 index 0000000..48e66ba --- /dev/null +++ b/include/webrtc/pc/rtcstatscollector.h @@ -0,0 +1,193 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_RTCSTATSCOLLECTOR_H_ +#define WEBRTC_PC_RTCSTATSCOLLECTOR_H_ + +#include +#include +#include +#include + +#include "webrtc/api/stats/rtcstats_objects.h" +#include "webrtc/api/stats/rtcstatscollectorcallback.h" +#include "webrtc/api/stats/rtcstatsreport.h" +#include "webrtc/base/asyncinvoker.h" +#include "webrtc/base/optional.h" +#include "webrtc/base/refcount.h" +#include "webrtc/base/scoped_ref_ptr.h" +#include "webrtc/base/sigslot.h" +#include "webrtc/base/sslidentity.h" +#include "webrtc/base/timeutils.h" +#include "webrtc/media/base/mediachannel.h" +#include "webrtc/pc/datachannel.h" +#include "webrtc/pc/trackmediainfomap.h" + +namespace cricket { +class Candidate; +} // namespace cricket + +namespace rtc { +class SSLCertificate; +} // namespace rtc + +namespace webrtc { + +class PeerConnection; +struct SessionStats; +struct ChannelNamePairs; + +// All public methods of the collector are to be called on the signaling thread. +// Stats are gathered on the signaling, worker and network threads +// asynchronously. The callback is invoked on the signaling thread. Resulting +// reports are cached for |cache_lifetime_| ms. +class RTCStatsCollector : public virtual rtc::RefCountInterface, + public sigslot::has_slots<> { + public: + static rtc::scoped_refptr Create( + PeerConnection* pc, + int64_t cache_lifetime_us = 50 * rtc::kNumMicrosecsPerMillisec); + + // Gets a recent stats report. If there is a report cached that is still fresh + // it is returned, otherwise new stats are gathered and returned. A report is + // considered fresh for |cache_lifetime_| ms. const RTCStatsReports are safe + // to use across multiple threads and may be destructed on any thread. + void GetStatsReport(rtc::scoped_refptr callback); + // Clears the cache's reference to the most recent stats report. Subsequently + // calling |GetStatsReport| guarantees fresh stats. + void ClearCachedStatsReport(); + + // If there is a |GetStatsReport| requests in-flight, waits until it has been + // completed. Must be called on the signaling thread. + void WaitForPendingRequest(); + + protected: + RTCStatsCollector(PeerConnection* pc, int64_t cache_lifetime_us); + ~RTCStatsCollector(); + + // Stats gathering on a particular thread. Calls |AddPartialResults| before + // returning. Virtual for the sake of testing. + virtual void ProducePartialResultsOnSignalingThread(int64_t timestamp_us); + virtual void ProducePartialResultsOnNetworkThread(int64_t timestamp_us); + + // Can be called on any thread. + void AddPartialResults( + const rtc::scoped_refptr& partial_report); + + private: + struct CertificateStatsPair { + std::unique_ptr local; + std::unique_ptr remote; + }; + + void AddPartialResults_s(rtc::scoped_refptr partial_report); + void DeliverCachedReport(); + + // Produces |RTCCertificateStats|. + void ProduceCertificateStats_n( + int64_t timestamp_us, + const std::map& transport_cert_stats, + RTCStatsReport* report) const; + // Produces |RTCCodecStats|. + void ProduceCodecStats_n( + int64_t timestamp_us, const TrackMediaInfoMap& track_media_info_map, + RTCStatsReport* report) const; + // Produces |RTCDataChannelStats|. + void ProduceDataChannelStats_s( + int64_t timestamp_us, RTCStatsReport* report) const; + // Produces |RTCIceCandidatePairStats| and |RTCIceCandidateStats|. + void ProduceIceCandidateAndPairStats_n( + int64_t timestamp_us, const SessionStats& session_stats, + const cricket::VideoMediaInfo* video_media_info, + RTCStatsReport* report) const; + // Produces |RTCMediaStreamStats| and |RTCMediaStreamTrackStats|. + void ProduceMediaStreamAndTrackStats_s( + int64_t timestamp_us, RTCStatsReport* report) const; + // Produces |RTCPeerConnectionStats|. + void ProducePeerConnectionStats_s( + int64_t timestamp_us, RTCStatsReport* report) const; + // Produces |RTCInboundRTPStreamStats| and |RTCOutboundRTPStreamStats|. + void ProduceRTPStreamStats_n( + int64_t timestamp_us, const SessionStats& session_stats, + const TrackMediaInfoMap& track_media_info_map, + RTCStatsReport* report) const; + // Produces |RTCTransportStats|. + void ProduceTransportStats_n( + int64_t timestamp_us, const SessionStats& session_stats, + const std::map& transport_cert_stats, + RTCStatsReport* report) const; + + // Helper function to stats-producing functions. + std::map + PrepareTransportCertificateStats_n(const SessionStats& session_stats) const; + std::unique_ptr PrepareTrackMediaInfoMap_s() const; + std::map PrepareTrackToID_s() const; + + // Slots for signals (sigslot) that are wired up to |pc_|. + void OnDataChannelCreated(DataChannel* channel); + // Slots for signals (sigslot) that are wired up to |channel|. + void OnDataChannelOpened(DataChannel* channel); + void OnDataChannelClosed(DataChannel* channel); + + PeerConnection* const pc_; + rtc::Thread* const signaling_thread_; + rtc::Thread* const worker_thread_; + rtc::Thread* const network_thread_; + rtc::AsyncInvoker invoker_; + + int num_pending_partial_reports_; + int64_t partial_report_timestamp_us_; + rtc::scoped_refptr partial_report_; + std::vector> callbacks_; + + // Set in |GetStatsReport|, read in |ProducePartialResultsOnNetworkThread| and + // |ProducePartialResultsOnSignalingThread|, reset after work is complete. Not + // passed as arguments to avoid copies. This is thread safe - when we + // set/reset we know there are no pending stats requests in progress. + std::unique_ptr channel_name_pairs_; + std::unique_ptr track_media_info_map_; + std::map track_to_id_; + + // A timestamp, in microseconds, that is based on a timer that is + // monotonically increasing. That is, even if the system clock is modified the + // difference between the timer and this timestamp is how fresh the cached + // report is. + int64_t cache_timestamp_us_; + int64_t cache_lifetime_us_; + rtc::scoped_refptr cached_report_; + + // Data recorded and maintained by the stats collector during its lifetime. + // Some stats are produced from this record instead of other components. + struct InternalRecord { + InternalRecord() : data_channels_opened(0), + data_channels_closed(0) {} + + // The opened count goes up when a channel is fully opened and the closed + // count goes up if a previously opened channel has fully closed. The opened + // count does not go down when a channel closes, meaning (opened - closed) + // is the number of channels currently opened. A channel that is closed + // before reaching the open state does not affect these counters. + uint32_t data_channels_opened; + uint32_t data_channels_closed; + // Identifies by address channels that have been opened, which remain in the + // set until they have been fully closed. + std::set opened_data_channels; + }; + InternalRecord internal_record_; +}; + +const char* CandidateTypeToRTCIceCandidateTypeForTesting( + const std::string& type); +const char* DataStateToRTCDataChannelStateForTesting( + DataChannelInterface::DataState state); + +} // namespace webrtc + +#endif // WEBRTC_PC_RTCSTATSCOLLECTOR_H_ diff --git a/include/webrtc/api/rtpreceiver.h b/include/webrtc/pc/rtpreceiver.h similarity index 52% rename from include/webrtc/api/rtpreceiver.h rename to include/webrtc/pc/rtpreceiver.h index 2e7339d..513f90c 100644 --- a/include/webrtc/api/rtpreceiver.h +++ b/include/webrtc/pc/rtpreceiver.h @@ -10,30 +10,47 @@ // This file contains classes that implement RtpReceiverInterface. // An RtpReceiver associates a MediaStreamTrackInterface with an underlying -// transport (provided by AudioProviderInterface/VideoProviderInterface) +// transport (provided by cricket::VoiceChannel/cricket::VideoChannel) -#ifndef WEBRTC_API_RTPRECEIVER_H_ -#define WEBRTC_API_RTPRECEIVER_H_ +#ifndef WEBRTC_PC_RTPRECEIVER_H_ +#define WEBRTC_PC_RTPRECEIVER_H_ + +#include #include -#include "webrtc/api/mediastreamprovider.h" +#include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/rtpreceiverinterface.h" -#include "webrtc/api/remoteaudiosource.h" -#include "webrtc/api/videotracksource.h" #include "webrtc/base/basictypes.h" +#include "webrtc/base/sigslot.h" #include "webrtc/media/base/videobroadcaster.h" +#include "webrtc/pc/channel.h" +#include "webrtc/pc/remoteaudiosource.h" +#include "webrtc/pc/videotracksource.h" namespace webrtc { +// Internal class used by PeerConnection. +class RtpReceiverInternal : public RtpReceiverInterface { + public: + virtual void Stop() = 0; + // This SSRC is used as an identifier for the receiver between the API layer + // and the WebRtcVideoEngine2, WebRtcVoiceEngine layer. + virtual uint32_t ssrc() const = 0; +}; + class AudioRtpReceiver : public ObserverInterface, public AudioSourceInterface::AudioObserver, - public rtc::RefCountedObject { + public rtc::RefCountedObject, + public sigslot::has_slots<> { public: - AudioRtpReceiver(MediaStreamInterface* stream, - const std::string& track_id, + // An SSRC of 0 will create a receiver that will match the first SSRC it + // sees. + // TODO(deadbeef): Use rtc::Optional, or have another constructor that + // doesn't take an SSRC, and make this one DCHECK(ssrc != 0). + AudioRtpReceiver(const std::string& track_id, uint32_t ssrc, - AudioProviderInterface* provider); + cricket::VoiceChannel* channel); virtual ~AudioRtpReceiver(); @@ -52,30 +69,49 @@ class AudioRtpReceiver : public ObserverInterface, return track_.get(); } - std::string id() const override { return id_; } + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_AUDIO; + } - void Stop() override; + std::string id() const override { return id_; } RtpParameters GetParameters() const override; bool SetParameters(const RtpParameters& parameters) override; + // RtpReceiverInternal implementation. + void Stop() override; + uint32_t ssrc() const override { return ssrc_; } + + void SetObserver(RtpReceiverObserverInterface* observer) override; + + // Does not take ownership. + // Should call SetChannel(nullptr) before |channel| is destroyed. + void SetChannel(cricket::VoiceChannel* channel); + private: void Reconfigure(); + void OnFirstPacketReceived(cricket::BaseChannel* channel); const std::string id_; const uint32_t ssrc_; - AudioProviderInterface* provider_; // Set to null in Stop(). + cricket::VoiceChannel* channel_; const rtc::scoped_refptr track_; bool cached_track_enabled_; + double cached_volume_ = 1; + bool stopped_ = false; + RtpReceiverObserverInterface* observer_ = nullptr; + bool received_first_packet_ = false; }; -class VideoRtpReceiver : public rtc::RefCountedObject { +class VideoRtpReceiver : public rtc::RefCountedObject, + public sigslot::has_slots<> { public: - VideoRtpReceiver(MediaStreamInterface* stream, - const std::string& track_id, + // An SSRC of 0 will create a receiver that will match the first SSRC it + // sees. + VideoRtpReceiver(const std::string& track_id, rtc::Thread* worker_thread, uint32_t ssrc, - VideoProviderInterface* provider); + cricket::VideoChannel* channel); virtual ~VideoRtpReceiver(); @@ -88,17 +124,31 @@ class VideoRtpReceiver : public rtc::RefCountedObject { return track_.get(); } - std::string id() const override { return id_; } + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_VIDEO; + } - void Stop() override; + std::string id() const override { return id_; } RtpParameters GetParameters() const override; bool SetParameters(const RtpParameters& parameters) override; + // RtpReceiverInternal implementation. + void Stop() override; + uint32_t ssrc() const override { return ssrc_; } + + void SetObserver(RtpReceiverObserverInterface* observer) override; + + // Does not take ownership. + // Should call SetChannel(nullptr) before |channel| is destroyed. + void SetChannel(cricket::VideoChannel* channel); + private: + void OnFirstPacketReceived(cricket::BaseChannel* channel); + std::string id_; uint32_t ssrc_; - VideoProviderInterface* provider_; + cricket::VideoChannel* channel_; // |broadcaster_| is needed since the decoder can only handle one sink. // It might be better if the decoder can handle multiple sinks and consider // the VideoSinkWants. @@ -107,8 +157,11 @@ class VideoRtpReceiver : public rtc::RefCountedObject { // the VideoRtpReceiver is stopped. rtc::scoped_refptr source_; rtc::scoped_refptr track_; + bool stopped_ = false; + RtpReceiverObserverInterface* observer_ = nullptr; + bool received_first_packet_ = false; }; } // namespace webrtc -#endif // WEBRTC_API_RTPRECEIVER_H_ +#endif // WEBRTC_PC_RTPRECEIVER_H_ diff --git a/include/webrtc/pc/rtpsender.h b/include/webrtc/pc/rtpsender.h new file mode 100644 index 0000000..0322399 --- /dev/null +++ b/include/webrtc/pc/rtpsender.h @@ -0,0 +1,251 @@ +/* + * Copyright 2015 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contains classes that implement RtpSenderInterface. +// An RtpSender associates a MediaStreamTrackInterface with an underlying +// transport (provided by AudioProviderInterface/VideoProviderInterface) + +#ifndef WEBRTC_PC_RTPSENDER_H_ +#define WEBRTC_PC_RTPSENDER_H_ + +#include +#include + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/rtpsenderinterface.h" +#include "webrtc/base/basictypes.h" +#include "webrtc/base/criticalsection.h" +#include "webrtc/media/base/audiosource.h" +#include "webrtc/pc/channel.h" +#include "webrtc/pc/dtmfsender.h" +#include "webrtc/pc/statscollector.h" + +namespace webrtc { + +// Internal interface used by PeerConnection. +class RtpSenderInternal : public RtpSenderInterface { + public: + // Used to set the SSRC of the sender, once a local description has been set. + // If |ssrc| is 0, this indiates that the sender should disconnect from the + // underlying transport (this occurs if the sender isn't seen in a local + // description). + virtual void SetSsrc(uint32_t ssrc) = 0; + + // TODO(deadbeef): Support one sender having multiple stream ids. + virtual void set_stream_id(const std::string& stream_id) = 0; + virtual std::string stream_id() const = 0; + + virtual void Stop() = 0; +}; + +// LocalAudioSinkAdapter receives data callback as a sink to the local +// AudioTrack, and passes the data to the sink of AudioSource. +class LocalAudioSinkAdapter : public AudioTrackSinkInterface, + public cricket::AudioSource { + public: + LocalAudioSinkAdapter(); + virtual ~LocalAudioSinkAdapter(); + + private: + // AudioSinkInterface implementation. + void OnData(const void* audio_data, + int bits_per_sample, + int sample_rate, + size_t number_of_channels, + size_t number_of_frames) override; + + // cricket::AudioSource implementation. + void SetSink(cricket::AudioSource::Sink* sink) override; + + cricket::AudioSource::Sink* sink_; + // Critical section protecting |sink_|. + rtc::CriticalSection lock_; +}; + +class AudioRtpSender : public DtmfProviderInterface, + public ObserverInterface, + public rtc::RefCountedObject { + public: + // StatsCollector provided so that Add/RemoveLocalAudioTrack can be called + // at the appropriate times. + // |channel| can be null if one does not exist yet. + AudioRtpSender(AudioTrackInterface* track, + const std::string& stream_id, + cricket::VoiceChannel* channel, + StatsCollector* stats); + + // Randomly generates stream_id. + // |channel| can be null if one does not exist yet. + AudioRtpSender(AudioTrackInterface* track, + cricket::VoiceChannel* channel, + StatsCollector* stats); + + // Randomly generates id and stream_id. + // |channel| can be null if one does not exist yet. + AudioRtpSender(cricket::VoiceChannel* channel, StatsCollector* stats); + + virtual ~AudioRtpSender(); + + // DtmfSenderProvider implementation. + bool CanInsertDtmf() override; + bool InsertDtmf(int code, int duration) override; + sigslot::signal0<>* GetOnDestroyedSignal() override; + + // ObserverInterface implementation. + void OnChanged() override; + + // RtpSenderInterface implementation. + bool SetTrack(MediaStreamTrackInterface* track) override; + rtc::scoped_refptr track() const override { + return track_; + } + + uint32_t ssrc() const override { return ssrc_; } + + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_AUDIO; + } + + std::string id() const override { return id_; } + + std::vector stream_ids() const override { + std::vector ret = {stream_id_}; + return ret; + } + + RtpParameters GetParameters() const override; + bool SetParameters(const RtpParameters& parameters) override; + + rtc::scoped_refptr GetDtmfSender() const override; + + // RtpSenderInternal implementation. + void SetSsrc(uint32_t ssrc) override; + + void set_stream_id(const std::string& stream_id) override { + stream_id_ = stream_id; + } + std::string stream_id() const override { return stream_id_; } + + void Stop() override; + + // Does not take ownership. + // Should call SetChannel(nullptr) before |channel| is destroyed. + void SetChannel(cricket::VoiceChannel* channel) { channel_ = channel; } + + private: + // TODO(nisse): Since SSRC == 0 is technically valid, figure out + // some other way to test if we have a valid SSRC. + bool can_send_track() const { return track_ && ssrc_; } + // Helper function to construct options for + // AudioProviderInterface::SetAudioSend. + void SetAudioSend(); + // Helper function to call SetAudioSend with "stop sending" parameters. + void ClearAudioSend(); + + void CreateDtmfSender(); + + sigslot::signal0<> SignalDestroyed; + + std::string id_; + std::string stream_id_; + cricket::VoiceChannel* channel_ = nullptr; + StatsCollector* stats_; + rtc::scoped_refptr track_; + rtc::scoped_refptr dtmf_sender_proxy_; + uint32_t ssrc_ = 0; + bool cached_track_enabled_ = false; + bool stopped_ = false; + + // Used to pass the data callback from the |track_| to the other end of + // cricket::AudioSource. + std::unique_ptr sink_adapter_; +}; + +class VideoRtpSender : public ObserverInterface, + public rtc::RefCountedObject { + public: + // |channel| can be null if one does not exist yet. + VideoRtpSender(VideoTrackInterface* track, + const std::string& stream_id, + cricket::VideoChannel* channel); + + // Randomly generates stream_id. + // |channel| can be null if one does not exist yet. + VideoRtpSender(VideoTrackInterface* track, cricket::VideoChannel* channel); + + // Randomly generates id and stream_id. + // |channel| can be null if one does not exist yet. + explicit VideoRtpSender(cricket::VideoChannel* channel); + + virtual ~VideoRtpSender(); + + // ObserverInterface implementation + void OnChanged() override; + + // RtpSenderInterface implementation + bool SetTrack(MediaStreamTrackInterface* track) override; + rtc::scoped_refptr track() const override { + return track_; + } + + uint32_t ssrc() const override { return ssrc_; } + + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_VIDEO; + } + + std::string id() const override { return id_; } + + std::vector stream_ids() const override { + std::vector ret = {stream_id_}; + return ret; + } + + RtpParameters GetParameters() const override; + bool SetParameters(const RtpParameters& parameters) override; + + rtc::scoped_refptr GetDtmfSender() const override; + + // RtpSenderInternal implementation. + void SetSsrc(uint32_t ssrc) override; + + void set_stream_id(const std::string& stream_id) override { + stream_id_ = stream_id; + } + std::string stream_id() const override { return stream_id_; } + + void Stop() override; + + // Does not take ownership. + // Should call SetChannel(nullptr) before |channel| is destroyed. + void SetChannel(cricket::VideoChannel* channel) { channel_ = channel; } + + private: + bool can_send_track() const { return track_ && ssrc_; } + // Helper function to construct options for + // VideoProviderInterface::SetVideoSend. + void SetVideoSend(); + // Helper function to call SetVideoSend with "stop sending" parameters. + void ClearVideoSend(); + + std::string id_; + std::string stream_id_; + cricket::VideoChannel* channel_ = nullptr; + rtc::scoped_refptr track_; + uint32_t ssrc_ = 0; + bool cached_track_enabled_ = false; + VideoTrackInterface::ContentHint cached_track_content_hint_ = + VideoTrackInterface::ContentHint::kNone; + bool stopped_ = false; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_RTPSENDER_H_ diff --git a/include/webrtc/api/sctputils.h b/include/webrtc/pc/sctputils.h similarity index 92% rename from include/webrtc/api/sctputils.h rename to include/webrtc/pc/sctputils.h index 2fb1943..940bd36 100644 --- a/include/webrtc/api/sctputils.h +++ b/include/webrtc/pc/sctputils.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_SCTPUTILS_H_ -#define WEBRTC_API_SCTPUTILS_H_ +#ifndef WEBRTC_PC_SCTPUTILS_H_ +#define WEBRTC_PC_SCTPUTILS_H_ #include @@ -38,4 +38,4 @@ bool WriteDataChannelOpenMessage(const std::string& label, void WriteDataChannelOpenAckMessage(rtc::CopyOnWriteBuffer* payload); } // namespace webrtc -#endif // WEBRTC_API_SCTPUTILS_H_ +#endif // WEBRTC_PC_SCTPUTILS_H_ diff --git a/include/webrtc/pc/srtpfilter.h b/include/webrtc/pc/srtpfilter.h index b54eb8b..06edddf 100644 --- a/include/webrtc/pc/srtpfilter.h +++ b/include/webrtc/pc/srtpfilter.h @@ -22,27 +22,19 @@ #include "webrtc/base/criticalsection.h" #include "webrtc/base/sigslotrepeater.h" #include "webrtc/base/sslstreamadapter.h" +#include "webrtc/base/thread_checker.h" #include "webrtc/media/base/cryptoparams.h" #include "webrtc/p2p/base/sessiondescription.h" // Forward declaration to avoid pulling in libsrtp headers here struct srtp_event_data_t; -struct srtp_ctx_t; -struct srtp_policy_t; +struct srtp_ctx_t_; namespace cricket { -// Key is 128 bits and salt is 112 bits == 30 bytes. B64 bloat => 40 bytes. -extern const int SRTP_MASTER_KEY_BASE64_LEN; - -// Needed for DTLS-SRTP -extern const int SRTP_MASTER_KEY_KEY_LEN; -extern const int SRTP_MASTER_KEY_SALT_LEN; - class SrtpSession; class SrtpStat; -void EnableSrtpDebugging(); void ShutdownSrtp(); // Class to transform SRTP to/from RTP. @@ -119,6 +111,9 @@ class SrtpFilter { // Returns rtp auth params from srtp context. bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len); + // Returns srtp overhead for rtp packets. + bool GetSrtpOverhead(int* srtp_overhead) const; + // Update the silent threshold (in ms) for signaling errors. void set_signal_silent_time(int signal_silent_time_in_ms); @@ -139,7 +134,9 @@ class SrtpFilter { CryptoParams* selected_params); bool ApplyParams(const CryptoParams& send_params, const CryptoParams& recv_params); - static bool ParseKeyParams(const std::string& params, uint8_t* key, int len); + static bool ParseKeyParams(const std::string& params, + uint8_t* key, + size_t len); private: enum State { @@ -184,10 +181,10 @@ class SrtpSession { // Configures the session for sending data using the specified // cipher-suite and key. Receiving must be done by a separate session. - bool SetSend(int cs, const uint8_t* key, int len); + bool SetSend(int cs, const uint8_t* key, size_t len); // Configures the session for receiving data using the specified // cipher-suite and key. Sending must be done by a separate session. - bool SetRecv(int cs, const uint8_t* key, int len); + bool SetRecv(int cs, const uint8_t* key, size_t len); // Encrypts/signs an individual RTP/RTCP packet, in-place. // If an HMAC is used, this will increase the packet size. @@ -207,6 +204,8 @@ class SrtpSession { // Helper method to get authentication params. bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len); + int GetSrtpOverhead() const; + // Update the silent threshold (in ms) for signaling errors. void set_signal_silent_time(int signal_silent_time_in_ms); @@ -217,7 +216,7 @@ class SrtpSession { SignalSrtpError; private: - bool SetKey(int type, int cs, const uint8_t* key, int len); + bool SetKey(int type, int cs, const uint8_t* key, size_t len); // Returns send stream current packet index from srtp db. bool GetSendStreamPacketIndex(void* data, int in_len, int64_t* index); @@ -225,9 +224,8 @@ class SrtpSession { void HandleEvent(const srtp_event_data_t* ev); static void HandleEventThunk(srtp_event_data_t* ev); - static std::list* sessions(); - - srtp_ctx_t* session_; + rtc::ThreadChecker thread_checker_; + srtp_ctx_t_* session_; int rtp_auth_tag_len_; int rtcp_auth_tag_len_; std::unique_ptr srtp_stat_; diff --git a/include/webrtc/api/statscollector.h b/include/webrtc/pc/statscollector.h similarity index 94% rename from include/webrtc/api/statscollector.h rename to include/webrtc/pc/statscollector.h index 8c359e4..bf895ed 100644 --- a/include/webrtc/api/statscollector.h +++ b/include/webrtc/pc/statscollector.h @@ -11,8 +11,8 @@ // This file contains a class used for gathering statistics from an ongoing // libjingle PeerConnection. -#ifndef WEBRTC_API_STATSCOLLECTOR_H_ -#define WEBRTC_API_STATSCOLLECTOR_H_ +#ifndef WEBRTC_PC_STATSCOLLECTOR_H_ +#define WEBRTC_PC_STATSCOLLECTOR_H_ #include #include @@ -21,7 +21,7 @@ #include "webrtc/api/mediastreaminterface.h" #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/api/statstypes.h" -#include "webrtc/api/webrtcsession.h" +#include "webrtc/pc/webrtcsession.h" namespace webrtc { @@ -78,6 +78,9 @@ class StatsCollector { const StatsReport::Id& transport_id, StatsReport::Direction direction); + // A track is invalid if there is no report data for it. + bool IsValidTrack(const std::string& track_id); + // Method used by the unittest to force a update of stats since UpdateStats() // that occur less than kMinGatherStatsPeriod number of ms apart will be // ignored. @@ -91,17 +94,13 @@ class StatsCollector { bool CopySelectedReports(const std::string& selector, StatsReports* reports); - // Helper method for AddCertificateReports. - StatsReport* AddOneCertificateReport( - const rtc::SSLCertificate* cert, const StatsReport* issuer); - // Helper method for creating IceCandidate report. |is_local| indicates // whether this candidate is local or remote. StatsReport* AddCandidateReport(const cricket::Candidate& candidate, bool local); // Adds a report for this certificate and every certificate in its chain, and - // returns the leaf certificate's report. + // returns the leaf certificate's report (|cert|'s report). StatsReport* AddCertificateReports(const rtc::SSLCertificate* cert); StatsReport* AddConnectionInfoReport(const std::string& content_name, @@ -150,4 +149,4 @@ class StatsCollector { } // namespace webrtc -#endif // WEBRTC_API_STATSCOLLECTOR_H_ +#endif // WEBRTC_PC_STATSCOLLECTOR_H_ diff --git a/include/webrtc/pc/streamcollection.h b/include/webrtc/pc/streamcollection.h new file mode 100644 index 0000000..b4d1f27 --- /dev/null +++ b/include/webrtc/pc/streamcollection.h @@ -0,0 +1,108 @@ +/* + * Copyright 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_STREAMCOLLECTION_H_ +#define WEBRTC_PC_STREAMCOLLECTION_H_ + +#include +#include + +#include "webrtc/api/peerconnectioninterface.h" + +namespace webrtc { + +// Implementation of StreamCollection. +class StreamCollection : public StreamCollectionInterface { + public: + static rtc::scoped_refptr Create() { + rtc::RefCountedObject* implementation = + new rtc::RefCountedObject(); + return implementation; + } + + static rtc::scoped_refptr Create( + StreamCollection* streams) { + rtc::RefCountedObject* implementation = + new rtc::RefCountedObject(streams); + return implementation; + } + + virtual size_t count() { + return media_streams_.size(); + } + + virtual MediaStreamInterface* at(size_t index) { + return media_streams_.at(index); + } + + virtual MediaStreamInterface* find(const std::string& label) { + for (StreamVector::iterator it = media_streams_.begin(); + it != media_streams_.end(); ++it) { + if ((*it)->label().compare(label) == 0) { + return (*it); + } + } + return NULL; + } + + virtual MediaStreamTrackInterface* FindAudioTrack( + const std::string& id) { + for (size_t i = 0; i < media_streams_.size(); ++i) { + MediaStreamTrackInterface* track = media_streams_[i]->FindAudioTrack(id); + if (track) { + return track; + } + } + return NULL; + } + + virtual MediaStreamTrackInterface* FindVideoTrack( + const std::string& id) { + for (size_t i = 0; i < media_streams_.size(); ++i) { + MediaStreamTrackInterface* track = media_streams_[i]->FindVideoTrack(id); + if (track) { + return track; + } + } + return NULL; + } + + void AddStream(MediaStreamInterface* stream) { + for (StreamVector::iterator it = media_streams_.begin(); + it != media_streams_.end(); ++it) { + if ((*it)->label().compare(stream->label()) == 0) + return; + } + media_streams_.push_back(stream); + } + + void RemoveStream(MediaStreamInterface* remove_stream) { + for (StreamVector::iterator it = media_streams_.begin(); + it != media_streams_.end(); ++it) { + if ((*it)->label().compare(remove_stream->label()) == 0) { + media_streams_.erase(it); + break; + } + } + } + + protected: + StreamCollection() {} + explicit StreamCollection(StreamCollection* original) + : media_streams_(original->media_streams_) { + } + typedef std::vector > + StreamVector; + StreamVector media_streams_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_STREAMCOLLECTION_H_ diff --git a/include/webrtc/api/test/androidtestinitializer.h b/include/webrtc/pc/test/androidtestinitializer.h similarity index 76% rename from include/webrtc/api/test/androidtestinitializer.h rename to include/webrtc/pc/test/androidtestinitializer.h index b56783e..48df9cc 100644 --- a/include/webrtc/api/test/androidtestinitializer.h +++ b/include/webrtc/pc/test/androidtestinitializer.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_ANDROIDTESTINITIALIZER_H_ -#define WEBRTC_API_TEST_ANDROIDTESTINITIALIZER_H_ +#ifndef WEBRTC_PC_TEST_ANDROIDTESTINITIALIZER_H_ +#define WEBRTC_PC_TEST_ANDROIDTESTINITIALIZER_H_ namespace webrtc { @@ -17,4 +17,4 @@ void InitializeAndroidObjects(); } // namespace webrtc -#endif // WEBRTC_API_TEST_ANDROIDTESTINITIALIZER_H_ +#endif // WEBRTC_PC_TEST_ANDROIDTESTINITIALIZER_H_ diff --git a/include/webrtc/api/test/fakeaudiocapturemodule.h b/include/webrtc/pc/test/fakeaudiocapturemodule.h similarity index 96% rename from include/webrtc/api/test/fakeaudiocapturemodule.h rename to include/webrtc/pc/test/fakeaudiocapturemodule.h index f89249a..72735b6 100644 --- a/include/webrtc/api/test/fakeaudiocapturemodule.h +++ b/include/webrtc/pc/test/fakeaudiocapturemodule.h @@ -17,8 +17,8 @@ // Note P postfix of a function indicates that it should only be called by the // processing thread. -#ifndef WEBRTC_API_TEST_FAKEAUDIOCAPTUREMODULE_H_ -#define WEBRTC_API_TEST_FAKEAUDIOCAPTUREMODULE_H_ +#ifndef WEBRTC_PC_TEST_FAKEAUDIOCAPTUREMODULE_H_ +#define WEBRTC_PC_TEST_FAKEAUDIOCAPTUREMODULE_H_ #include @@ -179,6 +179,16 @@ class FakeAudioCaptureModule int32_t EnableBuiltInAGC(bool enable) override { return -1; } bool BuiltInNSIsAvailable() const override { return false; } int32_t EnableBuiltInNS(bool enable) override { return -1; } +#if defined(WEBRTC_IOS) + int GetPlayoutAudioParameters( + webrtc::AudioParameters* params) const override { + return -1; + } + int GetRecordAudioParameters(webrtc::AudioParameters* params) const override { + return -1; + } +#endif // WEBRTC_IOS + // End of functions inherited from webrtc::AudioDeviceModule. // The following function is inherited from rtc::MessageHandler. @@ -268,4 +278,4 @@ class FakeAudioCaptureModule rtc::CriticalSection crit_callback_; }; -#endif // WEBRTC_API_TEST_FAKEAUDIOCAPTUREMODULE_H_ +#endif // WEBRTC_PC_TEST_FAKEAUDIOCAPTUREMODULE_H_ diff --git a/include/webrtc/api/test/fakedatachannelprovider.h b/include/webrtc/pc/test/fakedatachannelprovider.h similarity index 87% rename from include/webrtc/api/test/fakedatachannelprovider.h rename to include/webrtc/pc/test/fakedatachannelprovider.h index 3404ac1..114f3de 100644 --- a/include/webrtc/api/test/fakedatachannelprovider.h +++ b/include/webrtc/pc/test/fakedatachannelprovider.h @@ -8,10 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_FAKEDATACHANNELPROVIDER_H_ -#define WEBRTC_API_TEST_FAKEDATACHANNELPROVIDER_H_ +#ifndef WEBRTC_PC_TEST_FAKEDATACHANNELPROVIDER_H_ +#define WEBRTC_PC_TEST_FAKEDATACHANNELPROVIDER_H_ -#include "webrtc/api/datachannel.h" +#include "webrtc/base/checks.h" +#include "webrtc/pc/datachannel.h" class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { public: @@ -25,7 +26,7 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { bool SendData(const cricket::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, cricket::SendDataResult* result) override { - ASSERT(ready_to_send_ && transport_available_); + RTC_CHECK(ready_to_send_ && transport_available_); if (send_blocked_) { *result = cricket::SDR_BLOCK; return false; @@ -41,7 +42,8 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { } bool ConnectDataChannel(webrtc::DataChannel* data_channel) override { - ASSERT(connected_channels_.find(data_channel) == connected_channels_.end()); + RTC_CHECK(connected_channels_.find(data_channel) == + connected_channels_.end()); if (!transport_available_) { return false; } @@ -51,13 +53,14 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { } void DisconnectDataChannel(webrtc::DataChannel* data_channel) override { - ASSERT(connected_channels_.find(data_channel) != connected_channels_.end()); + RTC_CHECK(connected_channels_.find(data_channel) != + connected_channels_.end()); LOG(LS_INFO) << "DataChannel disconnected " << data_channel; connected_channels_.erase(data_channel); } void AddSctpDataStream(int sid) override { - ASSERT(sid >= 0); + RTC_CHECK(sid >= 0); if (!transport_available_) { return; } @@ -66,7 +69,7 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { } void RemoveSctpDataStream(int sid) override { - ASSERT(sid >= 0); + RTC_CHECK(sid >= 0); send_ssrcs_.erase(sid); recv_ssrcs_.erase(sid); } @@ -99,7 +102,7 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { // Set true to emulate the transport ReadyToSendData signal when the transport // becomes writable for the first time. void set_ready_to_send(bool ready) { - ASSERT(transport_available_); + RTC_CHECK(transport_available_); ready_to_send_ = ready; if (ready) { std::set::iterator it; @@ -141,4 +144,4 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface { std::set send_ssrcs_; std::set recv_ssrcs_; }; -#endif // WEBRTC_API_TEST_FAKEDATACHANNELPROVIDER_H_ +#endif // WEBRTC_PC_TEST_FAKEDATACHANNELPROVIDER_H_ diff --git a/include/webrtc/api/test/fakeperiodicvideocapturer.h b/include/webrtc/pc/test/fakeperiodicvideocapturer.h similarity index 83% rename from include/webrtc/api/test/fakeperiodicvideocapturer.h rename to include/webrtc/pc/test/fakeperiodicvideocapturer.h index ab98855..551df8b 100644 --- a/include/webrtc/api/test/fakeperiodicvideocapturer.h +++ b/include/webrtc/pc/test/fakeperiodicvideocapturer.h @@ -11,8 +11,8 @@ // FakePeriodicVideoCapturer implements a fake cricket::VideoCapturer that // creates video frames periodically after it has been started. -#ifndef WEBRTC_API_TEST_FAKEPERIODICVIDEOCAPTURER_H_ -#define WEBRTC_API_TEST_FAKEPERIODICVIDEOCAPTURER_H_ +#ifndef WEBRTC_PC_TEST_FAKEPERIODICVIDEOCAPTURER_H_ +#define WEBRTC_PC_TEST_FAKEPERIODICVIDEOCAPTURER_H_ #include @@ -42,7 +42,7 @@ class FakePeriodicVideoCapturer : public cricket::FakeVideoCapturer, virtual cricket::CaptureState Start(const cricket::VideoFormat& format) { cricket::CaptureState state = FakeVideoCapturer::Start(format); if (state != cricket::CS_FAILED) { - rtc::Thread::Current()->Post(this, MSG_CREATEFRAME); + rtc::Thread::Current()->Post(RTC_FROM_HERE, this, MSG_CREATEFRAME); } return state; } @@ -54,8 +54,9 @@ class FakePeriodicVideoCapturer : public cricket::FakeVideoCapturer, if (msg->message_id == MSG_CREATEFRAME) { if (IsRunning()) { CaptureFrame(); - rtc::Thread::Current()->PostDelayed(static_cast( - GetCaptureFormat()->interval / rtc::kNumNanosecsPerMillisec), + rtc::Thread::Current()->PostDelayed( + RTC_FROM_HERE, static_cast(GetCaptureFormat()->interval / + rtc::kNumNanosecsPerMillisec), this, MSG_CREATEFRAME); } } @@ -70,4 +71,4 @@ class FakePeriodicVideoCapturer : public cricket::FakeVideoCapturer, } // namespace webrtc -#endif // WEBRTC_API_TEST_FAKEPERIODICVIDEOCAPTURER_H_ +#endif // WEBRTC_PC_TEST_FAKEPERIODICVIDEOCAPTURER_H_ diff --git a/include/webrtc/api/test/fakedtlsidentitystore.h b/include/webrtc/pc/test/fakertccertificategenerator.h similarity index 86% rename from include/webrtc/api/test/fakedtlsidentitystore.h rename to include/webrtc/pc/test/fakertccertificategenerator.h index 58de38f..ce36834 100644 --- a/include/webrtc/api/test/fakedtlsidentitystore.h +++ b/include/webrtc/pc/test/fakertccertificategenerator.h @@ -8,16 +8,16 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_FAKEDTLSIDENTITYSERVICE_H_ -#define WEBRTC_API_TEST_FAKEDTLSIDENTITYSERVICE_H_ +#ifndef WEBRTC_PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_ +#define WEBRTC_PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_ #include #include #include -#include "webrtc/api/dtlsidentitystore.h" #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/base/rtccertificate.h" +#include "webrtc/base/rtccertificategenerator.h" // RSA with mod size 1024, pub exp 0x10001. static const rtc::RTCCertificatePEM kRsaPems[] = { @@ -118,13 +118,14 @@ static const rtc::RTCCertificatePEM kEcdsaPems[] = { "-----END CERTIFICATE-----\n") }; -class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, - public rtc::MessageHandler { +class FakeRTCCertificateGenerator + : public rtc::RTCCertificateGeneratorInterface, + public rtc::MessageHandler { public: typedef rtc::TypedMessageData > MessageData; + rtc::RTCCertificateGeneratorCallback> > MessageData; - FakeDtlsIdentityStore() : should_fail_(false) {} + FakeRTCCertificateGenerator() : should_fail_(false) {} void set_should_fail(bool should_fail) { should_fail_ = should_fail; @@ -133,16 +134,18 @@ class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, void use_original_key() { key_index_ = 0; } void use_alternate_key() { key_index_ = 1; } - void RequestIdentity( + int generated_certificates() { return generated_certificates_; } + + void GenerateCertificateAsync( const rtc::KeyParams& key_params, const rtc::Optional& expires_ms, - const rtc::scoped_refptr& - observer) override { + const rtc::scoped_refptr& + callback) override { // The certificates are created from constant PEM strings and use its coded // expiration time, we do not support modifying it. RTC_DCHECK(!expires_ms); MessageData* msg = new MessageData( - rtc::scoped_refptr(observer)); + rtc::scoped_refptr(callback)); uint32_t msg_id; // Only supports RSA-1024-0x10001 and ECDSA-P256. if (should_fail_) { @@ -156,26 +159,19 @@ class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, key_params.ec_curve() == rtc::EC_NIST_P256); msg_id = MSG_SUCCESS_ECDSA; } - rtc::Thread::Current()->Post(this, msg_id, msg); + rtc::Thread::Current()->Post(RTC_FROM_HERE, this, msg_id, msg); } static rtc::scoped_refptr GenerateCertificate() { - std::unique_ptr identity; switch (rtc::KT_DEFAULT) { case rtc::KT_RSA: - identity.reset( - rtc::SSLIdentity::FromPEMStrings(kRsaPems[0].private_key(), - kRsaPems[0].certificate())); - break; + return rtc::RTCCertificate::FromPEM(kRsaPems[0]); case rtc::KT_ECDSA: - identity.reset( - rtc::SSLIdentity::FromPEMStrings(kEcdsaPems[0].private_key(), - kEcdsaPems[0].certificate())); - break; + return rtc::RTCCertificate::FromPEM(kEcdsaPems[0]); default: RTC_NOTREACHED(); + return nullptr; } - return rtc::RTCCertificate::Create(std::move(identity)); } private: @@ -206,21 +202,22 @@ class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, // rtc::MessageHandler implementation. void OnMessage(rtc::Message* msg) override { MessageData* message_data = static_cast(msg->pdata); - rtc::scoped_refptr observer = + rtc::scoped_refptr callback = message_data->data(); + rtc::scoped_refptr certificate; switch (msg->message_id) { case MSG_SUCCESS_RSA: case MSG_SUCCESS_ECDSA: { rtc::KeyType key_type = msg->message_id == MSG_SUCCESS_RSA ? rtc::KT_RSA : rtc::KT_ECDSA; - std::unique_ptr identity( - rtc::SSLIdentity::FromPEMStrings(get_key(key_type), - get_cert(key_type))); - observer->OnSuccess(std::move(identity)); + certificate = rtc::RTCCertificate::FromPEM(get_pem(key_type)); + RTC_DCHECK(certificate); + ++generated_certificates_; + callback->OnSuccess(certificate); break; } case MSG_FAILURE: - observer->OnFailure(0); + callback->OnFailure(); break; } delete message_data; @@ -228,6 +225,7 @@ class FakeDtlsIdentityStore : public webrtc::DtlsIdentityStoreInterface, bool should_fail_; int key_index_ = 0; + int generated_certificates_ = 0; }; -#endif // WEBRTC_API_TEST_FAKEDTLSIDENTITYSERVICE_H_ +#endif // WEBRTC_PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_ diff --git a/include/webrtc/api/test/fakevideotrackrenderer.h b/include/webrtc/pc/test/fakevideotrackrenderer.h similarity index 85% rename from include/webrtc/api/test/fakevideotrackrenderer.h rename to include/webrtc/pc/test/fakevideotrackrenderer.h index 0d9b248..9bf0b95 100644 --- a/include/webrtc/api/test/fakevideotrackrenderer.h +++ b/include/webrtc/pc/test/fakevideotrackrenderer.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_FAKEVIDEOTRACKRENDERER_H_ -#define WEBRTC_API_TEST_FAKEVIDEOTRACKRENDERER_H_ +#ifndef WEBRTC_PC_TEST_FAKEVIDEOTRACKRENDERER_H_ +#define WEBRTC_PC_TEST_FAKEVIDEOTRACKRENDERER_H_ #include "webrtc/api/mediastreaminterface.h" #include "webrtc/media/base/fakevideorenderer.h" @@ -30,4 +30,4 @@ class FakeVideoTrackRenderer : public cricket::FakeVideoRenderer { } // namespace webrtc -#endif // WEBRTC_API_TEST_FAKEVIDEOTRACKRENDERER_H_ +#endif // WEBRTC_PC_TEST_FAKEVIDEOTRACKRENDERER_H_ diff --git a/include/webrtc/api/test/fakevideotracksource.h b/include/webrtc/pc/test/fakevideotracksource.h similarity index 58% rename from include/webrtc/api/test/fakevideotracksource.h rename to include/webrtc/pc/test/fakevideotracksource.h index 1cb264b..aa5f3f5 100644 --- a/include/webrtc/api/test/fakevideotracksource.h +++ b/include/webrtc/pc/test/fakevideotracksource.h @@ -8,35 +8,42 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_FAKEVIDEOTRACKSOURCE_H_ -#define WEBRTC_API_TEST_FAKEVIDEOTRACKSOURCE_H_ +#ifndef WEBRTC_PC_TEST_FAKEVIDEOTRACKSOURCE_H_ +#define WEBRTC_PC_TEST_FAKEVIDEOTRACKSOURCE_H_ #include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/videotracksource.h" #include "webrtc/media/base/fakevideocapturer.h" +#include "webrtc/pc/videotracksource.h" namespace webrtc { class FakeVideoTrackSource : public VideoTrackSource { public: + static rtc::scoped_refptr Create(bool is_screencast) { + return new rtc::RefCountedObject(is_screencast); + } + static rtc::scoped_refptr Create() { - return new rtc::RefCountedObject(); + return Create(false); } cricket::FakeVideoCapturer* fake_video_capturer() { return &fake_video_capturer_; } + bool is_screencast() const override { return is_screencast_; } + protected: - FakeVideoTrackSource() - : VideoTrackSource(&fake_video_capturer_, - false /* remote */) {} + explicit FakeVideoTrackSource(bool is_screencast) + : VideoTrackSource(&fake_video_capturer_, false /* remote */), + is_screencast_(is_screencast) {} virtual ~FakeVideoTrackSource() {} private: cricket::FakeVideoCapturer fake_video_capturer_; + const bool is_screencast_; }; } // namespace webrtc -#endif // WEBRTC_API_TEST_FAKEVIDEOTRACKSOURCE_H_ +#endif // WEBRTC_PC_TEST_FAKEVIDEOTRACKSOURCE_H_ diff --git a/include/webrtc/pc/test/mock_datachannel.h b/include/webrtc/pc/test/mock_datachannel.h new file mode 100644 index 0000000..105fcba --- /dev/null +++ b/include/webrtc/pc/test/mock_datachannel.h @@ -0,0 +1,58 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_TEST_MOCK_DATACHANNEL_H_ +#define WEBRTC_PC_TEST_MOCK_DATACHANNEL_H_ + +#include "webrtc/pc/datachannel.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockDataChannel : public rtc::RefCountedObject { + public: + MockDataChannel(int id, DataState state) + : MockDataChannel(id, "MockDataChannel", state, "udp", 0, 0, 0, 0) { + } + MockDataChannel( + int id, + const std::string& label, + DataState state, + const std::string& protocol, + uint32_t messages_sent, + uint64_t bytes_sent, + uint32_t messages_received, + uint64_t bytes_received) + : rtc::RefCountedObject( + nullptr, cricket::DCT_NONE, label) { + EXPECT_CALL(*this, id()).WillRepeatedly(testing::Return(id)); + EXPECT_CALL(*this, state()).WillRepeatedly(testing::Return(state)); + EXPECT_CALL(*this, protocol()).WillRepeatedly(testing::Return(protocol)); + EXPECT_CALL(*this, messages_sent()).WillRepeatedly( + testing::Return(messages_sent)); + EXPECT_CALL(*this, bytes_sent()).WillRepeatedly( + testing::Return(bytes_sent)); + EXPECT_CALL(*this, messages_received()).WillRepeatedly( + testing::Return(messages_received)); + EXPECT_CALL(*this, bytes_received()).WillRepeatedly( + testing::Return(bytes_received)); + } + MOCK_CONST_METHOD0(id, int()); + MOCK_CONST_METHOD0(state, DataState()); + MOCK_CONST_METHOD0(protocol, std::string()); + MOCK_CONST_METHOD0(messages_sent, uint32_t()); + MOCK_CONST_METHOD0(bytes_sent, uint64_t()); + MOCK_CONST_METHOD0(messages_received, uint32_t()); + MOCK_CONST_METHOD0(bytes_received, uint64_t()); +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_TEST_MOCK_DATACHANNEL_H_ diff --git a/include/webrtc/pc/test/mock_peerconnection.h b/include/webrtc/pc/test/mock_peerconnection.h new file mode 100644 index 0000000..97f31c1 --- /dev/null +++ b/include/webrtc/pc/test/mock_peerconnection.h @@ -0,0 +1,51 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_TEST_MOCK_PEERCONNECTION_H_ +#define WEBRTC_PC_TEST_MOCK_PEERCONNECTION_H_ + +#include + +#include "webrtc/pc/peerconnection.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +// The factory isn't really used; it just satisfies the base PeerConnection. +class FakePeerConnectionFactory + : public rtc::RefCountedObject { + public: + FakePeerConnectionFactory() + : rtc::RefCountedObject(nullptr, nullptr) { + } +}; + +class MockPeerConnection + : public rtc::RefCountedObject { + public: + MockPeerConnection() + : rtc::RefCountedObject( + new FakePeerConnectionFactory()) {} + MOCK_METHOD0(local_streams, + rtc::scoped_refptr()); + MOCK_METHOD0(remote_streams, + rtc::scoped_refptr()); + MOCK_METHOD0(session, WebRtcSession*()); + MOCK_CONST_METHOD0(GetSenders, + std::vector>()); + MOCK_CONST_METHOD0(GetReceivers, + std::vector>()); + MOCK_CONST_METHOD0(sctp_data_channels, + const std::vector>&()); +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_TEST_MOCK_PEERCONNECTION_H_ diff --git a/include/webrtc/pc/test/mock_webrtcsession.h b/include/webrtc/pc/test/mock_webrtcsession.h new file mode 100644 index 0000000..d476377 --- /dev/null +++ b/include/webrtc/pc/test/mock_webrtcsession.h @@ -0,0 +1,65 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_TEST_MOCK_WEBRTCSESSION_H_ +#define WEBRTC_PC_TEST_MOCK_WEBRTCSESSION_H_ + +#include +#include + +#include "webrtc/pc/webrtcsession.h" +#include "webrtc/media/sctp/sctptransportinternal.h" +#include "webrtc/test/gmock.h" + +namespace webrtc { + +class MockWebRtcSession : public webrtc::WebRtcSession { + public: + // TODO(nisse): Valid overrides commented out, because the gmock + // methods don't use any override declarations, and we want to avoid + // warnings from -Winconsistent-missing-override. See + // http://crbug.com/428099. + explicit MockWebRtcSession(MediaControllerInterface* media_controller) + : WebRtcSession( + media_controller, + rtc::Thread::Current(), + rtc::Thread::Current(), + rtc::Thread::Current(), + nullptr, + std::unique_ptr( + new cricket::TransportController(rtc::Thread::Current(), + rtc::Thread::Current(), + nullptr)), + std::unique_ptr()) {} + MOCK_METHOD0(voice_channel, cricket::VoiceChannel*()); + MOCK_METHOD0(video_channel, cricket::VideoChannel*()); + // Libjingle uses "local" for a outgoing track, and "remote" for a incoming + // track. + MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*)); + MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*)); + MOCK_METHOD1(GetStats, + std::unique_ptr(const ChannelNamePairs&)); + MOCK_METHOD2(GetLocalCertificate, + bool(const std::string& transport_name, + rtc::scoped_refptr* certificate)); + + // Workaround for gmock's inability to cope with move-only return values. + std::unique_ptr GetRemoteSSLCertificate( + const std::string& transport_name) /* override */ { + return std::unique_ptr( + GetRemoteSSLCertificate_ReturnsRawPointer(transport_name)); + } + MOCK_METHOD1(GetRemoteSSLCertificate_ReturnsRawPointer, + rtc::SSLCertificate*(const std::string& transport_name)); +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_TEST_MOCK_WEBRTCSESSION_H_ diff --git a/include/webrtc/api/test/mockpeerconnectionobservers.h b/include/webrtc/pc/test/mockpeerconnectionobservers.h similarity index 88% rename from include/webrtc/api/test/mockpeerconnectionobservers.h rename to include/webrtc/pc/test/mockpeerconnectionobservers.h index 39a8f01..bde59a8 100644 --- a/include/webrtc/api/test/mockpeerconnectionobservers.h +++ b/include/webrtc/pc/test/mockpeerconnectionobservers.h @@ -10,13 +10,14 @@ // This file contains mock implementations of observers used in PeerConnection. -#ifndef WEBRTC_API_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ -#define WEBRTC_API_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ +#ifndef WEBRTC_PC_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ +#define WEBRTC_PC_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ #include #include #include "webrtc/api/datachannelinterface.h" +#include "webrtc/base/checks.h" namespace webrtc { @@ -74,7 +75,7 @@ class MockSetSessionDescriptionObserver class MockDataChannelObserver : public webrtc::DataChannelObserver { public: explicit MockDataChannelObserver(webrtc::DataChannelInterface* channel) - : channel_(channel), received_message_count_(0) { + : channel_(channel) { channel_->RegisterObserver(this); state_ = channel_->state(); } @@ -86,19 +87,21 @@ class MockDataChannelObserver : public webrtc::DataChannelObserver { void OnStateChange() override { state_ = channel_->state(); } void OnMessage(const DataBuffer& buffer) override { - last_message_.assign(buffer.data.data(), buffer.data.size()); - ++received_message_count_; + messages_.push_back( + std::string(buffer.data.data(), buffer.data.size())); } bool IsOpen() const { return state_ == DataChannelInterface::kOpen; } - const std::string& last_message() const { return last_message_; } - size_t received_message_count() const { return received_message_count_; } + std::vector messages() const { return messages_; } + std::string last_message() const { + return messages_.empty() ? std::string() : messages_.back(); + } + size_t received_message_count() const { return messages_.size(); } private: rtc::scoped_refptr channel_; DataChannelInterface::DataState state_; - std::string last_message_; - size_t received_message_count_; + std::vector messages_; }; class MockStatsObserver : public webrtc::StatsObserver { @@ -107,7 +110,7 @@ class MockStatsObserver : public webrtc::StatsObserver { virtual ~MockStatsObserver() {} virtual void OnComplete(const StatsReports& reports) { - ASSERT(!called_); + RTC_CHECK(!called_); called_ = true; stats_.Clear(); stats_.number_of_reports = reports.size(); @@ -141,37 +144,37 @@ class MockStatsObserver : public webrtc::StatsObserver { double timestamp() const { return stats_.timestamp; } int AudioOutputLevel() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.audio_output_level; } int AudioInputLevel() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.audio_input_level; } int BytesReceived() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.bytes_received; } int BytesSent() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.bytes_sent; } int AvailableReceiveBandwidth() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.available_receive_bandwidth; } std::string DtlsCipher() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.dtls_cipher; } std::string SrtpCipher() const { - ASSERT(called_); + RTC_CHECK(called_); return stats_.srtp_cipher; } @@ -224,4 +227,4 @@ class MockStatsObserver : public webrtc::StatsObserver { } // namespace webrtc -#endif // WEBRTC_API_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ +#endif // WEBRTC_PC_TEST_MOCKPEERCONNECTIONOBSERVERS_H_ diff --git a/include/webrtc/api/test/peerconnectiontestwrapper.h b/include/webrtc/pc/test/peerconnectiontestwrapper.h similarity index 69% rename from include/webrtc/api/test/peerconnectiontestwrapper.h rename to include/webrtc/pc/test/peerconnectiontestwrapper.h index 3272366..b761b05 100644 --- a/include/webrtc/api/test/peerconnectiontestwrapper.h +++ b/include/webrtc/pc/test/peerconnectiontestwrapper.h @@ -8,22 +8,29 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_TEST_PEERCONNECTIONTESTWRAPPER_H_ -#define WEBRTC_API_TEST_PEERCONNECTIONTESTWRAPPER_H_ +#ifndef WEBRTC_PC_TEST_PEERCONNECTIONTESTWRAPPER_H_ +#define WEBRTC_PC_TEST_PEERCONNECTIONTESTWRAPPER_H_ #include #include "webrtc/api/peerconnectioninterface.h" -#include "webrtc/api/test/fakeaudiocapturemodule.h" #include "webrtc/api/test/fakeconstraints.h" -#include "webrtc/api/test/fakevideotrackrenderer.h" #include "webrtc/base/sigslot.h" +#include "webrtc/pc/test/fakeaudiocapturemodule.h" +#include "webrtc/pc/test/fakevideotrackrenderer.h" class PeerConnectionTestWrapper : public webrtc::PeerConnectionObserver, public webrtc::CreateSessionDescriptionObserver, public sigslot::has_slots<> { public: + // We need these using declarations because there are two versions of each of + // the below methods and we only override one of them. + // TODO(deadbeef): Remove once there's only one version of the methods. + using PeerConnectionObserver::OnAddStream; + using PeerConnectionObserver::OnRemoveStream; + using PeerConnectionObserver::OnDataChannel; + static void Connect(PeerConnectionTestWrapper* caller, PeerConnectionTestWrapper* callee); @@ -32,31 +39,35 @@ class PeerConnectionTestWrapper rtc::Thread* worker_thread); virtual ~PeerConnectionTestWrapper(); - bool CreatePc(const webrtc::MediaConstraintsInterface* constraints); + bool CreatePc( + const webrtc::MediaConstraintsInterface* constraints, + const webrtc::PeerConnectionInterface::RTCConfiguration& config); + + webrtc::PeerConnectionInterface* pc() { return peer_connection_.get(); } rtc::scoped_refptr CreateDataChannel( const std::string& label, const webrtc::DataChannelInit& init); // Implements PeerConnectionObserver. - virtual void OnSignalingChange( - webrtc::PeerConnectionInterface::SignalingState new_state) {} - virtual void OnStateChange( - webrtc::PeerConnectionObserver::StateType state_changed) {} - virtual void OnAddStream(webrtc::MediaStreamInterface* stream); - virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) {} - virtual void OnDataChannel(webrtc::DataChannelInterface* data_channel); - virtual void OnRenegotiationNeeded() {} - virtual void OnIceConnectionChange( - webrtc::PeerConnectionInterface::IceConnectionState new_state) {} - virtual void OnIceGatheringChange( - webrtc::PeerConnectionInterface::IceGatheringState new_state) {} - virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate); - virtual void OnIceComplete() {} + void OnSignalingChange( + webrtc::PeerConnectionInterface::SignalingState new_state) override {} + void OnAddStream( + rtc::scoped_refptr stream) override; + void OnRemoveStream( + rtc::scoped_refptr stream) override {} + void OnDataChannel( + rtc::scoped_refptr data_channel) override ; + void OnRenegotiationNeeded() override {} + void OnIceConnectionChange( + webrtc::PeerConnectionInterface::IceConnectionState new_state) override {} + void OnIceGatheringChange( + webrtc::PeerConnectionInterface::IceGatheringState new_state) override {} + void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override; // Implements CreateSessionDescriptionObserver. - virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc); - virtual void OnFailure(const std::string& error) {} + void OnSuccess(webrtc::SessionDescriptionInterface* desc) override; + void OnFailure(const std::string& error) override {} void CreateOffer(const webrtc::MediaConstraintsInterface* constraints); void CreateAnswer(const webrtc::MediaConstraintsInterface* constraints); @@ -101,4 +112,4 @@ class PeerConnectionTestWrapper std::unique_ptr renderer_; }; -#endif // WEBRTC_API_TEST_PEERCONNECTIONTESTWRAPPER_H_ +#endif // WEBRTC_PC_TEST_PEERCONNECTIONTESTWRAPPER_H_ diff --git a/include/webrtc/pc/test/rtcstatsobtainer.h b/include/webrtc/pc/test/rtcstatsobtainer.h new file mode 100644 index 0000000..d0d4b61 --- /dev/null +++ b/include/webrtc/pc/test/rtcstatsobtainer.h @@ -0,0 +1,53 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_TEST_RTCSTATSOBTAINER_H_ +#define WEBRTC_PC_TEST_RTCSTATSOBTAINER_H_ + +#include "webrtc/api/stats/rtcstatsreport.h" +#include "webrtc/base/gunit.h" + +namespace webrtc { + +class RTCStatsObtainer : public RTCStatsCollectorCallback { + public: + static rtc::scoped_refptr Create( + rtc::scoped_refptr* report_ptr = nullptr) { + return rtc::scoped_refptr( + new rtc::RefCountedObject(report_ptr)); + } + + void OnStatsDelivered( + const rtc::scoped_refptr& report) override { + EXPECT_TRUE(thread_checker_.CalledOnValidThread()); + report_ = report; + if (report_ptr_) + *report_ptr_ = report_; + } + + rtc::scoped_refptr report() const { + EXPECT_TRUE(thread_checker_.CalledOnValidThread()); + return report_; + } + + protected: + explicit RTCStatsObtainer( + rtc::scoped_refptr* report_ptr) + : report_ptr_(report_ptr) {} + + private: + rtc::ThreadChecker thread_checker_; + rtc::scoped_refptr report_; + rtc::scoped_refptr* report_ptr_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_TEST_RTCSTATSOBTAINER_H_ diff --git a/include/webrtc/api/test/testsdpstrings.h b/include/webrtc/pc/test/testsdpstrings.h similarity index 96% rename from include/webrtc/api/test/testsdpstrings.h rename to include/webrtc/pc/test/testsdpstrings.h index 158b16c..ff097b2 100644 --- a/include/webrtc/api/test/testsdpstrings.h +++ b/include/webrtc/pc/test/testsdpstrings.h @@ -10,8 +10,8 @@ // This file contain SDP strings used for testing. -#ifndef WEBRTC_API_TEST_TESTSDPSTRINGS_H_ -#define WEBRTC_API_TEST_TESTSDPSTRINGS_H_ +#ifndef WEBRTC_PC_TEST_TESTSDPSTRINGS_H_ +#define WEBRTC_PC_TEST_TESTSDPSTRINGS_H_ namespace webrtc { @@ -29,6 +29,7 @@ static const char kFireFoxSdpOffer[] = "c=IN IP4 74.95.2.170\r\n" "a=rtpmap:109 opus/48000/2\r\n" "a=ptime:20\r\n" + "a=rtcp-mux\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:8 PCMA/8000\r\n" "a=rtpmap:101 telephone-event/8000\r\n" @@ -46,6 +47,7 @@ static const char kFireFoxSdpOffer[] = " 10.0.254.2 rport 50962\r\n" "m=video 38826 RTP/SAVPF 120\r\n" "c=IN IP4 74.95.2.170\r\n" + "a=rtcp-mux\r\n" "a=rtpmap:120 VP8/90000\r\n" "a=sendrecv\r\n" "a=candidate:0 1 UDP 2112946431 172.16.191.1 62017 typ host\r\n" @@ -127,4 +129,4 @@ static const char kAudioSdpWithUnsupportedCodecs[] = } // namespace webrtc -#endif // WEBRTC_API_TEST_TESTSDPSTRINGS_H_ +#endif // WEBRTC_PC_TEST_TESTSDPSTRINGS_H_ diff --git a/include/webrtc/pc/trackmediainfomap.h b/include/webrtc/pc/trackmediainfomap.h new file mode 100644 index 0000000..ceab741 --- /dev/null +++ b/include/webrtc/pc/trackmediainfomap.h @@ -0,0 +1,102 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_TRACKMEDIAINFOMAP_H_ +#define WEBRTC_PC_TRACKMEDIAINFOMAP_H_ + +#include +#include +#include + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/rtpreceiverinterface.h" +#include "webrtc/api/rtpsenderinterface.h" +#include "webrtc/base/refcount.h" +#include "webrtc/media/base/mediachannel.h" + +namespace webrtc { + +// Audio/video tracks and sender/receiver statistical information are associated +// with each other based on attachments to RTP senders/receivers. This class +// maps that relationship, in both directions, so that stats about a track can +// be retrieved on a per-attachment basis. +// +// An RTP sender/receiver sends or receives media for a set of SSRCs. The media +// comes from an audio/video track that is attached to it. +// |[Voice/Video][Sender/Receiver]Info| has statistical information for a set of +// SSRCs. Looking at the RTP senders and receivers uncovers the track <-> info +// relationships, which this class does. +class TrackMediaInfoMap { + public: + TrackMediaInfoMap( + std::unique_ptr voice_media_info, + std::unique_ptr video_media_info, + const std::vector>& rtp_senders, + const std::vector>& + rtp_receivers); + + const cricket::VoiceMediaInfo* voice_media_info() const { + return voice_media_info_.get(); + } + const cricket::VideoMediaInfo* video_media_info() const { + return video_media_info_.get(); + } + + const std::vector* GetVoiceSenderInfos( + const AudioTrackInterface& local_audio_track) const; + const cricket::VoiceReceiverInfo* GetVoiceReceiverInfo( + const AudioTrackInterface& remote_audio_track) const; + const std::vector* GetVideoSenderInfos( + const VideoTrackInterface& local_video_track) const; + const cricket::VideoReceiverInfo* GetVideoReceiverInfo( + const VideoTrackInterface& remote_video_track) const; + + rtc::scoped_refptr GetAudioTrack( + const cricket::VoiceSenderInfo& voice_sender_info) const; + rtc::scoped_refptr GetAudioTrack( + const cricket::VoiceReceiverInfo& voice_receiver_info) const; + rtc::scoped_refptr GetVideoTrack( + const cricket::VideoSenderInfo& video_sender_info) const; + rtc::scoped_refptr GetVideoTrack( + const cricket::VideoReceiverInfo& video_receiver_info) const; + + private: + std::unique_ptr voice_media_info_; + std::unique_ptr video_media_info_; + // These maps map tracks (identified by a pointer) to their corresponding info + // object of the correct kind. One track can map to multiple info objects. + std::map> + voice_infos_by_local_track_; + std::map + voice_info_by_remote_track_; + std::map> + video_infos_by_local_track_; + std::map + video_info_by_remote_track_; + // These maps map info objects to their corresponding tracks. They are always + // the inverse of the maps above. One info object always maps to only one + // track. + std::map> + audio_track_by_sender_info_; + std::map> + audio_track_by_receiver_info_; + std::map> + video_track_by_sender_info_; + std::map> + video_track_by_receiver_info_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_TRACKMEDIAINFOMAP_H_ diff --git a/include/webrtc/api/videocapturertracksource.h b/include/webrtc/pc/videocapturertracksource.h similarity index 75% rename from include/webrtc/api/videocapturertracksource.h rename to include/webrtc/pc/videocapturertracksource.h index 92f00dc..2477340 100644 --- a/include/webrtc/api/videocapturertracksource.h +++ b/include/webrtc/pc/videocapturertracksource.h @@ -8,17 +8,17 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_VIDEOCAPTURERTRACKSOURCE_H_ -#define WEBRTC_API_VIDEOCAPTURERTRACKSOURCE_H_ +#ifndef WEBRTC_PC_VIDEOCAPTURERTRACKSOURCE_H_ +#define WEBRTC_PC_VIDEOCAPTURERTRACKSOURCE_H_ #include #include "webrtc/api/mediastreaminterface.h" -#include "webrtc/api/videotracksource.h" #include "webrtc/base/asyncinvoker.h" #include "webrtc/base/sigslot.h" #include "webrtc/media/base/videocapturer.h" #include "webrtc/media/base/videocommon.h" +#include "webrtc/pc/videotracksource.h" // VideoCapturerTrackSource implements VideoTrackSourceInterface. It owns a // cricket::VideoCapturer and make sure the camera is started at a resolution @@ -33,41 +33,35 @@ class MediaConstraintsInterface; class VideoCapturerTrackSource : public VideoTrackSource, public sigslot::has_slots<> { public: - // Creates an instance of VideoCapturerTrackSource. - // VideoCapturerTrackSource take ownership of |capturer|. + // Creates an instance of VideoCapturerTrackSource from |capturer|. // |constraints| can be NULL and in that case the camera is opened using a // default resolution. static rtc::scoped_refptr Create( rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, + std::unique_ptr capturer, const webrtc::MediaConstraintsInterface* constraints, bool remote); static rtc::scoped_refptr Create( rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, + std::unique_ptr capturer, bool remote); - bool is_screencast() const override { - return video_capturer_->IsScreencast(); - } - rtc::Optional needs_denoising() const override { - return needs_denoising_; - } + bool is_screencast() const final { return video_capturer_->IsScreencast(); } + rtc::Optional needs_denoising() const final { return needs_denoising_; } - bool GetStats(Stats* stats) override; - - void Stop() override; - void Restart() override; + bool GetStats(Stats* stats) final; protected: VideoCapturerTrackSource(rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, + std::unique_ptr capturer, bool remote); virtual ~VideoCapturerTrackSource(); void Initialize(const webrtc::MediaConstraintsInterface* constraints); private: + void Stop(); + void OnStateChange(cricket::VideoCapturer* capturer, cricket::CaptureState capture_state); @@ -82,4 +76,4 @@ class VideoCapturerTrackSource : public VideoTrackSource, } // namespace webrtc -#endif // WEBRTC_API_VIDEOCAPTURERTRACKSOURCE_H_ +#endif // WEBRTC_PC_VIDEOCAPTURERTRACKSOURCE_H_ diff --git a/include/webrtc/api/videotrack.h b/include/webrtc/pc/videotrack.h similarity index 77% rename from include/webrtc/api/videotrack.h rename to include/webrtc/pc/videotrack.h index 60a0a64..7e75e14 100644 --- a/include/webrtc/api/videotrack.h +++ b/include/webrtc/pc/videotrack.h @@ -8,16 +8,16 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_VIDEOTRACK_H_ -#define WEBRTC_API_VIDEOTRACK_H_ +#ifndef WEBRTC_PC_VIDEOTRACK_H_ +#define WEBRTC_PC_VIDEOTRACK_H_ #include #include -#include "webrtc/api/mediastreamtrack.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread_checker.h" #include "webrtc/media/base/videosourcebase.h" +#include "webrtc/pc/mediastreamtrack.h" namespace webrtc { @@ -29,13 +29,15 @@ class VideoTrack : public MediaStreamTrack, const std::string& label, VideoTrackSourceInterface* source); - void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, const rtc::VideoSinkWants& wants) override; - void RemoveSink(rtc::VideoSinkInterface* sink) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; VideoTrackSourceInterface* GetSource() const override { return video_source_.get(); } + ContentHint content_hint() const override; + void set_content_hint(ContentHint hint) override; bool set_enabled(bool enable) override; std::string kind() const override; @@ -50,8 +52,9 @@ class VideoTrack : public MediaStreamTrack, rtc::ThreadChecker signaling_thread_checker_; rtc::ThreadChecker worker_thread_checker_; rtc::scoped_refptr video_source_; + ContentHint content_hint_ GUARDED_BY(signaling_thread_checker_); }; } // namespace webrtc -#endif // WEBRTC_API_VIDEOTRACK_H_ +#endif // WEBRTC_PC_VIDEOTRACK_H_ diff --git a/include/webrtc/pc/videotracksource.h b/include/webrtc/pc/videotracksource.h new file mode 100644 index 0000000..259b1c3 --- /dev/null +++ b/include/webrtc/pc/videotracksource.h @@ -0,0 +1,55 @@ +/* + * Copyright 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_PC_VIDEOTRACKSOURCE_H_ +#define WEBRTC_PC_VIDEOTRACKSOURCE_H_ + +#include "webrtc/api/mediastreaminterface.h" +#include "webrtc/api/notifier.h" +#include "webrtc/base/thread_checker.h" +#include "webrtc/media/base/mediachannel.h" +#include "webrtc/media/base/videosinkinterface.h" + +// VideoTrackSource implements VideoTrackSourceInterface. +namespace webrtc { + +class VideoTrackSource : public Notifier { + public: + VideoTrackSource(rtc::VideoSourceInterface* source, bool remote); + void SetState(SourceState new_state); + // OnSourceDestroyed clears this instance pointer to |source_|. It is useful + // when the underlying rtc::VideoSourceInterface is destroyed before the + // reference counted VideoTrackSource. + void OnSourceDestroyed(); + + SourceState state() const override { return state_; } + bool remote() const override { return remote_; } + + bool is_screencast() const override { return false; } + rtc::Optional needs_denoising() const override { + return rtc::Optional(); } + + bool GetStats(Stats* stats) override { return false; } + + void AddOrUpdateSink(rtc::VideoSinkInterface* sink, + const rtc::VideoSinkWants& wants) override; + void RemoveSink(rtc::VideoSinkInterface* sink) override; + + private: + rtc::ThreadChecker worker_thread_checker_; + rtc::VideoSourceInterface* source_; + cricket::VideoOptions options_; + SourceState state_; + const bool remote_; +}; + +} // namespace webrtc + +#endif // WEBRTC_PC_VIDEOTRACKSOURCE_H_ diff --git a/include/webrtc/pc/webrtcsdp.h b/include/webrtc/pc/webrtcsdp.h new file mode 100644 index 0000000..beaf0c5 --- /dev/null +++ b/include/webrtc/pc/webrtcsdp.h @@ -0,0 +1,87 @@ +/* + * Copyright 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +// This file contain functions for parsing and serializing SDP messages. +// Related RFC/draft including: +// * RFC 4566 - SDP +// * RFC 5245 - ICE +// * RFC 3388 - Grouping of Media Lines in SDP +// * RFC 4568 - SDP Security Descriptions for Media Streams +// * draft-lennox-mmusic-sdp-source-selection-02 - +// Mechanisms for Media Source Selection in SDP + +#ifndef WEBRTC_PC_WEBRTCSDP_H_ +#define WEBRTC_PC_WEBRTCSDP_H_ + +#include + +namespace cricket { +class Candidate; +} // namespace cricket + +namespace webrtc { +class IceCandidateInterface; +class JsepIceCandidate; +class JsepSessionDescription; +struct SdpParseError; + +// Serializes the passed in JsepSessionDescription. +// Serialize SessionDescription including candidates if +// JsepSessionDescription has candidates. +// jdesc - The JsepSessionDescription object to be serialized. +// unified_plan_sdp - If set to true, include "a=msid" lines where appropriate. +// return - SDP string serialized from the arguments. +std::string SdpSerialize(const JsepSessionDescription& jdesc, + bool unified_plan_sdp); + +// Serializes the passed in IceCandidateInterface to a SDP string. +// candidate - The candidate to be serialized. +std::string SdpSerializeCandidate(const IceCandidateInterface& candidate); + +// Serializes a cricket Candidate. +// candidate - The candidate to be serialized. +std::string SdpSerializeCandidate(const cricket::Candidate& candidate); + +// Deserializes the passed in SDP string to a JsepSessionDescription. +// message - SDP string to be Deserialized. +// jdesc - The JsepSessionDescription deserialized from the SDP string. +// error - The detail error information when parsing fails. +// return - true on success, false on failure. +bool SdpDeserialize(const std::string& message, + JsepSessionDescription* jdesc, + SdpParseError* error); + +// Deserializes the passed in SDP string to one JsepIceCandidate. +// The first line must be a=candidate line and only the first line will be +// parsed. +// message - The SDP string to be Deserialized. +// candidates - The JsepIceCandidate from the SDP string. +// error - The detail error information when parsing fails. +// return - true on success, false on failure. +bool SdpDeserializeCandidate(const std::string& message, + JsepIceCandidate* candidate, + SdpParseError* error); + +// Deserializes the passed in SDP string to a cricket Candidate. +// The first line must be a=candidate line and only the first line will be +// parsed. +// transport_name - The transport name (MID) of the candidate. +// message - The SDP string to be deserialized. +// candidate - The cricket Candidate from the SDP string. +// error - The detail error information when parsing fails. +// return - true on success, false on failure. +bool SdpDeserializeCandidate(const std::string& transport_name, + const std::string& message, + cricket::Candidate* candidate, + SdpParseError* error); + +} // namespace webrtc + +#endif // WEBRTC_PC_WEBRTCSDP_H_ diff --git a/include/webrtc/api/webrtcsession.h b/include/webrtc/pc/webrtcsession.h similarity index 65% rename from include/webrtc/api/webrtcsession.h rename to include/webrtc/pc/webrtcsession.h index 98217bf..f8e0830 100644 --- a/include/webrtc/api/webrtcsession.h +++ b/include/webrtc/pc/webrtcsession.h @@ -8,37 +8,46 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_WEBRTCSESSION_H_ -#define WEBRTC_API_WEBRTCSESSION_H_ +#ifndef WEBRTC_PC_WEBRTCSESSION_H_ +#define WEBRTC_PC_WEBRTCSESSION_H_ #include #include #include #include -#include "webrtc/api/datachannel.h" -#include "webrtc/api/dtmfsender.h" -#include "webrtc/api/mediacontroller.h" -#include "webrtc/api/mediastreamprovider.h" #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/api/statstypes.h" #include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" #include "webrtc/base/sigslot.h" #include "webrtc/base/sslidentity.h" #include "webrtc/base/thread.h" #include "webrtc/media/base/mediachannel.h" #include "webrtc/p2p/base/candidate.h" #include "webrtc/p2p/base/transportcontroller.h" +#include "webrtc/pc/datachannel.h" +#include "webrtc/pc/mediacontroller.h" #include "webrtc/pc/mediasession.h" +#ifdef HAVE_QUIC +#include "webrtc/pc/quicdatatransport.h" +#endif // HAVE_QUIC + namespace cricket { class ChannelManager; -class DataChannel; +class RtpDataChannel; +class SctpTransportInternal; +class SctpTransportInternalFactory; class StatsReport; class VideoChannel; class VoiceChannel; +#ifdef HAVE_QUIC +class QuicTransportChannel; +#endif // HAVE_QUIC + } // namespace cricket namespace webrtc { @@ -60,8 +69,8 @@ extern const char kSdpWithoutIceUfragPwd[]; extern const char kSdpWithoutSdesAndDtlsDisabled[]; extern const char kSessionError[]; extern const char kSessionErrorDesc[]; -extern const char kDtlsSetupFailureRtp[]; -extern const char kDtlsSetupFailureRtcp[]; +extern const char kDtlsSrtpSetupFailureRtp[]; +extern const char kDtlsSrtpSetupFailureRtcp[]; extern const char kEnableBundleFailed[]; // Maximum number of received video streams that will be processed by webrtc @@ -108,6 +117,20 @@ struct SessionStats { TransportStatsMap transport_stats; }; +struct ChannelNamePair { + ChannelNamePair( + const std::string& content_name, const std::string& transport_name) + : content_name(content_name), transport_name(transport_name) {} + std::string content_name; + std::string transport_name; +}; + +struct ChannelNamePairs { + rtc::Optional voice; + rtc::Optional video; + rtc::Optional data; +}; + // A WebRtcSession manages general session state. This includes negotiation // of both the application-level and network-level protocols: the former // defines what will be sent and the latter defines how it will be sent. Each @@ -115,11 +138,9 @@ struct SessionStats { // participates in the network-level negotiation. The individual streams of // packets are represented by TransportChannels. The application-level protocol // is represented by SessionDecription objects. -class WebRtcSession : public AudioProviderInterface, - public VideoProviderInterface, - public DtmfProviderInterface, - public DataChannelProviderInterface, - public sigslot::has_slots<> { +class WebRtcSession : + public DataChannelProviderInterface, + public sigslot::has_slots<> { public: enum State { STATE_INIT = 0, @@ -137,14 +158,19 @@ class WebRtcSession : public AudioProviderInterface, ERROR_TRANSPORT = 2, // transport error of some kind }; - WebRtcSession(webrtc::MediaControllerInterface* media_controller, - rtc::Thread* network_thread, - rtc::Thread* worker_thread, - rtc::Thread* signaling_thread, - cricket::PortAllocator* port_allocator); + // |sctp_factory| may be null, in which case SCTP is treated as unsupported. + WebRtcSession( + webrtc::MediaControllerInterface* media_controller, + rtc::Thread* network_thread, + rtc::Thread* worker_thread, + rtc::Thread* signaling_thread, + cricket::PortAllocator* port_allocator, + std::unique_ptr transport_controller, + std::unique_ptr sctp_factory); virtual ~WebRtcSession(); // These are const to allow them to be called from const methods. + rtc::Thread* network_thread() const { return network_thread_; } rtc::Thread* worker_thread() const { return worker_thread_; } rtc::Thread* signaling_thread() const { return signaling_thread_; } @@ -153,7 +179,7 @@ class WebRtcSession : public AudioProviderInterface, bool Initialize( const PeerConnectionFactoryInterface::Options& options, - std::unique_ptr dtls_identity_store, + std::unique_ptr cert_generator, const PeerConnectionInterface::RTCConfiguration& rtc_configuration); // Deletes the voice, video and data channel and changes the session state // to STATE_CLOSED. @@ -175,27 +201,34 @@ class WebRtcSession : public AudioProviderInterface, ice_observer_ = observer; } + // Exposed for stats collecting. virtual cricket::VoiceChannel* voice_channel() { return voice_channel_.get(); } virtual cricket::VideoChannel* video_channel() { return video_channel_.get(); } - virtual cricket::DataChannel* data_channel() { - return data_channel_.get(); + // Only valid when using deprecated RTP data channels. + virtual cricket::RtpDataChannel* rtp_data_channel() { + return rtp_data_channel_.get(); + } + virtual rtc::Optional sctp_content_name() const { + return sctp_content_name_; + } + virtual rtc::Optional sctp_transport_name() const { + return sctp_transport_name_; } cricket::BaseChannel* GetChannel(const std::string& content_name); - void SetSdesPolicy(cricket::SecurePolicy secure_policy); cricket::SecurePolicy SdesPolicy() const; - // Get current ssl role from transport. - bool GetSslRole(const std::string& transport_name, rtc::SSLRole* role); - - // Get current SSL role for this channel's transport. - // If |transport| is null, returns false. - bool GetSslRole(const cricket::BaseChannel* channel, rtc::SSLRole* role); + // Get current SSL role used by SCTP's underlying transport. + bool GetSctpSslRole(rtc::SSLRole* role); + // Get SSL role for an arbitrary m= section (handles bundling correctly). + // TODO(deadbeef): This is only used internally by the session description + // factory, it shouldn't really be public). + bool GetSslRole(const std::string& content_name, rtc::SSLRole* role); void CreateOffer( CreateSessionDescriptionObserver* observer, @@ -209,6 +242,7 @@ class WebRtcSession : public AudioProviderInterface, // The ownership of |desc| will be transferred after this call. bool SetRemoteDescription(SessionDescriptionInterface* desc, std::string* err_desc); + bool ProcessIceMessage(const IceCandidateInterface* ice_candidate); bool RemoveRemoteIceCandidates( @@ -224,58 +258,30 @@ class WebRtcSession : public AudioProviderInterface, void MaybeStartGathering(); const SessionDescriptionInterface* local_description() const { - return local_desc_.get(); + return pending_local_description_ ? pending_local_description_.get() + : current_local_description_.get(); } const SessionDescriptionInterface* remote_description() const { - return remote_desc_.get(); + return pending_remote_description_ ? pending_remote_description_.get() + : current_remote_description_.get(); + } + const SessionDescriptionInterface* current_local_description() const { + return current_local_description_.get(); + } + const SessionDescriptionInterface* current_remote_description() const { + return current_remote_description_.get(); + } + const SessionDescriptionInterface* pending_local_description() const { + return pending_local_description_.get(); + } + const SessionDescriptionInterface* pending_remote_description() const { + return pending_remote_description_.get(); } // Get the id used as a media stream track's "id" field from ssrc. virtual bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id); virtual bool GetRemoteTrackIdBySsrc(uint32_t ssrc, std::string* track_id); - // AudioMediaProviderInterface implementation. - void SetAudioPlayout(uint32_t ssrc, bool enable) override; - void SetAudioSend(uint32_t ssrc, - bool enable, - const cricket::AudioOptions& options, - cricket::AudioSource* source) override; - void SetAudioPlayoutVolume(uint32_t ssrc, double volume) override; - void SetRawAudioSink(uint32_t ssrc, - std::unique_ptr sink) override; - - RtpParameters GetAudioRtpSendParameters(uint32_t ssrc) const override; - bool SetAudioRtpSendParameters(uint32_t ssrc, - const RtpParameters& parameters) override; - RtpParameters GetAudioRtpReceiveParameters(uint32_t ssrc) const override; - bool SetAudioRtpReceiveParameters(uint32_t ssrc, - const RtpParameters& parameters) override; - - // Implements VideoMediaProviderInterface. - bool SetSource( - uint32_t ssrc, - rtc::VideoSourceInterface* source) override; - void SetVideoPlayout( - uint32_t ssrc, - bool enable, - rtc::VideoSinkInterface* sink) override; - void SetVideoSend(uint32_t ssrc, - bool enable, - const cricket::VideoOptions* options) override; - - RtpParameters GetVideoRtpSendParameters(uint32_t ssrc) const override; - bool SetVideoRtpSendParameters(uint32_t ssrc, - const RtpParameters& parameters) override; - RtpParameters GetVideoRtpReceiveParameters(uint32_t ssrc) const override; - bool SetVideoRtpReceiveParameters(uint32_t ssrc, - const RtpParameters& parameters) override; - - // Implements DtmfProviderInterface. - bool CanInsertDtmf(const std::string& track_id) override; - bool InsertDtmf(const std::string& track_id, - int code, int duration) override; - sigslot::signal0<>* GetOnDestroyedSignal() override; - // Implements DataChannelProviderInterface. bool SendData(const cricket::SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, @@ -288,10 +294,14 @@ class WebRtcSession : public AudioProviderInterface, // Returns stats for all channels of all transports. // This avoids exposing the internal structures used to track them. - virtual bool GetTransportStats(SessionStats* stats); - - // Get stats for a specific channel - bool GetChannelTransportStats(cricket::BaseChannel* ch, SessionStats* stats); + // The parameterless version creates |ChannelNamePairs| from |voice_channel|, + // |video_channel| and |voice_channel| if available - this requires it to be + // called on the signaling thread - and invokes the other |GetStats|. The + // other |GetStats| can be invoked on any thread; if not invoked on the + // network thread a thread hop will happen. + std::unique_ptr GetStats_s(); + virtual std::unique_ptr GetStats( + const ChannelNamePairs& channel_name_pairs); // virtual so it can be mocked in unit tests virtual bool GetLocalCertificate( @@ -304,13 +314,24 @@ class WebRtcSession : public AudioProviderInterface, cricket::DataChannelType data_channel_type() const; + // Returns true if there was an ICE restart initiated by the remote offer. bool IceRestartPending(const std::string& content_name) const; + // Set the "needs-ice-restart" flag as described in JSEP. After the flag is + // set, offers should generate new ufrags/passwords until an ICE restart + // occurs. + void SetNeedsIceRestartFlag(); + // Returns true if the ICE restart flag above was set, and no ICE restart has + // occurred yet for this transport (by applying a local description with + // changed ufrag/password). If the transport has been deleted as a result of + // bundling, returns false. + bool NeedsIceRestart(const std::string& content_name) const; + // Called when an RTCCertificate is generated or retrieved by // WebRTCSessionDescriptionFactory. Should happen before setLocalDescription. void OnCertificateReady( const rtc::scoped_refptr& certificate); - void OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp); + void OnDtlsSrtpSetupFailure(cricket::BaseChannel*, bool rtcp); // For unit test. bool waiting_for_certificate_for_testing() const; @@ -319,23 +340,28 @@ class WebRtcSession : public AudioProviderInterface, void set_metrics_observer( webrtc::MetricsObserverInterface* metrics_observer) { metrics_observer_ = metrics_observer; + transport_controller_->SetMetricsObserver(metrics_observer); } - // Called when voice_channel_, video_channel_ and data_channel_ are created - // and destroyed. As a result of, for example, setting a new description. + // Called when voice_channel_, video_channel_ and + // rtp_data_channel_/sctp_transport_ are created and destroyed. As a result + // of, for example, setting a new description. sigslot::signal0<> SignalVoiceChannelCreated; sigslot::signal0<> SignalVoiceChannelDestroyed; sigslot::signal0<> SignalVideoChannelCreated; sigslot::signal0<> SignalVideoChannelDestroyed; sigslot::signal0<> SignalDataChannelCreated; sigslot::signal0<> SignalDataChannelDestroyed; - // Called when the whole session is destroyed. - sigslot::signal0<> SignalDestroyed; // Called when a valid data channel OPEN message is received. // std::string represents the data channel label. sigslot::signal2 SignalDataChannelOpenMessage; +#ifdef HAVE_QUIC + QuicDataTransport* quic_data_transport() { + return quic_data_transport_.get(); + } +#endif // HAVE_QUIC private: // Indicates the type of SessionDescription in a call to SetLocalDescription @@ -346,6 +372,17 @@ class WebRtcSession : public AudioProviderInterface, kAnswer, }; + // Non-const versions of local_description()/remote_description(), for use + // internally. + SessionDescriptionInterface* mutable_local_description() { + return pending_local_description_ ? pending_local_description_.get() + : current_local_description_.get(); + } + SessionDescriptionInterface* mutable_remote_description() { + return pending_remote_description_ ? pending_remote_description_.get() + : current_remote_description_.get(); + } + // Log session state. void LogState(State old_state, State new_state); @@ -364,6 +401,7 @@ class WebRtcSession : public AudioProviderInterface, bool PushdownMediaDescription(cricket::ContentAction action, cricket::ContentSource source, std::string* error_desc); + bool PushdownSctpParameters_n(cricket::ContentSource source); bool PushdownTransportDescription(cricket::ContentSource source, cricket::ContentAction action, @@ -425,11 +463,27 @@ class WebRtcSession : public AudioProviderInterface, bool CreateDataChannel(const cricket::ContentInfo* content, const std::string* bundle_transport); - // Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN - // messages. - void OnDataChannelMessageReceived(cricket::DataChannel* channel, - const cricket::ReceiveDataParams& params, - const rtc::CopyOnWriteBuffer& payload); + std::unique_ptr GetStats_n( + const ChannelNamePairs& channel_name_pairs); + + bool CreateSctpTransport_n(const std::string& content_name, + const std::string& transport_name); + // For bundling. + void ChangeSctpTransport_n(const std::string& transport_name); + void DestroySctpTransport_n(); + // SctpTransport signal handlers. Needed to marshal signals from the network + // to signaling thread. + void OnSctpTransportReadyToSendData_n(); + // This may be called with "false" if the direction of the m= section causes + // us to tear down the SCTP connection. + void OnSctpTransportReadyToSendData_s(bool ready); + void OnSctpTransportDataReceived_n(const cricket::ReceiveDataParams& params, + const rtc::CopyOnWriteBuffer& payload); + // Beyond just firing the signal to the signaling thread, listens to SCTP + // CONTROL messages on unused SIDs and processes them as OPEN messages. + void OnSctpTransportDataReceived_s(const cricket::ReceiveDataParams& params, + const rtc::CopyOnWriteBuffer& payload); + void OnSctpStreamClosedRemotely_n(int sid); std::string BadStateErrMsg(State state); void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state); @@ -458,6 +512,11 @@ class WebRtcSession : public AudioProviderInterface, const SessionDescriptionInterface* remote_desc, bool* valid); + // Returns true if SRTP (either using DTLS-SRTP or SDES) is required by + // this session. + bool SrtpRequired() const; + + // TransportController signal handlers. void OnTransportControllerConnectionState(cricket::IceConnectionState state); void OnTransportControllerReceiving(bool receiving); void OnTransportControllerGatheringState(cricket::IceGatheringState state); @@ -466,6 +525,7 @@ class WebRtcSession : public AudioProviderInterface, const std::vector& candidates); void OnTransportControllerCandidatesRemoved( const std::vector& candidates); + void OnTransportControllerDtlsHandshakeError(rtc::SSLHandshakeError error); std::string GetSessionErrorMsg(); @@ -480,6 +540,14 @@ class WebRtcSession : public AudioProviderInterface, void OnSentPacket_w(const rtc::SentPacket& sent_packet); + const std::string GetTransportName(const std::string& content_name); + + void DestroyRtcpTransport_n(const std::string& transport_name); + void DestroyVideoChannel(); + void DestroyVoiceChannel(); + void DestroyDataChannel(); + + rtc::Thread* const network_thread_; rtc::Thread* const worker_thread_; rtc::Thread* const signaling_thread_; @@ -490,17 +558,48 @@ class WebRtcSession : public AudioProviderInterface, const std::string sid_; bool initial_offerer_ = false; - std::unique_ptr transport_controller_; + const std::unique_ptr transport_controller_; + const std::unique_ptr sctp_factory_; MediaControllerInterface* media_controller_; std::unique_ptr voice_channel_; std::unique_ptr video_channel_; - std::unique_ptr data_channel_; + // |rtp_data_channel_| is used if in RTP data channel mode, |sctp_transport_| + // when using SCTP. + std::unique_ptr rtp_data_channel_; + + std::unique_ptr sctp_transport_; + // |sctp_transport_name_| keeps track of what DTLS transport the SCTP + // transport is using (which can change due to bundling). + rtc::Optional sctp_transport_name_; + // |sctp_content_name_| is the content name (MID) in SDP. + rtc::Optional sctp_content_name_; + // Value cached on signaling thread. Only updated when SctpReadyToSendData + // fires on the signaling thread. + bool sctp_ready_to_send_data_ = false; + // Same as signals provided by SctpTransport, but these are guaranteed to + // fire on the signaling thread, whereas SctpTransport fires on the networking + // thread. + // |sctp_invoker_| is used so that any signals queued on the signaling thread + // from the network thread are immediately discarded if the SctpTransport is + // destroyed (due to m= section being rejected). + // TODO(deadbeef): Use a proxy object to ensure that method calls/signals + // are marshalled to the right thread. Could almost use proxy.h for this, + // but it doesn't have a mechanism for marshalling sigslot::signals + std::unique_ptr sctp_invoker_; + sigslot::signal1 SignalSctpReadyToSendData; + sigslot::signal2 + SignalSctpDataReceived; + sigslot::signal1 SignalSctpStreamClosedRemotely; + cricket::ChannelManager* channel_manager_; IceObserver* ice_observer_; PeerConnectionInterface::IceConnectionState ice_connection_state_; bool ice_connection_receiving_; - std::unique_ptr local_desc_; - std::unique_ptr remote_desc_; + std::unique_ptr current_local_description_; + std::unique_ptr pending_local_description_; + std::unique_ptr current_remote_description_; + std::unique_ptr pending_remote_description_; // If the remote peer is using a older version of implementation. bool older_version_remote_peer_; bool dtls_enabled_; @@ -511,6 +610,8 @@ class WebRtcSession : public AudioProviderInterface, // not set or false, SCTP is allowed (DCT_SCTP); // 2. If constraint kEnableRtpDataChannels is true, RTP is allowed (DCT_RTP); // 3. If both 1&2 are false, data channel is not allowed (DCT_NONE). + // The data channel type could be DCT_QUIC if the QUIC data channel is + // enabled. cricket::DataChannelType data_channel_type_; // List of content names for which the remote side triggered an ICE restart. std::set pending_ice_restarts_; @@ -528,8 +629,15 @@ class WebRtcSession : public AudioProviderInterface, // Declares the RTCP mux policy for the WebRTCSession. PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy_; + bool received_first_video_packet_ = false; + bool received_first_audio_packet_ = false; + +#ifdef HAVE_QUIC + std::unique_ptr quic_data_transport_; +#endif // HAVE_QUIC + RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSession); }; } // namespace webrtc -#endif // WEBRTC_API_WEBRTCSESSION_H_ +#endif // WEBRTC_PC_WEBRTCSESSION_H_ diff --git a/include/webrtc/api/webrtcsessiondescriptionfactory.h b/include/webrtc/pc/webrtcsessiondescriptionfactory.h similarity index 69% rename from include/webrtc/api/webrtcsessiondescriptionfactory.h rename to include/webrtc/pc/webrtcsessiondescriptionfactory.h index 17e2ddd..7572f24 100644 --- a/include/webrtc/api/webrtcsessiondescriptionfactory.h +++ b/include/webrtc/pc/webrtcsessiondescriptionfactory.h @@ -8,16 +8,16 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_API_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ -#define WEBRTC_API_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ +#ifndef WEBRTC_PC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ +#define WEBRTC_PC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ #include -#include "webrtc/api/dtlsidentitystore.h" #include "webrtc/api/peerconnectioninterface.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/messagehandler.h" #include "webrtc/base/rtccertificate.h" +#include "webrtc/base/rtccertificategenerator.h" #include "webrtc/p2p/base/transportdescriptionfactory.h" #include "webrtc/pc/mediasession.h" @@ -32,17 +32,17 @@ class MediaConstraintsInterface; class SessionDescriptionInterface; class WebRtcSession; -// DTLS identity request callback class. -class WebRtcIdentityRequestObserver : public DtlsIdentityRequestObserver, - public sigslot::has_slots<> { +// DTLS certificate request callback class. +class WebRtcCertificateGeneratorCallback + : public rtc::RTCCertificateGeneratorCallback, + public sigslot::has_slots<> { public: - // DtlsIdentityRequestObserver overrides. - void OnFailure(int error) override; - void OnSuccess(const std::string& der_cert, - const std::string& der_private_key) override; - void OnSuccess(std::unique_ptr identity) override; + // |rtc::RTCCertificateGeneratorCallback| overrides. + void OnSuccess( + const rtc::scoped_refptr& certificate) override; + void OnFailure() override; - sigslot::signal1 SignalRequestFailed; + sigslot::signal0<> SignalRequestFailed; sigslot::signal1&> SignalCertificateReady; }; @@ -66,37 +66,29 @@ struct CreateSessionDescriptionRequest { cricket::MediaSessionOptions options; }; -// This class is used to create offer/answer session description with regards to -// the async DTLS identity generation for WebRtcSession. -// It queues the create offer/answer request until the DTLS identity -// request has completed, i.e. when OnIdentityRequestFailed or OnIdentityReady -// is called. +// This class is used to create offer/answer session description. Certificates +// for WebRtcSession/DTLS are either supplied at construction or generated +// asynchronously. It queues the create offer/answer request until the +// certificate generation has completed, i.e. when OnCertificateRequestFailed or +// OnCertificateReady is called. class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, public sigslot::has_slots<> { public: - // Construct with DTLS disabled. - WebRtcSessionDescriptionFactory(rtc::Thread* signaling_thread, - cricket::ChannelManager* channel_manager, - WebRtcSession* session, - const std::string& session_id); - - // Construct with DTLS enabled using the specified |dtls_identity_store| to - // generate a certificate. + // If |certificate_generator| is not null, DTLS is enabled and a default + // certificate is generated asynchronously; otherwise DTLS is disabled. WebRtcSessionDescriptionFactory( rtc::Thread* signaling_thread, cricket::ChannelManager* channel_manager, - std::unique_ptr dtls_identity_store, WebRtcSession* session, - const std::string& session_id); - - // Construct with DTLS enabled using the specified (already generated) - // |certificate|. + const std::string& session_id, + std::unique_ptr cert_generator); + // Construct with DTLS enabled using the specified |certificate|. WebRtcSessionDescriptionFactory( rtc::Thread* signaling_thread, cricket::ChannelManager* channel_manager, - const rtc::scoped_refptr& certificate, WebRtcSession* session, - const std::string& session_id); + const std::string& session_id, + const rtc::scoped_refptr& certificate); virtual ~WebRtcSessionDescriptionFactory(); static void CopyCandidatesFromSessionDescription( @@ -130,15 +122,15 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, CERTIFICATE_FAILED, }; + // If |certificate_generator| or |certificate| is not null DTLS is enabled, + // otherwise DTLS is disabled. WebRtcSessionDescriptionFactory( rtc::Thread* signaling_thread, cricket::ChannelManager* channel_manager, - std::unique_ptr dtls_identity_store, - const rtc::scoped_refptr& - identity_request_observer, WebRtcSession* session, const std::string& session_id, - bool dtls_enabled); + std::unique_ptr cert_generator, + const rtc::scoped_refptr& certificate); // MessageHandler implementation. virtual void OnMessage(rtc::Message* msg); @@ -154,7 +146,7 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, CreateSessionDescriptionObserver* observer, SessionDescriptionInterface* description); - void OnIdentityRequestFailed(int error); + void OnCertificateRequestFailed(); void SetCertificate( const rtc::scoped_refptr& certificate); @@ -164,9 +156,7 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, cricket::TransportDescriptionFactory transport_desc_factory_; cricket::MediaSessionDescriptionFactory session_desc_factory_; uint64_t session_version_; - const std::unique_ptr dtls_identity_store_; - const rtc::scoped_refptr - identity_request_observer_; + const std::unique_ptr cert_generator_; // TODO(jiayl): remove the dependency on session once bug 2264 is fixed. WebRtcSession* const session_; const std::string session_id_; @@ -176,4 +166,4 @@ class WebRtcSessionDescriptionFactory : public rtc::MessageHandler, }; } // namespace webrtc -#endif // WEBRTC_API_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ +#endif // WEBRTC_PC_WEBRTCSESSIONDESCRIPTIONFACTORY_H_ diff --git a/include/webrtc/stats/test/rtcteststats.h b/include/webrtc/stats/test/rtcteststats.h new file mode 100644 index 0000000..a0ac8a1 --- /dev/null +++ b/include/webrtc/stats/test/rtcteststats.h @@ -0,0 +1,47 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_STATS_TEST_RTCTESTSTATS_H_ +#define WEBRTC_STATS_TEST_RTCTESTSTATS_H_ + +#include +#include + +#include "webrtc/api/stats/rtcstats.h" + +namespace webrtc { + +class RTCTestStats : public RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + RTCTestStats(const std::string& id, int64_t timestamp_us); + RTCTestStats(const RTCTestStats& other); + ~RTCTestStats() override; + + RTCStatsMember m_bool; + RTCStatsMember m_int32; + RTCStatsMember m_uint32; + RTCStatsMember m_int64; + RTCStatsMember m_uint64; + RTCStatsMember m_double; + RTCStatsMember m_string; + RTCStatsMember> m_sequence_bool; + RTCStatsMember> m_sequence_int32; + RTCStatsMember> m_sequence_uint32; + RTCStatsMember> m_sequence_int64; + RTCStatsMember> m_sequence_uint64; + RTCStatsMember> m_sequence_double; + RTCStatsMember> m_sequence_string; +}; + +} // namespace webrtc + +#endif // WEBRTC_STATS_TEST_RTCTESTSTATS_H_ diff --git a/include/webrtc/system_wrappers/include/aligned_array.h b/include/webrtc/system_wrappers/include/aligned_array.h index a2ffe99..71fefea 100644 --- a/include/webrtc/system_wrappers/include/aligned_array.h +++ b/include/webrtc/system_wrappers/include/aligned_array.h @@ -23,7 +23,7 @@ template class AlignedArray { AlignedArray(size_t rows, size_t cols, size_t alignment) : rows_(rows), cols_(cols) { - RTC_CHECK_GT(alignment, 0u); + RTC_CHECK_GT(alignment, 0); head_row_ = static_cast(AlignedMalloc(rows_ * sizeof(*head_row_), alignment)); for (size_t i = 0; i < rows_; ++i) { diff --git a/include/webrtc/system_wrappers/include/clock.h b/include/webrtc/system_wrappers/include/clock.h index a209770..5066844 100644 --- a/include/webrtc/system_wrappers/include/clock.h +++ b/include/webrtc/system_wrappers/include/clock.h @@ -13,6 +13,7 @@ #include +#include "webrtc/system_wrappers/include/ntp_time.h" #include "webrtc/system_wrappers/include/rw_lock_wrapper.h" #include "webrtc/typedefs.h" @@ -43,8 +44,14 @@ class Clock { // Retrieve an NTP absolute timestamp in milliseconds. virtual int64_t CurrentNtpInMilliseconds() const = 0; + // TODO(danilchap): Make pure virtual once implemented in derived classed + // replacing CurrentNtp function. + virtual NtpTime CurrentNtpTime() const; + // Converts an NTP timestamp to a millisecond timestamp. - static int64_t NtpToMs(uint32_t seconds, uint32_t fractions); + static int64_t NtpToMs(uint32_t seconds, uint32_t fractions) { + return NtpTime(seconds, fractions).ToMs(); + } // Returns an instance of the real-time system clock implementation. static Clock* GetRealTimeClock(); diff --git a/include/webrtc/system_wrappers/include/compile_assert_c.h b/include/webrtc/system_wrappers/include/compile_assert_c.h index b402d71..00f6306 100644 --- a/include/webrtc/system_wrappers/include/compile_assert_c.h +++ b/include/webrtc/system_wrappers/include/compile_assert_c.h @@ -11,14 +11,11 @@ #ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_COMPILE_ASSERT_H_ #define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_COMPILE_ASSERT_H_ -#ifdef __cplusplus -#error "Only use this for C files. For C++, use static_assert." -#endif - // Use this macro to verify at compile time that certain restrictions are met. // The argument is the boolean expression to evaluate. // Example: // COMPILE_ASSERT(sizeof(foo) < 128); +// Note: In C++, use static_assert instead! #define COMPILE_ASSERT(expression) switch (0) {case 0: case expression:;} #endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_COMPILE_ASSERT_H_ diff --git a/include/webrtc/system_wrappers/include/data_log.h b/include/webrtc/system_wrappers/include/data_log.h deleted file mode 100644 index f6cad88..0000000 --- a/include/webrtc/system_wrappers/include/data_log.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This singleton can be used for logging data for offline processing. Data -// logged with it can conveniently be parsed and processed with e.g. Matlab. -// -// Following is an example of the log file format, starting with the header -// row at line 1, and the data rows following. -// col1,col2,col3,multi-value-col4[3],,,col5 -// 123,10.2,-243,1,2,3,100 -// 241,12.3,233,1,2,3,200 -// 13,16.4,-13,1,2,3,300 -// -// As can be seen in the example, a multi-value-column is specified with the -// name followed the number of elements it contains. This followed by -// number of elements - 1 empty columns. -// -// Without multi-value-columns this format can be natively by Matlab. With -// multi-value-columns a small Matlab script is needed, available at -// trunk/tools/matlab/parseLog.m. -// -// Table names and column names are case sensitive. - -#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_H_ -#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_H_ - -#include - -#include "webrtc/system_wrappers/include/data_log_impl.h" - -namespace webrtc { - -class DataLog { - public: - // Creates a log which uses a separate thread (referred to as the file - // writer thread) for writing log rows to file. - // - // Calls to this function after the log object has been created will only - // increment the reference counter. - static int CreateLog(); - - // Decrements the reference counter and deletes the log when the counter - // reaches 0. Should be called equal number of times as successful calls to - // CreateLog or memory leak will occur. - static void ReturnLog(); - - // Combines the string table_name and the integer table_id into a new string - // table_name + _ + table_id. The new string will be lower-case. - static std::string Combine(const std::string& table_name, int table_id); - - // Adds a new table, with the name table_name, and creates the file, with the - // name table_name + ".txt", to which the table will be written. - // table_name is treated in a case sensitive way. - static int AddTable(const std::string& table_name); - - // Adds a new column to a table. The column will be a multi-value-column - // if multi_value_length is greater than 1. - // table_name and column_name are treated in a case sensitive way. - static int AddColumn(const std::string& table_name, - const std::string& column_name, - int multi_value_length); - - // Inserts a single value into a table with name table_name at the column with - // name column_name. - // Note that the ValueContainer makes use of the copy constructor, - // operator= and operator<< of the type T, and that the template type must - // implement a deep copy copy constructor and operator=. - // Copy constructor and operator= must not be disabled for the type T. - // table_name and column_name are treated in a case sensitive way. - template - static int InsertCell(const std::string& table_name, - const std::string& column_name, - T value) { - DataLogImpl* data_log = DataLogImpl::StaticInstance(); - if (data_log == NULL) - return -1; - return data_log->InsertCell( - table_name, - column_name, - new ValueContainer(value)); - } - - // Inserts an array of values into a table with name table_name at the - // column specified by column_name, which must be a multi-value-column. - // Note that the MultiValueContainer makes use of the copy constructor, - // operator= and operator<< of the type T, and that the template type - // must implement a deep copy copy constructor and operator=. - // Copy constructor and operator= must not be disabled for the type T. - // table_name and column_name are treated in a case sensitive way. - template - static int InsertCell(const std::string& table_name, - const std::string& column_name, - const T* array, - int length) { - DataLogImpl* data_log = DataLogImpl::StaticInstance(); - if (data_log == NULL) - return -1; - return data_log->InsertCell( - table_name, - column_name, - new MultiValueContainer(array, length)); - } - - // For the table with name table_name: Writes the current row to file. - // Starts a new empty row. - // table_name is treated in a case-sensitive way. - static int NextRow(const std::string& table_name); -}; - -} // namespace webrtc - -#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_H_ diff --git a/include/webrtc/system_wrappers/include/data_log_c.h b/include/webrtc/system_wrappers/include/data_log_c.h deleted file mode 100644 index d31e4d9..0000000 --- a/include/webrtc/system_wrappers/include/data_log_c.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This is a pure C wrapper of the DataLog class. The functions are directly -// mapped here except for InsertCell as C does not support templates. -// See data_log.h for a description of the functions. - -#ifndef SRC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_C_H_ -#define SRC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_C_H_ - -#include // size_t - -#include "webrtc/typedefs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// All char* parameters in this file are expected to be null-terminated -// character sequences. -int WebRtcDataLog_CreateLog(); -void WebRtcDataLog_ReturnLog(); -char* WebRtcDataLog_Combine(char* combined_name, size_t combined_len, - const char* table_name, int table_id); -int WebRtcDataLog_AddTable(const char* table_name); -int WebRtcDataLog_AddColumn(const char* table_name, const char* column_name, - int multi_value_length); - -int WebRtcDataLog_InsertCell_int(const char* table_name, - const char* column_name, - int value); -int WebRtcDataLog_InsertArray_int(const char* table_name, - const char* column_name, - const int* values, - int length); -int WebRtcDataLog_InsertCell_float(const char* table_name, - const char* column_name, - float value); -int WebRtcDataLog_InsertArray_float(const char* table_name, - const char* column_name, - const float* values, - int length); -int WebRtcDataLog_InsertCell_double(const char* table_name, - const char* column_name, - double value); -int WebRtcDataLog_InsertArray_double(const char* table_name, - const char* column_name, - const double* values, - int length); -int WebRtcDataLog_InsertCell_int32(const char* table_name, - const char* column_name, - int32_t value); -int WebRtcDataLog_InsertArray_int32(const char* table_name, - const char* column_name, - const int32_t* values, - int length); -int WebRtcDataLog_InsertCell_uint32(const char* table_name, - const char* column_name, - uint32_t value); -int WebRtcDataLog_InsertArray_uint32(const char* table_name, - const char* column_name, - const uint32_t* values, - int length); -int WebRtcDataLog_InsertCell_int64(const char* table_name, - const char* column_name, - int64_t value); -int WebRtcDataLog_InsertArray_int64(const char* table_name, - const char* column_name, - const int64_t* values, - int length); - -int WebRtcDataLog_NextRow(const char* table_name); - -#ifdef __cplusplus -} // end of extern "C" -#endif - -#endif // SRC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_C_H_ // NOLINT diff --git a/include/webrtc/system_wrappers/include/data_log_impl.h b/include/webrtc/system_wrappers/include/data_log_impl.h deleted file mode 100644 index 6d59fa8..0000000 --- a/include/webrtc/system_wrappers/include/data_log_impl.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// This file contains the helper classes for the DataLog APIs. See data_log.h -// for the APIs. -// -// These classes are helper classes used for logging data for offline -// processing. Data logged with these classes can conveniently be parsed and -// processed with e.g. Matlab. -#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_ -#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_ - -#include -#include -#include -#include -#include - -#include "webrtc/base/platform_thread.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -class CriticalSectionWrapper; -class EventWrapper; -class LogTable; -class RWLockWrapper; - -// All container classes need to implement a ToString-function to be -// writable to file. Enforce this via the Container interface. -class Container { - public: - virtual ~Container() {} - - virtual void ToString(std::string* container_string) const = 0; -}; - -template -class ValueContainer : public Container { - public: - explicit ValueContainer(T data) : data_(data) {} - - virtual void ToString(std::string* container_string) const { - *container_string = ""; - std::stringstream ss; - ss << data_ << ","; - ss >> *container_string; - } - - private: - T data_; -}; - -template -class MultiValueContainer : public Container { - public: - MultiValueContainer(const T* data, int length) - : data_(data, data + length) { - } - - virtual void ToString(std::string* container_string) const { - *container_string = ""; - std::stringstream ss; - for (size_t i = 0; i < data_.size(); ++i) - ss << data_[i] << ","; - *container_string += ss.str(); - } - - private: - std::vector data_; -}; - -class DataLogImpl { - public: - ~DataLogImpl(); - - // The implementation of the CreateLog() method declared in data_log.h. - // See data_log.h for a description. - static int CreateLog(); - - // The implementation of the StaticInstance() method declared in data_log.h. - // See data_log.h for a description. - static DataLogImpl* StaticInstance(); - - // The implementation of the ReturnLog() method declared in data_log.h. See - // data_log.h for a description. - static void ReturnLog(); - - // The implementation of the AddTable() method declared in data_log.h. See - // data_log.h for a description. - int AddTable(const std::string& table_name); - - // The implementation of the AddColumn() method declared in data_log.h. See - // data_log.h for a description. - int AddColumn(const std::string& table_name, - const std::string& column_name, - int multi_value_length); - - // Inserts a Container into a table with name table_name at the column - // with name column_name. - // column_name is treated in a case sensitive way. - int InsertCell(const std::string& table_name, - const std::string& column_name, - const Container* value_container); - - // The implementation of the NextRow() method declared in data_log.h. See - // data_log.h for a description. - int NextRow(const std::string& table_name); - - private: - DataLogImpl(); - - // Initializes the DataLogImpl object, allocates and starts the - // thread file_writer_thread_. - int Init(); - - // Write all complete rows in every table to file. - // This function should only be called by the file_writer_thread_ if that - // thread is running to avoid race conditions. - void Flush(); - - // Run() is called by the thread file_writer_thread_. - static bool Run(void* obj); - - // This function writes data to file. Note, it blocks if there is no data - // that should be written to file availble. Flush is the non-blocking - // version of this function. - void Process(); - - // Stops the continuous calling of Process(). - void StopThread(); - - // Collection of tables indexed by the table name as std::string. - typedef std::map TableMap; - typedef std::unique_ptr CritSectScopedPtr; - - static CritSectScopedPtr crit_sect_; - static DataLogImpl* instance_; - int counter_; - TableMap tables_; - EventWrapper* flush_event_; - // This is a unique_ptr so that we don't have to create threads in the no-op - // impl. - std::unique_ptr file_writer_thread_; - RWLockWrapper* tables_lock_; -}; - -} // namespace webrtc - -#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_ diff --git a/include/webrtc/system_wrappers/include/field_trial.h b/include/webrtc/system_wrappers/include/field_trial.h index 62fbfd1..b94be2c 100644 --- a/include/webrtc/system_wrappers/include/field_trial.h +++ b/include/webrtc/system_wrappers/include/field_trial.h @@ -62,6 +62,13 @@ namespace field_trial { // Note: To keep things tidy append all the trial names with WebRTC. std::string FindFullName(const std::string& name); +// Convenience method, returns true iff FindFullName(name) return a string that +// starts with "Enabled". +// TODO(tommi): Make sure all implementations support this. +inline bool IsEnabled(const char* name) { + return FindFullName(name).find("Enabled") == 0; +} + } // namespace field_trial } // namespace webrtc diff --git a/include/webrtc/system_wrappers/include/file_wrapper.h b/include/webrtc/system_wrappers/include/file_wrapper.h index b32a62f..a1d899c 100644 --- a/include/webrtc/system_wrappers/include/file_wrapper.h +++ b/include/webrtc/system_wrappers/include/file_wrapper.h @@ -14,6 +14,7 @@ #include #include +#include "webrtc/base/criticalsection.h" #include "webrtc/common_types.h" #include "webrtc/typedefs.h" @@ -22,55 +23,64 @@ namespace webrtc { +// TODO(tommi): Remove the base classes, rename to rtc::File and move to base. class FileWrapper : public InStream, public OutStream { public: static const size_t kMaxFileNameSize = 1024; - // Factory method. Constructor disabled. + // Factory methods. + // TODO(tommi): Remove Create(). static FileWrapper* Create(); + static FileWrapper Open(const char* file_name_utf8, bool read_only); + + FileWrapper(FILE* file, size_t max_size); + ~FileWrapper() override; + + // Support for move semantics. + FileWrapper(FileWrapper&& other); + FileWrapper& operator=(FileWrapper&& other); // Returns true if a file has been opened. - virtual bool Open() const = 0; + bool is_open() const { return file_ != nullptr; } // Opens a file in read or write mode, decided by the read_only parameter. - virtual int OpenFile(const char* file_name_utf8, - bool read_only, - bool loop = false, - bool text = false) = 0; + bool OpenFile(const char* file_name_utf8, bool read_only); - // Initializes the wrapper from an existing handle. |read_only| must match in - // the mode the file was opened in. If |manage_file| is true, the wrapper + // Initializes the wrapper from an existing handle. The wrapper // takes ownership of |handle| and closes it in CloseFile(). - virtual int OpenFromFileHandle(FILE* handle, - bool manage_file, - bool read_only, - bool loop = false) = 0; + bool OpenFromFileHandle(FILE* handle); - virtual int CloseFile() = 0; + void CloseFile(); // Limits the file size to |bytes|. Writing will fail after the cap // is hit. Pass zero to use an unlimited size. - virtual int SetMaxFileSize(size_t bytes) = 0; - - // Flush any pending writes. - virtual int Flush() = 0; - - // Returns the opened file's name in |file_name_utf8|. Provide the size of - // the buffer in bytes in |size|. The name will be truncated if |size| is - // too small. - virtual int FileName(char* file_name_utf8, - size_t size) const = 0; - - // Write |format| to the opened file. Arguments are taken in the same manner - // as printf. That is, supply a format string containing text and - // specifiers. Returns the number of characters written or -1 on error. - virtual int WriteText(const char* format, ...) = 0; - - // Inherited from both Instream and OutStream. - // Rewinds the file to the start. Only available when OpenFile() has been - // called with |loop| == true or |readOnly| == true. - // virtual int Rewind() = 0; + // TODO(tommi): Could we move this out into a separate class? + void SetMaxFileSize(size_t bytes); + + // Flush any pending writes. Note: Flushing when closing, is not required. + int Flush(); + + // Rewinds the file to the start. int Rewind() override; + int Read(void* buf, size_t length) override; + bool Write(const void* buf, size_t length) override; + + private: + FileWrapper(); + + void CloseFileImpl(); + int FlushImpl(); + + // TODO(tommi): Remove the lock. + rtc::CriticalSection lock_; + + FILE* file_ = nullptr; + size_t position_ = 0; + size_t max_size_in_bytes_ = 0; + + // Copying is not supported. + FileWrapper(const FileWrapper&) = delete; + FileWrapper& operator=(const FileWrapper&) = delete; }; } // namespace webrtc diff --git a/include/webrtc/system_wrappers/include/logcat_trace_context.h b/include/webrtc/system_wrappers/include/logcat_trace_context.h index 8bb01d8..fc36386 100644 --- a/include/webrtc/system_wrappers/include/logcat_trace_context.h +++ b/include/webrtc/system_wrappers/include/logcat_trace_context.h @@ -24,10 +24,10 @@ namespace webrtc { class LogcatTraceContext : public webrtc::TraceCallback { public: LogcatTraceContext(); - virtual ~LogcatTraceContext(); + ~LogcatTraceContext() override; // TraceCallback impl. - virtual void Print(TraceLevel level, const char* message, int length); + void Print(TraceLevel level, const char* message, int length) override; }; } // namespace webrtc diff --git a/include/webrtc/system_wrappers/include/metrics.h b/include/webrtc/system_wrappers/include/metrics.h index d5e5492..3ce6c20 100644 --- a/include/webrtc/system_wrappers/include/metrics.h +++ b/include/webrtc/system_wrappers/include/metrics.h @@ -44,7 +44,7 @@ // Histogram* histogram_pointer, const std::string& name, int sample); // // - or link with the default implementations (i.e. -// system_wrappers/system_wrappers.gyp:metrics_default). +// system_wrappers:metrics_default). // // // Example usage: @@ -58,6 +58,9 @@ // }; // // RTC_HISTOGRAM_ENUMERATION("WebRTC.Types", kTypeX, kBoundary); +// +// NOTE: It is recommended to do the Chromium review for modifications to +// histograms.xml before new metrics are committed to WebRTC. // Macros for adding samples to a named histogram. @@ -82,31 +85,13 @@ RTC_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50) #define RTC_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \ - RTC_HISTOGRAM_COMMON_BLOCK(name, sample, false, \ + RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \ webrtc::metrics::HistogramFactoryGetCounts(name, min, max, bucket_count)) -// RTC_HISTOGRAM_COUNTS with logging. -#define RTC_LOGGED_HISTOGRAM_COUNTS_100(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 100, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS_200(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 200, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS_500(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 500, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS_1000(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS_10000(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS_100000(name, sample) \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50) - -#define RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count) \ - RTC_HISTOGRAM_COMMON_BLOCK(name, sample, true, \ - webrtc::metrics::HistogramFactoryGetCounts(name, min, max, bucket_count)) +#define RTC_HISTOGRAM_COUNTS_LINEAR(name, sample, min, max, bucket_count) \ + RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \ + webrtc::metrics::HistogramFactoryGetCountsLinear( \ + name, min, max, bucket_count)) // Deprecated. // TODO(asapersson): Remove. @@ -121,55 +106,53 @@ #define RTC_HISTOGRAM_PERCENTAGE(name, sample) \ RTC_HISTOGRAM_ENUMERATION(name, sample, 101) -// RTC_HISTOGRAM_PERCENTAGE with logging. -#define RTC_LOGGED_HISTOGRAM_PERCENTAGE(name, sample) \ - RTC_LOGGED_HISTOGRAM_ENUMERATION(name, sample, 101) +// Histogram for booleans. +#define RTC_HISTOGRAM_BOOLEAN(name, sample) \ + RTC_HISTOGRAM_ENUMERATION(name, sample, 2) // Histogram for enumerators (evenly spaced buckets). // |boundary| should be above the max enumerator sample. #define RTC_HISTOGRAM_ENUMERATION(name, sample, boundary) \ - RTC_HISTOGRAM_COMMON_BLOCK(name, sample, false, \ - webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary)) - -// RTC_HISTOGRAM_ENUMERATION with logging. -#define RTC_LOGGED_HISTOGRAM_ENUMERATION(name, sample, boundary) \ - RTC_HISTOGRAM_COMMON_BLOCK(name, sample, true, \ + RTC_HISTOGRAM_COMMON_BLOCK(name, sample, \ webrtc::metrics::HistogramFactoryGetEnumeration(name, boundary)) // The name of the histogram should not vary. // TODO(asapersson): Consider changing string to const char*. -#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, log, \ - factory_get_invocation) \ - do { \ - if (log) { \ - LOG(LS_INFO) << constant_name << " " << sample; \ - } \ +#define RTC_HISTOGRAM_COMMON_BLOCK(constant_name, sample, \ + factory_get_invocation) \ + do { \ static webrtc::metrics::Histogram* atomic_histogram_pointer = nullptr; \ - webrtc::metrics::Histogram* histogram_pointer = \ - rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \ - if (!histogram_pointer) { \ - histogram_pointer = factory_get_invocation; \ - webrtc::metrics::Histogram* prev_pointer = \ - rtc::AtomicOps::CompareAndSwapPtr( \ - &atomic_histogram_pointer, \ - static_cast(nullptr), \ - histogram_pointer); \ - RTC_DCHECK(prev_pointer == nullptr || \ - prev_pointer == histogram_pointer); \ - } \ - webrtc::metrics::HistogramAdd(histogram_pointer, constant_name, sample); \ + webrtc::metrics::Histogram* histogram_pointer = \ + rtc::AtomicOps::AcquireLoadPtr(&atomic_histogram_pointer); \ + if (!histogram_pointer) { \ + histogram_pointer = factory_get_invocation; \ + webrtc::metrics::Histogram* prev_pointer = \ + rtc::AtomicOps::CompareAndSwapPtr( \ + &atomic_histogram_pointer, \ + static_cast(nullptr), \ + histogram_pointer); \ + RTC_DCHECK(prev_pointer == nullptr || \ + prev_pointer == histogram_pointer); \ + } \ + if (histogram_pointer) { \ + RTC_DCHECK_EQ(constant_name, \ + webrtc::metrics::GetHistogramName(histogram_pointer)) \ + << "The name should not vary."; \ + webrtc::metrics::HistogramAdd(histogram_pointer, sample); \ + } \ } while (0) // Deprecated. // The histogram is constructed/found for each call. -// May be used for histograms with infrequent updates. +// May be used for histograms with infrequent updates.` #define RTC_HISTOGRAM_COMMON_BLOCK_SLOW(name, sample, factory_get_invocation) \ - do { \ - webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \ - webrtc::metrics::HistogramAdd(histogram_pointer, name, sample); \ + do { \ + webrtc::metrics::Histogram* histogram_pointer = factory_get_invocation; \ + if (histogram_pointer) { \ + webrtc::metrics::HistogramAdd(histogram_pointer, sample); \ + } \ } while (0) - // Helper macros. // Macros for calling a histogram with varying name (e.g. when using a metric // in different modes such as real-time vs screenshare). @@ -205,39 +188,6 @@ RTC_HISTOGRAMS_COMMON(index, name, sample, \ RTC_HISTOGRAM_PERCENTAGE(name, sample)) -// RTC_HISTOGRAMS_COUNTS with logging. -#define RTC_LOGGED_HISTOGRAMS_COUNTS_100(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 100, 50)) - -#define RTC_LOGGED_HISTOGRAMS_COUNTS_200(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 200, 50)) - -#define RTC_LOGGED_HISTOGRAMS_COUNTS_500(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 500, 50)) - -#define RTC_LOGGED_HISTOGRAMS_COUNTS_1000(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 1000, 50)) - -#define RTC_LOGGED_HISTOGRAMS_COUNTS_10000(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 10000, 50)) - -#define RTC_LOGGED_HISTOGRAMS_COUNTS_100000(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_COUNTS(name, sample, 1, 100000, 50)) - -#define RTC_LOGGED_HISTOGRAMS_ENUMERATION(index, name, sample, boundary) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_ENUMERATION(name, sample, boundary)) - -#define RTC_LOGGED_HISTOGRAMS_PERCENTAGE(index, name, sample) \ - RTC_HISTOGRAMS_COMMON(index, name, sample, \ - RTC_LOGGED_HISTOGRAM_PERCENTAGE(name, sample)) - #define RTC_HISTOGRAMS_COMMON(index, name, sample, macro_invocation) \ do { \ switch (index) { \ @@ -271,18 +221,24 @@ class Histogram; Histogram* HistogramFactoryGetCounts( const std::string& name, int min, int max, int bucket_count); +// Get histogram for counters with linear bucket spacing. +Histogram* HistogramFactoryGetCountsLinear(const std::string& name, + int min, + int max, + int bucket_count); + // Get histogram for enumerators. // |boundary| should be above the max enumerator sample. Histogram* HistogramFactoryGetEnumeration( const std::string& name, int boundary); +// Returns name of the histogram. +const std::string& GetHistogramName(Histogram* histogram_pointer); + // Function for adding a |sample| to a histogram. -// |name| can be used to verify that it matches the histogram name. -void HistogramAdd( - Histogram* histogram_pointer, const std::string& name, int sample); +void HistogramAdd(Histogram* histogram_pointer, int sample); } // namespace metrics } // namespace webrtc #endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_H_ - diff --git a/include/webrtc/system_wrappers/include/metrics_default.h b/include/webrtc/system_wrappers/include/metrics_default.h new file mode 100644 index 0000000..e262198 --- /dev/null +++ b/include/webrtc/system_wrappers/include/metrics_default.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_DEFAULT_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_DEFAULT_H_ + +#include +#include +#include + +namespace webrtc { +namespace metrics { + +// This class does not actually exist. It is casted to an implementation defined +// pointer inside the functions. +class Histogram; + +struct SampleInfo { + SampleInfo(const std::string& name, int min, int max, size_t bucket_count); + ~SampleInfo(); + + const std::string name; + const int min; + const int max; + const size_t bucket_count; + std::map samples; // +}; + +// Enables collection of samples. +// This method should be called before any other call into webrtc. +void Enable(); + +// Gets histograms and clears all samples. +void GetAndReset( + std::map>* histograms); + +// Functions below are mainly for testing. + +// Clears all samples. +void Reset(); + +// Returns the number of times the |sample| has been added to the histogram. +int NumEvents(const std::string& name, int sample); + +// Returns the total number of added samples to the histogram. +int NumSamples(const std::string& name); + +// Returns the minimum sample value (or -1 if the histogram has no samples). +int MinSample(const std::string& name); + +} // namespace metrics +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_METRICS_DEFAULT_H_ diff --git a/include/webrtc/system_wrappers/include/ntp_time.h b/include/webrtc/system_wrappers/include/ntp_time.h index 229666e..5e53064 100644 --- a/include/webrtc/system_wrappers/include/ntp_time.h +++ b/include/webrtc/system_wrappers/include/ntp_time.h @@ -10,50 +10,45 @@ #ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_ #define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_NTP_TIME_H_ -#include "webrtc/base/basictypes.h" -#include "webrtc/system_wrappers/include/clock.h" +#include namespace webrtc { class NtpTime { public: - NtpTime() : seconds_(0), fractions_(0) {} - explicit NtpTime(const Clock& clock) { - clock.CurrentNtp(seconds_, fractions_); - } + static constexpr uint64_t kFractionsPerSecond = 0x100000000; + NtpTime() : value_(0) {} + explicit NtpTime(uint64_t value) : value_(value) {} NtpTime(uint32_t seconds, uint32_t fractions) - : seconds_(seconds), fractions_(fractions) {} + : value_(seconds * kFractionsPerSecond + fractions) {} NtpTime(const NtpTime&) = default; NtpTime& operator=(const NtpTime&) = default; + explicit operator uint64_t() const { return value_; } - void SetCurrent(const Clock& clock) { - clock.CurrentNtp(seconds_, fractions_); - } void Set(uint32_t seconds, uint32_t fractions) { - seconds_ = seconds; - fractions_ = fractions; - } - void Reset() { - seconds_ = 0; - fractions_ = 0; + value_ = seconds * kFractionsPerSecond + fractions; } + void Reset() { value_ = 0; } - int64_t ToMs() const { return Clock::NtpToMs(seconds_, fractions_); } - - // NTP standard (RFC1305, section 3.1) explicitly state value 0/0 is invalid. - bool Valid() const { return !(seconds_ == 0 && fractions_ == 0); } + int64_t ToMs() const { + static constexpr double kNtpFracPerMs = 4.294967296E6; // 2^32 / 1000. + const double frac_ms = static_cast(fractions()) / kNtpFracPerMs; + return 1000 * static_cast(seconds()) + + static_cast(frac_ms + 0.5); + } + // NTP standard (RFC1305, section 3.1) explicitly state value 0 is invalid. + bool Valid() const { return value_ != 0; } - uint32_t seconds() const { return seconds_; } - uint32_t fractions() const { return fractions_; } + uint32_t seconds() const { return value_ / kFractionsPerSecond; } + uint32_t fractions() const { return value_ % kFractionsPerSecond; } private: - uint32_t seconds_; - uint32_t fractions_; + uint64_t value_; }; inline bool operator==(const NtpTime& n1, const NtpTime& n2) { - return n1.seconds() == n2.seconds() && n1.fractions() == n2.fractions(); + return static_cast(n1) == static_cast(n2); } inline bool operator!=(const NtpTime& n1, const NtpTime& n2) { return !(n1 == n2); diff --git a/include/webrtc/system_wrappers/include/rtp_to_ntp.h b/include/webrtc/system_wrappers/include/rtp_to_ntp.h deleted file mode 100644 index 0c91928..0000000 --- a/include/webrtc/system_wrappers/include/rtp_to_ntp.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ -#define SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ - -#include - -#include "webrtc/typedefs.h" - -namespace webrtc { - -struct RtcpMeasurement { - RtcpMeasurement(); - RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); - uint32_t ntp_secs; - uint32_t ntp_frac; - uint32_t rtp_timestamp; -}; - -typedef std::list RtcpList; - -// Updates |rtcp_list| with timestamps from the latest RTCP SR. -// |new_rtcp_sr| will be set to true if these are the timestamps which have -// never be added to |rtcp_list|. -bool UpdateRtcpList(uint32_t ntp_secs, - uint32_t ntp_frac, - uint32_t rtp_timestamp, - RtcpList* rtcp_list, - bool* new_rtcp_sr); - -// Converts an RTP timestamp to the NTP domain in milliseconds using two -// (RTP timestamp, NTP timestamp) pairs. -bool RtpToNtpMs(int64_t rtp_timestamp, const RtcpList& rtcp, - int64_t* timestamp_in_ms); - -// Returns 1 there has been a forward wrap around, 0 if there has been no wrap -// around and -1 if there has been a backwards wrap around (i.e. reordering). -int CheckForWrapArounds(uint32_t rtp_timestamp, uint32_t rtcp_rtp_timestamp); - -} // namespace webrtc - -#endif // SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ diff --git a/include/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h b/include/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h new file mode 100644 index 0000000..a17428b --- /dev/null +++ b/include/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ + +#include + +#include "webrtc/system_wrappers/include/ntp_time.h" +#include "webrtc/typedefs.h" + +namespace webrtc { +// Class for converting an RTP timestamp to the NTP domain in milliseconds. +// The class needs to be trained with (at least 2) RTP/NTP timestamp pairs from +// RTCP sender reports before the convertion can be done. +class RtpToNtpEstimator { + public: + RtpToNtpEstimator(); + ~RtpToNtpEstimator(); + + // RTP and NTP timestamp pair from a RTCP SR report. + struct RtcpMeasurement { + RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); + bool IsEqual(const RtcpMeasurement& other) const; + + NtpTime ntp_time; + uint32_t rtp_timestamp; + }; + + // Estimated parameters from RTP and NTP timestamp pairs in |measurements_|. + struct Parameters { + double frequency_khz = 0.0; + double offset_ms = 0.0; + bool calculated = false; + }; + + // Updates measurements with RTP/NTP timestamp pair from a RTCP sender report. + // |new_rtcp_sr| is set to true if a new report is added. + bool UpdateMeasurements(uint32_t ntp_secs, + uint32_t ntp_frac, + uint32_t rtp_timestamp, + bool* new_rtcp_sr); + + // Converts an RTP timestamp to the NTP domain in milliseconds. + // Returns true on success, false otherwise. + bool Estimate(int64_t rtp_timestamp, int64_t* rtp_timestamp_ms) const; + + const Parameters& params() const { return params_; } + + private: + void UpdateParameters(); + + std::list measurements_; + Parameters params_; +}; + +// Returns: +// 1: forward wrap around. +// 0: no wrap around. +// -1: backwards wrap around (i.e. reordering). +int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp); + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ diff --git a/include/webrtc/system_wrappers/include/sort.h b/include/webrtc/system_wrappers/include/sort.h deleted file mode 100644 index 5bf2afa..0000000 --- a/include/webrtc/system_wrappers/include/sort.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Generic unstable sorting routines. - -#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SORT_H_ -#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SORT_H_ - -#include "webrtc/common_types.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -enum Type { - TYPE_Word8, - TYPE_UWord8, - TYPE_Word16, - TYPE_UWord16, - TYPE_Word32, - TYPE_UWord32, - TYPE_Word64, - TYPE_UWord64, - TYPE_Float32, - TYPE_Float64 -}; - -// Sorts intrinsic data types. -// -// data [in/out] A pointer to an array of intrinsic type. -// Upon return it will be sorted in ascending order. -// num_of_elements The number of elements in the array. -// data_type Enum corresponding to the type of the array. -// -// returns 0 on success, -1 on failure. -int32_t Sort(void* data, uint32_t num_of_elements, Type data_type); - -// Sorts arbitrary data types. This requires an array of intrinsically typed -// key values which will be used to sort the data array. There must be a -// one-to-one correspondence between data elements and key elements, with -// corresponding elements sharing the same position in their respective -// arrays. -// -// data [in/out] A pointer to an array of arbitrary type. -// Upon return it will be sorted in ascending order. -// key [in] A pointer to an array of keys used to sort the -// data array. -// num_of_elements The number of elements in the arrays. -// size_of_element The size, in bytes, of the data array. -// key_type Enum corresponding to the type of the key array. -// -// returns 0 on success, -1 on failure. -// -int32_t KeySort(void* data, void* key, uint32_t num_of_elements, - uint32_t size_of_element, Type key_type); - -} // namespace webrtc - -#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_SORT_H_ diff --git a/include/webrtc/system_wrappers/include/stl_util.h b/include/webrtc/system_wrappers/include/stl_util.h deleted file mode 100644 index b7a7021..0000000 --- a/include/webrtc/system_wrappers/include/stl_util.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -// Borrowed from Chromium's src/base/stl_util.h. - -#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_STL_UTIL_H_ -#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_STL_UTIL_H_ - -#include -#include -#include -#include -#include -#include - -namespace webrtc { - -// Clears internal memory of an STL object. -// STL clear()/reserve(0) does not always free internal memory allocated -// This function uses swap/destructor to ensure the internal memory is freed. -template -void STLClearObject(T* obj) { - T tmp; - tmp.swap(*obj); - // Sometimes "T tmp" allocates objects with memory (arena implementation?). - // Hence using additional reserve(0) even if it doesn't always work. - obj->reserve(0); -} - -// For a range within a container of pointers, calls delete (non-array version) -// on these pointers. -// NOTE: for these three functions, we could just implement a DeleteObject -// functor and then call for_each() on the range and functor, but this -// requires us to pull in all of algorithm.h, which seems expensive. -// For hash_[multi]set, it is important that this deletes behind the iterator -// because the hash_set may call the hash function on the iterator when it is -// advanced, which could result in the hash function trying to deference a -// stale pointer. -template -void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete *temp; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// BOTH items in the pairs. -// NOTE: Like STLDeleteContainerPointers, it is important that this deletes -// behind the iterator because if both the key and value are deleted, the -// container may call the hash function on the iterator when it is advanced, -// which could result in the hash function trying to dereference a stale -// pointer. -template -void STLDeleteContainerPairPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - delete temp->second; - } -} - -// For a range within a container of pairs, calls delete (non-array version) on -// the FIRST item in the pairs. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -template -void STLDeleteContainerPairFirstPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->first; - } -} - -// For a range within a container of pairs, calls delete. -// NOTE: Like STLDeleteContainerPointers, deleting behind the iterator. -// Deleting the value does not always invalidate the iterator, but it may -// do so if the key is a pointer into the value object. -template -void STLDeleteContainerPairSecondPointers(ForwardIterator begin, - ForwardIterator end) { - while (begin != end) { - ForwardIterator temp = begin; - ++begin; - delete temp->second; - } -} - -// To treat a possibly-empty vector as an array, use these functions. -// If you know the array will never be empty, you can use &*v.begin() -// directly, but that is undefined behaviour if |v| is empty. -template -inline T* vector_as_array(std::vector* v) { - return v->empty() ? NULL : &*v->begin(); -} - -template -inline const T* vector_as_array(const std::vector* v) { - return v->empty() ? NULL : &*v->begin(); -} - -// Return a mutable char* pointing to a string's internal buffer, -// which may not be null-terminated. Writing through this pointer will -// modify the string. -// -// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the -// next call to a string method that invalidates iterators. -// -// As of 2006-04, there is no standard-blessed way of getting a -// mutable reference to a string's internal buffer. However, issue 530 -// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) -// proposes this as the method. According to Matt Austern, this should -// already work on all current implementations. -inline char* string_as_array(std::string* str) { - // DO NOT USE const_cast(str->data()) - return str->empty() ? NULL : &*str->begin(); -} - -// The following functions are useful for cleaning up STL containers whose -// elements point to allocated memory. - -// STLDeleteElements() deletes all the elements in an STL container and clears -// the container. This function is suitable for use with a vector, set, -// hash_set, or any other STL container which defines sensible begin(), end(), -// and clear() methods. -// -// If container is NULL, this function is a no-op. -// -// As an alternative to calling STLDeleteElements() directly, consider -// STLElementDeleter (defined below), which ensures that your container's -// elements are deleted when the STLElementDeleter goes out of scope. -template -void STLDeleteElements(T* container) { - if (!container) - return; - STLDeleteContainerPointers(container->begin(), container->end()); - container->clear(); -} - -// Given an STL container consisting of (key, value) pairs, STLDeleteValues -// deletes all the "value" components and clears the container. Does nothing -// in the case it's given a NULL pointer. -template -void STLDeleteValues(T* container) { - if (!container) - return; - for (typename T::iterator i(container->begin()); i != container->end(); ++i) - delete i->second; - container->clear(); -} - - -// The following classes provide a convenient way to delete all elements or -// values from STL containers when they goes out of scope. This greatly -// simplifies code that creates temporary objects and has multiple return -// statements. Example: -// -// vector tmp_proto; -// STLElementDeleter > d(&tmp_proto); -// if (...) return false; -// ... -// return success; - -// Given a pointer to an STL container this class will delete all the element -// pointers when it goes out of scope. -template -class STLElementDeleter { - public: - STLElementDeleter(T* container) : container_(container) {} - ~STLElementDeleter() { STLDeleteElements(container_); } - - private: - T* container_; -}; - -// Given a pointer to an STL container this class will delete all the value -// pointers when it goes out of scope. -template -class STLValueDeleter { - public: - STLValueDeleter(T* container) : container_(container) {} - ~STLValueDeleter() { STLDeleteValues(container_); } - - private: - T* container_; -}; - -// Test to see if a set, map, hash_set or hash_map contains a particular key. -// Returns true if the key is in the collection. -template -bool ContainsKey(const Collection& collection, const Key& key) { - return collection.find(key) != collection.end(); -} - -// Returns true if the container is sorted. -template -bool STLIsSorted(const Container& cont) { - // Note: Use reverse iterator on container to ensure we only require - // value_type to implement operator<. - return std::adjacent_find(cont.rbegin(), cont.rend(), - std::less()) - == cont.rend(); -} - -// Returns a new ResultType containing the difference of two sorted containers. -template -ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) { - assert(STLIsSorted(a1)); - assert(STLIsSorted(a2)); - ResultType difference; - std::set_difference(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(difference, difference.end())); - return difference; -} - -// Returns a new ResultType containing the union of two sorted containers. -template -ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) { - assert(STLIsSorted(a1)); - assert(STLIsSorted(a2)); - ResultType result; - std::set_union(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(result, result.end())); - return result; -} - -// Returns a new ResultType containing the intersection of two sorted -// containers. -template -ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) { - assert(STLIsSorted(a1)); - assert(STLIsSorted(a2)); - ResultType result; - std::set_intersection(a1.begin(), a1.end(), - a2.begin(), a2.end(), - std::inserter(result, result.end())); - return result; -} - -// Returns true if the sorted container |a1| contains all elements of the sorted -// container |a2|. -template -bool STLIncludes(const Arg1& a1, const Arg2& a2) { - assert(STLIsSorted(a1)); - assert(STLIsSorted(a2)); - return std::includes(a1.begin(), a1.end(), - a2.begin(), a2.end()); -} - -} // namespace webrtc - -#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_STL_UTIL_H_ diff --git a/include/webrtc/system_wrappers/include/trace.h b/include/webrtc/system_wrappers/include/trace.h index 25a3d74..e3ca3c6 100644 --- a/include/webrtc/system_wrappers/include/trace.h +++ b/include/webrtc/system_wrappers/include/trace.h @@ -60,9 +60,6 @@ class Trace { static int32_t SetTraceFile(const char* file_name, const bool add_file_counter = false); - // Returns the name of the file that the trace is currently writing to. - static int32_t TraceFile(char file_name[1024]); - // Registers callback to receive trace messages. // TODO(hellner): Why not use OutStream instead? Why is TraceCallback not // defined in this file? diff --git a/include/webrtc/system_wrappers/source/data_log_c_helpers_unittest.h b/include/webrtc/system_wrappers/source/data_log_c_helpers_unittest.h deleted file mode 100644 index ef86eae..0000000 --- a/include/webrtc/system_wrappers/source/data_log_c_helpers_unittest.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_ -#define SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -int WebRtcDataLogCHelper_TestCreateLog(); - -int WebRtcDataLogCHelper_TestReturnLog(); - -int WebRtcDataLogCHelper_TestCombine(); - -int WebRtcDataLogCHelper_TestAddTable(); - -int WebRtcDataLogCHelper_TestAddColumn(); - -int WebRtcDataLogCHelper_TestNextRow(); - -int WebRtcDataLogCHelper_TestInsertCell_int(); - -int WebRtcDataLogCHelper_TestInsertArray_int(); - -int WebRtcDataLogCHelper_TestInsertCell_float(); - -int WebRtcDataLogCHelper_TestInsertArray_float(); - -int WebRtcDataLogCHelper_TestInsertCell_double(); - -int WebRtcDataLogCHelper_TestInsertArray_double(); - -int WebRtcDataLogCHelper_TestInsertCell_int32(); - -int WebRtcDataLogCHelper_TestInsertArray_int32(); - -int WebRtcDataLogCHelper_TestInsertCell_uint32(); - -int WebRtcDataLogCHelper_TestInsertArray_uint32(); - -int WebRtcDataLogCHelper_TestInsertCell_int64(); - -int WebRtcDataLogCHelper_TestInsertArray_int64(); - -#ifdef __cplusplus -} // end of extern "C" -#endif - -#endif // SRC_SYSTEM_WRAPPERS_SOURCE_DATA_LOG_C_HELPERS_UNITTEST_H_ diff --git a/include/webrtc/system_wrappers/source/file_impl.h b/include/webrtc/system_wrappers/source/file_impl.h deleted file mode 100644 index 51103d6..0000000 --- a/include/webrtc/system_wrappers/source/file_impl.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_ -#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_ - -#include - -#include - -#include "webrtc/system_wrappers/include/file_wrapper.h" - -namespace webrtc { - -class RWLockWrapper; - -class FileWrapperImpl : public FileWrapper { - public: - FileWrapperImpl(); - ~FileWrapperImpl() override; - - int FileName(char* file_name_utf8, size_t size) const override; - - bool Open() const override; - - int OpenFile(const char* file_name_utf8, - bool read_only, - bool loop = false, - bool text = false) override; - - int OpenFromFileHandle(FILE* handle, - bool manage_file, - bool read_only, - bool loop = false) override; - - int CloseFile() override; - int SetMaxFileSize(size_t bytes) override; - int Flush() override; - - int Read(void* buf, size_t length) override; - bool Write(const void* buf, size_t length) override; - int WriteText(const char* format, ...) override; - int Rewind() override; - - private: - int CloseFileImpl(); - int FlushImpl(); - - std::unique_ptr rw_lock_; - - FILE* id_; - bool managed_file_handle_; - bool open_; - bool looping_; - bool read_only_; - size_t max_size_in_bytes_; // -1 indicates file size limitation is off - size_t size_in_bytes_; - char file_name_utf8_[kMaxFileNameSize]; -}; - -} // namespace webrtc - -#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FILE_IMPL_H_ diff --git a/include/webrtc/system_wrappers/source/trace_impl.h b/include/webrtc/system_wrappers/source/trace_impl.h index 182f580..045b3cd 100644 --- a/include/webrtc/system_wrappers/source/trace_impl.h +++ b/include/webrtc/system_wrappers/source/trace_impl.h @@ -41,8 +41,6 @@ class TraceImpl : public Trace { static TraceImpl* GetTrace(const TraceLevel level = kTraceAll); int32_t SetTraceFileImpl(const char* file_name, const bool add_file_counter); - int32_t TraceFileImpl(char file_name[FileWrapper::kMaxFileNameSize]); - int32_t SetTraceCallbackImpl(TraceCallback* callback); void AddImpl(const TraceLevel level, const TraceModule module, @@ -82,9 +80,8 @@ class TraceImpl : public Trace { const TraceLevel level); bool UpdateFileName( - const char file_name_utf8[FileWrapper::kMaxFileNameSize], - char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize], - const uint32_t new_count) const; + char file_name_with_counter_utf8[FileWrapper::kMaxFileNameSize], + const uint32_t new_count) const EXCLUSIVE_LOCKS_REQUIRED(crit_); bool CreateFileName( const char file_name_utf8[FileWrapper::kMaxFileNameSize], @@ -99,6 +96,7 @@ class TraceImpl : public Trace { uint32_t file_count_text_ GUARDED_BY(crit_); const std::unique_ptr trace_file_ GUARDED_BY(crit_); + std::string trace_file_path_ GUARDED_BY(crit_); rtc::CriticalSection crit_; }; diff --git a/include/webrtc/typedefs.h b/include/webrtc/typedefs.h index e65b77a..16e10c5 100644 --- a/include/webrtc/typedefs.h +++ b/include/webrtc/typedefs.h @@ -37,12 +37,12 @@ #define WEBRTC_ARCH_32_BITS #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__MIPSEL__) +#define WEBRTC_ARCH_MIPS_FAMILY #if defined(__LP64__) -#define WEBRTC_ARCH_MIPS64_FAMILY +#define WEBRTC_ARCH_64_BITS #else -#define WEBRTC_ARCH_MIPS_FAMILY -#endif #define WEBRTC_ARCH_32_BITS +#endif #define WEBRTC_ARCH_LITTLE_ENDIAN #elif defined(__pnacl__) #define WEBRTC_ARCH_32_BITS @@ -61,7 +61,6 @@ #define WEBRTC_CPU_DETECTION #endif -// TODO(pbos): Use webrtc/base/basictypes.h instead to include fixed-size ints. #include // Annotate a function indicating the caller must examine the return value. @@ -99,6 +98,7 @@ #endif #endif +#ifndef NO_RETURN // Annotate a function that will not return control flow to the caller. #if defined(_MSC_VER) #define NO_RETURN __declspec(noreturn) @@ -107,5 +107,6 @@ #else #define NO_RETURN #endif +#endif #endif // WEBRTC_TYPEDEFS_H_ diff --git a/include/webrtc/video_decoder.h b/include/webrtc/video_decoder.h index 4f25e1f..70c0912 100644 --- a/include/webrtc/video_decoder.h +++ b/include/webrtc/video_decoder.h @@ -24,7 +24,7 @@ namespace webrtc { class RTPFragmentationHeader; // TODO(pbos): Expose these through a public (root) header or change these APIs. struct CodecSpecificInfo; -struct VideoCodec; +class VideoCodec; class DecodedImageCallback { public: @@ -35,11 +35,18 @@ class DecodedImageCallback { // decode time excluding waiting time for any previous pending frame to // return. This is necessary for breaking positive feedback in the delay // estimation when the decoder has a single output buffer. - // TODO(perkj): Remove default implementation when chromium has been updated. virtual int32_t Decoded(VideoFrame& decodedImage, int64_t decode_time_ms) { // The default implementation ignores custom decode time value. return Decoded(decodedImage); } + // TODO(sakal): Remove other implementations when upstream projects have been + // updated. + virtual void Decoded(VideoFrame& decodedImage, + rtc::Optional decode_time_ms, + rtc::Optional qp) { + Decoded(decodedImage, + decode_time_ms ? static_cast(*decode_time_ms) : -1); + } virtual int32_t ReceivedDecodedReferenceFrame(const uint64_t pictureId) { return -1; @@ -50,15 +57,6 @@ class DecodedImageCallback { class VideoDecoder { public: - enum DecoderType { - kH264, - kVp8, - kVp9, - kUnsupportedCodec, - }; - - static VideoDecoder* Create(DecoderType codec_type); - virtual ~VideoDecoder() {} virtual int32_t InitDecode(const VideoCodec* codec_settings, @@ -83,67 +81,6 @@ class VideoDecoder { virtual const char* ImplementationName() const { return "unknown"; } }; -// Class used to wrap external VideoDecoders to provide a fallback option on -// software decoding when a hardware decoder fails to decode a stream due to -// hardware restrictions, such as max resolution. -class VideoDecoderSoftwareFallbackWrapper : public webrtc::VideoDecoder { - public: - VideoDecoderSoftwareFallbackWrapper(VideoCodecType codec_type, - VideoDecoder* decoder); - - int32_t InitDecode(const VideoCodec* codec_settings, - int32_t number_of_cores) override; - - int32_t Decode(const EncodedImage& input_image, - bool missing_frames, - const RTPFragmentationHeader* fragmentation, - const CodecSpecificInfo* codec_specific_info, - int64_t render_time_ms) override; - - int32_t RegisterDecodeCompleteCallback( - DecodedImageCallback* callback) override; - - int32_t Release() override; - bool PrefersLateDecoding() const override; - - const char* ImplementationName() const override; - - private: - bool InitFallbackDecoder(); - - const DecoderType decoder_type_; - VideoDecoder* const decoder_; - - VideoCodec codec_settings_; - int32_t number_of_cores_; - std::string fallback_implementation_name_; - std::unique_ptr fallback_decoder_; - DecodedImageCallback* callback_; -}; - -// Video decoder class to be used for unknown codecs. Doesn't support decoding -// but logs messages to LS_ERROR. -class NullVideoDecoder : public VideoDecoder { - public: - NullVideoDecoder(); - - int32_t InitDecode(const VideoCodec* codec_settings, - int32_t number_of_cores) override; - - int32_t Decode(const EncodedImage& input_image, - bool missing_frames, - const RTPFragmentationHeader* fragmentation, - const CodecSpecificInfo* codec_specific_info, - int64_t render_time_ms) override; - - int32_t RegisterDecodeCompleteCallback( - DecodedImageCallback* callback) override; - - int32_t Release() override; - - const char* ImplementationName() const override; -}; - } // namespace webrtc #endif // WEBRTC_VIDEO_DECODER_H_ diff --git a/include/webrtc/video_encoder.h b/include/webrtc/video_encoder.h index 0100239..0a21fa3 100644 --- a/include/webrtc/video_encoder.h +++ b/include/webrtc/video_encoder.h @@ -15,26 +15,53 @@ #include #include +#include "webrtc/base/checks.h" #include "webrtc/common_types.h" #include "webrtc/typedefs.h" #include "webrtc/video_frame.h" +#include "webrtc/base/optional.h" namespace webrtc { class RTPFragmentationHeader; // TODO(pbos): Expose these through a public (root) header or change these APIs. struct CodecSpecificInfo; -struct VideoCodec; +class VideoCodec; class EncodedImageCallback { public: virtual ~EncodedImageCallback() {} + struct Result { + enum Error { + OK, + + // Failed to send the packet. + ERROR_SEND_FAILED, + }; + + Result(Error error) : error(error) {} + Result(Error error, uint32_t frame_id) : error(error), frame_id(frame_id) {} + + Error error; + + // Frame ID assigned to the frame. The frame ID should be the same as the ID + // seen by the receiver for this frame. RTP timestamp of the frame is used + // as frame ID when RTP is used to send video. Must be used only when + // error=OK. + uint32_t frame_id = 0; + + // Tells the encoder that the next frame is should be dropped. + bool drop_next_frame = false; + }; + // Callback function which is called when an image has been encoded. - // TODO(perkj): Change this to return void. - virtual int32_t Encoded(const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_specific_info, - const RTPFragmentationHeader* fragmentation) = 0; + virtual Result OnEncodedImage( + const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_specific_info, + const RTPFragmentationHeader* fragmentation) = 0; + + virtual void OnDroppedFrame() {} }; class VideoEncoder { @@ -45,8 +72,25 @@ class VideoEncoder { kVp9, kUnsupportedCodec, }; - + struct QpThresholds { + QpThresholds(int l, int h) : low(l), high(h) {} + QpThresholds() : low(-1), high(-1) {} + int low; + int high; + }; + struct ScalingSettings { + ScalingSettings(bool on, int low, int high) + : enabled(on), + thresholds(rtc::Optional(QpThresholds(low, high))) {} + explicit ScalingSettings(bool on) : enabled(on) {} + const bool enabled; + const rtc::Optional thresholds; + }; static VideoEncoder* Create(EncoderType codec_type); + // Returns true if this type of encoder can be created using + // VideoEncoder::Create. + static bool IsSupportedSoftware(EncoderType codec_type); + static EncoderType CodecToEncoderType(VideoCodecType codec_type); static VideoCodecVP8 GetDefaultVp8Settings(); static VideoCodecVP9 GetDefaultVp9Settings(); @@ -121,65 +165,28 @@ class VideoEncoder { // - framerate : The target frame rate // // Return value : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise. - virtual int32_t SetRates(uint32_t bitrate, uint32_t framerate) = 0; + virtual int32_t SetRates(uint32_t bitrate, uint32_t framerate) { + RTC_NOTREACHED() << "SetRate(uint32_t, uint32_t) is deprecated."; + return -1; + } + + // Default fallback: Just use the sum of bitrates as the single target rate. + // TODO(sprang): Remove this default implementation when we remove SetRates(). + virtual int32_t SetRateAllocation(const BitrateAllocation& allocation, + uint32_t framerate) { + return SetRates(allocation.get_sum_kbps(), framerate); + } + + // Any encoder implementation wishing to use the WebRTC provided + // quality scaler must implement this method. + virtual ScalingSettings GetScalingSettings() const { + return ScalingSettings(false); + } virtual int32_t SetPeriodicKeyFrames(bool enable) { return -1; } - virtual void OnDroppedFrame() {} virtual bool SupportsNativeHandle() const { return false; } virtual const char* ImplementationName() const { return "unknown"; } }; -// Class used to wrap external VideoEncoders to provide a fallback option on -// software encoding when a hardware encoder fails to encode a stream due to -// hardware restrictions, such as max resolution. -class VideoEncoderSoftwareFallbackWrapper : public VideoEncoder { - public: - VideoEncoderSoftwareFallbackWrapper(VideoCodecType codec_type, - webrtc::VideoEncoder* encoder); - - int32_t InitEncode(const VideoCodec* codec_settings, - int32_t number_of_cores, - size_t max_payload_size) override; - - int32_t RegisterEncodeCompleteCallback( - EncodedImageCallback* callback) override; - - int32_t Release() override; - int32_t Encode(const VideoFrame& frame, - const CodecSpecificInfo* codec_specific_info, - const std::vector* frame_types) override; - int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override; - - int32_t SetRates(uint32_t bitrate, uint32_t framerate) override; - void OnDroppedFrame() override; - bool SupportsNativeHandle() const override; - const char* ImplementationName() const override; - - private: - bool InitFallbackEncoder(); - - // Settings used in the last InitEncode call and used if a dynamic fallback to - // software is required. - VideoCodec codec_settings_; - int32_t number_of_cores_; - size_t max_payload_size_; - - // The last bitrate/framerate set, and a flag for noting they are set. - bool rates_set_; - uint32_t bitrate_; - uint32_t framerate_; - - // The last channel parameters set, and a flag for noting they are set. - bool channel_parameters_set_; - uint32_t packet_loss_; - int64_t rtt_; - - const EncoderType encoder_type_; - webrtc::VideoEncoder* const encoder_; - - std::unique_ptr fallback_encoder_; - std::string fallback_implementation_name_; - EncodedImageCallback* callback_; -}; } // namespace webrtc #endif // WEBRTC_VIDEO_ENCODER_H_ diff --git a/include/webrtc/video_frame.h b/include/webrtc/video_frame.h index 4dc3411..3b0c16c 100644 --- a/include/webrtc/video_frame.h +++ b/include/webrtc/video_frame.h @@ -11,134 +11,19 @@ #ifndef WEBRTC_VIDEO_FRAME_H_ #define WEBRTC_VIDEO_FRAME_H_ -#include "webrtc/base/scoped_ref_ptr.h" +// TODO(nisse): This header file should eventually be deleted. For +// declarations of classes related to unencoded video frame, use the +// headers under api/video instead. The EncodedImage class stays in +// this file until we have figured out how to refactor and clean up +// related interfaces. + +#include "webrtc/api/video/video_frame.h" +#include "webrtc/api/video/i420_buffer.h" #include "webrtc/common_types.h" -#include "webrtc/common_video/include/video_frame_buffer.h" -#include "webrtc/common_video/rotation.h" #include "webrtc/typedefs.h" namespace webrtc { -class VideoFrame { - public: - VideoFrame(); - VideoFrame(const rtc::scoped_refptr& buffer, - uint32_t timestamp, - int64_t render_time_ms, - VideoRotation rotation); - - // CreateEmptyFrame: Sets frame dimensions and allocates buffers based - // on set dimensions - height and plane stride. - // If required size is bigger than the allocated one, new buffers of adequate - // size will be allocated. - void CreateEmptyFrame(int width, - int height, - int stride_y, - int stride_u, - int stride_v); - - // CreateFrame: Sets the frame's members and buffers. If required size is - // bigger than allocated one, new buffers of adequate size will be allocated. - void CreateFrame(const uint8_t* buffer_y, - const uint8_t* buffer_u, - const uint8_t* buffer_v, - int width, - int height, - int stride_y, - int stride_u, - int stride_v, - VideoRotation rotation); - - // CreateFrame: Sets the frame's members and buffers. If required size is - // bigger than allocated one, new buffers of adequate size will be allocated. - // |buffer| must be a packed I420 buffer. - void CreateFrame(const uint8_t* buffer, - int width, - int height, - VideoRotation rotation); - - // Deep copy frame: If required size is bigger than allocated one, new - // buffers of adequate size will be allocated. - void CopyFrame(const VideoFrame& videoFrame); - - // Creates a shallow copy of |videoFrame|, i.e, the this object will retain a - // reference to the video buffer also retained by |videoFrame|. - void ShallowCopy(const VideoFrame& videoFrame); - - // Get allocated size per plane. - int allocated_size(PlaneType type) const; - - // Get frame width. - int width() const; - - // Get frame height. - int height() const; - - // Set frame timestamp (90kHz). - void set_timestamp(uint32_t timestamp) { timestamp_ = timestamp; } - - // Get frame timestamp (90kHz). - uint32_t timestamp() const { return timestamp_; } - - // Set capture ntp time in miliseconds. - void set_ntp_time_ms(int64_t ntp_time_ms) { - ntp_time_ms_ = ntp_time_ms; - } - - // Get capture ntp time in miliseconds. - int64_t ntp_time_ms() const { return ntp_time_ms_; } - - // Naming convention for Coordination of Video Orientation. Please see - // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf - // - // "pending rotation" or "pending" = a frame that has a VideoRotation > 0. - // - // "not pending" = a frame that has a VideoRotation == 0. - // - // "apply rotation" = modify a frame from being "pending" to being "not - // pending" rotation (a no-op for "unrotated"). - // - VideoRotation rotation() const { return rotation_; } - void set_rotation(VideoRotation rotation) { - rotation_ = rotation; - } - - // Set render time in miliseconds. - void set_render_time_ms(int64_t render_time_ms) { - render_time_ms_ = render_time_ms; - } - - // Get render time in miliseconds. - int64_t render_time_ms() const { return render_time_ms_; } - - // Return true if underlying plane buffers are of zero size, false if not. - bool IsZeroSize() const; - - // Return the underlying buffer. Never nullptr for a properly - // initialized VideoFrame. - // Creating a new reference breaks the HasOneRef and IsMutable - // logic. So return a const ref to our reference. - const rtc::scoped_refptr& video_frame_buffer() - const; - - // Set the underlying buffer. - void set_video_frame_buffer( - const rtc::scoped_refptr& buffer); - - // Convert native-handle frame to memory-backed I420 frame. Should not be - // called on a non-native-handle frame. - VideoFrame ConvertNativeToI420Frame() const; - - private: - // An opaque reference counted handle that stores the pixel data. - rtc::scoped_refptr video_frame_buffer_; - uint32_t timestamp_; - int64_t ntp_time_ms_; - int64_t render_time_ms_; - VideoRotation rotation_; -}; - - // TODO(pbos): Rename EncodedFrame and reformat this class' members. class EncodedImage { public: @@ -153,14 +38,10 @@ class EncodedImage { EncodedImage(uint8_t* buffer, size_t length, size_t size) : _buffer(buffer), _length(length), _size(size) {} + // TODO(kthelgason): get rid of this struct as it only has a single member + // remaining. struct AdaptReason { - AdaptReason() - : quality_resolution_downscales(-1), - bw_resolutions_disabled(-1) {} - - int quality_resolution_downscales; // Number of times this frame is down - // scaled in resolution due to quality. - // Or -1 if information is not provided. + AdaptReason() : bw_resolutions_disabled(-1) {} int bw_resolutions_disabled; // Number of resolutions that are not sent // due to bandwidth for this frame. // Or -1 if information is not provided. @@ -179,6 +60,11 @@ class EncodedImage { bool _completeFrame = false; AdaptReason adapt_reason_; int qp_ = -1; // Quantizer value. + + // When an application indicates non-zero values here, it is taken as an + // indication that all future frames will be constrained with those limits + // until the application indicates a change again. + PlayoutDelay playout_delay_ = {-1, -1}; }; } // namespace webrtc diff --git a/include/webrtc/video_receive_stream.h b/include/webrtc/video_receive_stream.h index 167df47..12629d0 100644 --- a/include/webrtc/video_receive_stream.h +++ b/include/webrtc/video_receive_stream.h @@ -16,11 +16,12 @@ #include #include +#include "webrtc/api/call/transport.h" +#include "webrtc/base/platform_file.h" #include "webrtc/common_types.h" #include "webrtc/common_video/include/frame_callback.h" #include "webrtc/config.h" #include "webrtc/media/base/videosinkinterface.h" -#include "webrtc/transport.h" namespace webrtc { @@ -43,12 +44,20 @@ class VideoReceiveStream { // Name of the decoded payload (such as VP8). Maps back to the depacketizer // used to unpack incoming packets. std::string payload_name; + + // This map contains the codec specific parameters from SDP, i.e. the "fmtp" + // parameters. It is the same as cricket::CodecParameterMap used in + // cricket::VideoCodec. + std::map codec_params; }; struct Stats { + std::string ToString(int64_t time_ms) const; + int network_frame_rate = 0; int decode_frame_rate = 0; int render_frame_rate = 0; + uint32_t frames_rendered = 0; // Decoder stats. std::string decoder_implementation_name = "unknown"; @@ -60,12 +69,17 @@ class VideoReceiveStream { int jitter_buffer_ms = 0; int min_playout_delay_ms = 0; int render_delay_ms = 10; + uint32_t frames_decoded = 0; + rtc::Optional qp_sum; int current_payload_type = -1; int total_bitrate_bps = 0; int discarded_packets = 0; + int width = 0; + int height = 0; + int sync_offset_ms = std::numeric_limits::max(); uint32_t ssrc = 0; @@ -76,10 +90,23 @@ class VideoReceiveStream { }; struct Config { + private: + // Access to the copy constructor is private to force use of the Copy() + // method for those exceptional cases where we do use it. + Config(const Config&) = default; + + public: Config() = delete; + Config(Config&&) = default; explicit Config(Transport* rtcp_send_transport) : rtcp_send_transport(rtcp_send_transport) {} + Config& operator=(Config&&) = default; + Config& operator=(const Config&) = delete; + + // Mostly used by tests. Avoid creating copies if you can. + Config Copy() const { return Config(*this); } + std::string ToString() const; // Decoders for every payload that we can receive. @@ -91,6 +118,7 @@ class VideoReceiveStream { // Synchronization source (stream identifier) to be received. uint32_t remote_ssrc = 0; + // Sender SSRC used for sending RTCP (such as receiver reports). uint32_t local_ssrc = 0; @@ -113,27 +141,15 @@ class VideoReceiveStream { // See NackConfig for description. NackConfig nack; - // See FecConfig for description. - FecConfig fec; - - // RTX settings for incoming video payloads that may be received. RTX is - // disabled if there's no config present. - struct Rtx { - // SSRCs to use for the RTX streams. - uint32_t ssrc = 0; - - // Payload type to use for the RTX stream. - int payload_type = 0; - }; + // See UlpfecConfig for description. + UlpfecConfig ulpfec; - // Map from video RTP payload type -> RTX config. - typedef std::map RtxMap; - RtxMap rtx; + // SSRC for retransmissions. + uint32_t rtx_ssrc = 0; - // If set to true, the RTX payload type mapping supplied in |rtx| will be - // used when restoring RTX packets. Without it, RTX packets will always be - // restored to the last non-RTX packet payload type received. - bool use_rtx_payload_mapping_on_restore = false; + // Map from video payload type (apt) -> RTX payload type (pt). + // For RTX to be enabled, both an SSRC and this mapping are needed. + std::map rtx_payload_types; // RTP header extensions used for the received stream. std::vector extensions; @@ -142,8 +158,7 @@ class VideoReceiveStream { // Transport for outgoing packets (RTCP). Transport* rtcp_send_transport = nullptr; - // VideoRenderer will be called for each decoded frame. 'nullptr' disables - // rendering of this stream. + // Must not be 'nullptr' when the stream is started. rtc::VideoSinkInterface* renderer = nullptr; // Expected delay needed by the renderer, i.e. the frame will be delivered @@ -165,11 +180,6 @@ class VideoReceiveStream { // saving the stream to a file. 'nullptr' disables the callback. EncodedFrameObserver* pre_decode_callback = nullptr; - // Called for each decoded frame. E.g. used when adding effects to the - // decoded - // stream. 'nullptr' disables the callback. - I420FrameCallback* pre_render_callback = nullptr; - // Target delay in milliseconds. A positive value indicates this stream is // used for streaming instead of a real-time call. int target_delay_ms = 0; @@ -185,6 +195,17 @@ class VideoReceiveStream { // TODO(pbos): Add info on currently-received codec to Stats. virtual Stats GetStats() const = 0; + // Takes ownership of the file, is responsible for closing it later. + // Calling this method will close and finalize any current log. + // Giving rtc::kInvalidPlatformFileValue disables logging. + // If a frame to be written would make the log too large the write fails and + // the log is closed and finalized. A |byte_limit| of 0 means no limit. + virtual void EnableEncodedFrameRecording(rtc::PlatformFile file, + size_t byte_limit) = 0; + inline void DisableEncodedFrameRecording() { + EnableEncodedFrameRecording(rtc::kInvalidPlatformFileValue, 0); + } + protected: virtual ~VideoReceiveStream() {} }; diff --git a/include/webrtc/video_send_stream.h b/include/webrtc/video_send_stream.h index 886367f..680eb02 100644 --- a/include/webrtc/video_send_stream.h +++ b/include/webrtc/video_send_stream.h @@ -13,35 +13,30 @@ #include #include +#include +#include +#include +#include "webrtc/api/call/transport.h" +#include "webrtc/base/platform_file.h" #include "webrtc/common_types.h" #include "webrtc/common_video/include/frame_callback.h" #include "webrtc/config.h" #include "webrtc/media/base/videosinkinterface.h" -#include "webrtc/transport.h" -#include "webrtc/media/base/videosinkinterface.h" +#include "webrtc/media/base/videosourceinterface.h" namespace webrtc { -class LoadObserver; class VideoEncoder; -// Class to deliver captured frame to the video send stream. -class VideoCaptureInput { - public: - // These methods do not lock internally and must be called sequentially. - // If your application switches input sources synchronization must be done - // externally to make sure that any old frames are not delivered concurrently. - virtual void IncomingCapturedFrame(const VideoFrame& video_frame) = 0; - - protected: - virtual ~VideoCaptureInput() {} -}; - class VideoSendStream { public: struct StreamStats { + std::string ToString() const; + FrameCounts frame_counts; + bool is_rtx = false; + bool is_flexfec = false; int width = 0; int height = 0; // TODO(holmer): Move bitrate_bps out to the webrtc::Call layer. @@ -55,26 +50,54 @@ class VideoSendStream { }; struct Stats { + std::string ToString(int64_t time_ms) const; std::string encoder_implementation_name = "unknown"; int input_frame_rate = 0; int encode_frame_rate = 0; int avg_encode_time_ms = 0; int encode_usage_percent = 0; + uint32_t frames_encoded = 0; + rtc::Optional qp_sum; + // Bitrate the encoder is currently configured to use due to bandwidth + // limitations. int target_media_bitrate_bps = 0; + // Bitrate the encoder is actually producing. int media_bitrate_bps = 0; + // Media bitrate this VideoSendStream is configured to prefer if there are + // no bandwidth limitations. + int preferred_media_bitrate_bps = 0; bool suspended = false; bool bw_limited_resolution = false; + bool cpu_limited_resolution = false; + // Total number of times resolution as been requested to be changed due to + // CPU adaptation. + int number_of_cpu_adapt_changes = 0; std::map substreams; }; struct Config { + public: Config() = delete; + Config(Config&&) = default; explicit Config(Transport* send_transport) : send_transport(send_transport) {} + Config& operator=(Config&&) = default; + Config& operator=(const Config&) = delete; + + // Mostly used by tests. Avoid creating copies if you can. + Config Copy() const { return Config(*this); } + std::string ToString() const; struct EncoderSettings { + EncoderSettings() = default; + EncoderSettings(std::string payload_name, + int payload_type, + VideoEncoder* encoder) + : payload_name(std::move(payload_name)), + payload_type(payload_type), + encoder(encoder) {} std::string ToString() const; std::string payload_name; @@ -112,8 +135,24 @@ class VideoSendStream { // See NackConfig for description. NackConfig nack; - // See FecConfig for description. - FecConfig fec; + // See UlpfecConfig for description. + UlpfecConfig ulpfec; + + struct Flexfec { + // Payload type of FlexFEC. Set to -1 to disable sending FlexFEC. + int payload_type = -1; + + // SSRC of FlexFEC stream. + uint32_t ssrc = 0; + + // Vector containing a single element, corresponding to the SSRC of the + // media stream being protected by this FlexFEC stream. + // The vector MUST have size 1. + // + // TODO(brandtr): Update comment above when we support + // multistream protection. + std::vector protected_media_ssrcs; + } flexfec; // Settings for RTP retransmission payload format, see RFC 4588 for // details. @@ -133,10 +172,6 @@ class VideoSendStream { // Transport for outgoing packets. Transport* send_transport = nullptr; - // Callback for overuse and normal usage based on the jitter of incoming - // captured frames. 'nullptr' disables the callback. - LoadObserver* overuse_callback = nullptr; - // Called for each I420 frame before encoding the frame. Can be used for // effects, snapshots etc. 'nullptr' disables the callback. rtc::VideoSinkInterface* pre_encode_callback = nullptr; @@ -147,10 +182,6 @@ class VideoSendStream { // than the measuring window, since the sample data will have been dropped. EncodedFrameObserver* post_encode_callback = nullptr; - // Renderer for local preview. The local renderer will be called even if - // sending hasn't started. 'nullptr' disables local rendering. - rtc::VideoSinkInterface* local_renderer = nullptr; - // Expected delay needed by the renderer, i.e. the frame will be delivered // this many milliseconds, if possible, earlier than expected render time. // Only valid if |local_renderer| is set. @@ -164,6 +195,14 @@ class VideoSendStream { // below the minimum configured bitrate. If this variable is false, the // stream may send at a rate higher than the estimated available bitrate. bool suspend_below_min_bitrate = false; + + // Enables periodic bandwidth probing in application-limited region. + bool periodic_alr_bandwidth_probing = false; + + private: + // Access to the copy constructor is private to force use of the Copy() + // method for those exceptional cases where we do use it. + Config(const Config&) = default; }; // Starts stream activity. @@ -173,17 +212,41 @@ class VideoSendStream { // When a stream is stopped, it can't receive, process or deliver packets. virtual void Stop() = 0; - // Gets interface used to insert captured frames. Valid as long as the - // VideoSendStream is valid. - virtual VideoCaptureInput* Input() = 0; + // Based on the spec in + // https://w3c.github.io/webrtc-pc/#idl-def-rtcdegradationpreference. + enum class DegradationPreference { + kMaintainResolution, + // TODO(perkj): Implement kMaintainFrameRate. kBalanced will drop frames + // if the encoder overshoots or the encoder can not encode fast enough. + kBalanced, + }; + virtual void SetSource( + rtc::VideoSourceInterface* source, + const DegradationPreference& degradation_preference) = 0; // Set which streams to send. Must have at least as many SSRCs as configured // in the config. Encoder settings are passed on to the encoder instance along // with the VideoStream settings. - virtual void ReconfigureVideoEncoder(const VideoEncoderConfig& config) = 0; + virtual void ReconfigureVideoEncoder(VideoEncoderConfig config) = 0; virtual Stats GetStats() = 0; + // Takes ownership of each file, is responsible for closing them later. + // Calling this method will close and finalize any current logs. + // Some codecs produce multiple streams (VP8 only at present), each of these + // streams will log to a separate file. kMaxSimulcastStreams in common_types.h + // gives the max number of such streams. If there is no file for a stream, or + // the file is rtc::kInvalidPlatformFileValue, frames from that stream will + // not be logged. + // If a frame to be written would make the log too large the write fails and + // the log is closed and finalized. A |byte_limit| of 0 means no limit. + virtual void EnableEncodedFrameRecording( + const std::vector& files, + size_t byte_limit) = 0; + inline void DisableEncodedFrameRecording() { + EnableEncodedFrameRecording(std::vector(), 0); + } + protected: virtual ~VideoSendStream() {} }; diff --git a/lib/libwebrtc-darwin-amd64-magic.a b/lib/libwebrtc-darwin-amd64-magic.a index 8dbd901..53f2fcd 100644 Binary files a/lib/libwebrtc-darwin-amd64-magic.a and b/lib/libwebrtc-darwin-amd64-magic.a differ diff --git a/lib/libwebrtc-linux-amd64-magic.a b/lib/libwebrtc-linux-amd64-magic.a index 7735919..23ccf49 100644 Binary files a/lib/libwebrtc-linux-amd64-magic.a and b/lib/libwebrtc-linux-amd64-magic.a differ diff --git a/lib/libwebrtc-linux-arm-magic.a b/lib/libwebrtc-linux-arm-magic.a new file mode 100644 index 0000000..42be7dd Binary files /dev/null and b/lib/libwebrtc-linux-arm-magic.a differ diff --git a/peerconnection.cc b/peerconnection.cc index bab63d5..275007a 100644 --- a/peerconnection.cc +++ b/peerconnection.cc @@ -10,9 +10,9 @@ #include #include "webrtc/api/test/fakeconstraints.h" -#include "webrtc/api/test/fakeaudiocapturemodule.h" +#include "webrtc/pc/test/fakeaudiocapturemodule.h" #include "webrtc/api/jsepsessiondescription.h" -#include "webrtc/api/webrtcsdp.h" +#include "webrtc/pc/webrtcsdp.h" #define SUCCESS 0 #define FAILURE -1 @@ -244,12 +244,12 @@ PeerConnectionInterface::RTCConfiguration *castConfig_( for (auto s : servers) { // cgo only allows C arrays, but webrtc expects std::vectors vector urls(s.urls, s.urls + s.numUrls); - c->servers.push_back({ - "", // TODO: Remove once webrtc deprecates the first uri field. - urls, - s.username, - s.credential - }); + PeerConnectionInterface::IceServer is {}; + is.uri =""; // TODO: Remove once webrtc deprecates the first uri field. + is.urls = urls; + is.username = s.username; + is.password = s.credential; + c->servers.push_back(is); } // Cast Go const "enums" to C++ Enums. @@ -417,12 +417,13 @@ int CGO_IceGatheringState(CGO_Peer cgoPeer) { int CGO_SetConfiguration(CGO_Peer cgoPeer, CGO_Configuration* cgoConfig) { Peer *peer = (Peer*)cgoPeer; auto cConfig = castConfig_(cgoConfig); - bool success = peer->pc_->SetConfiguration(*cConfig); + webrtc::RTCError *error = new webrtc::RTCError(); + bool success = peer->pc_->SetConfiguration(*cConfig, error); if (success) { peer->SetConfig(cConfig); return SUCCESS; } - return FAILURE; + return (int) error->type(); } // PeerConnection::CreateDataChannel diff --git a/peerconnection.go b/peerconnection.go index 6f5e6e0..9c91a4d 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -32,6 +32,7 @@ package webrtc /* #cgo CXXFLAGS: -std=c++0x #cgo LDFLAGS: -L${SRCDIR}/lib +#cgo linux,arm pkg-config: webrtc-linux-arm.pc #cgo linux,386 pkg-config: webrtc-linux-386.pc #cgo linux,amd64 pkg-config: webrtc-linux-amd64.pc #cgo darwin,amd64 pkg-config: webrtc-darwin-amd64.pc @@ -42,6 +43,7 @@ package webrtc import "C" import ( "errors" + "fmt" "unsafe" ) @@ -313,8 +315,9 @@ func (pc *PeerConnection) GetConfiguration() Configuration { func (pc *PeerConnection) SetConfiguration(config Configuration) error { cConfig := config._CGO() defer freeConfig(cConfig) - if 0 != C.CGO_SetConfiguration(pc.cgoPeer, cConfig) { - return errors.New("PeerConnection: could not set configuration.") + err := C.CGO_SetConfiguration(pc.cgoPeer, cConfig) + if err != 0 { + return errors.New(fmt.Sprintf("PeerConnection: could not set configuration. Error ID: %d", err)) } pc.config = config return nil diff --git a/peerconnection_test.go b/peerconnection_test.go index dcf47d0..b4c7b4e 100644 --- a/peerconnection_test.go +++ b/peerconnection_test.go @@ -55,7 +55,9 @@ func TestPeerConnection(t *testing.T) { config := NewConfiguration( OptionIceServer("stun:something.else"), OptionIceTransportPolicy(IceTransportPolicyRelay)) - pc.SetConfiguration(*config) + So(config.IceTransportPolicy, ShouldEqual, IceTransportPolicyRelay) + pc, err = NewPeerConnection(config) + So(err, ShouldBeNil) got := pc.GetConfiguration() So(got.IceTransportPolicy, ShouldEqual, IceTransportPolicyRelay) }) diff --git a/webrtc-linux-arm.pc b/webrtc-linux-arm.pc new file mode 100644 index 0000000..0f6ab92 --- /dev/null +++ b/webrtc-linux-arm.pc @@ -0,0 +1,17 @@ +pc=${pcfiledir} + +Name: webrtc +Description: webrtc +Version: 1 + +Cflags: \ + -I${pc}/include \ + -D_GLIBCXX_USE_CXX11_ABI=0 \ + -DPOSIX + +Libs: \ + -L${pc}/lib \ + -lwebrtc-linux-arm-magic \ + -ldl \ + -lX11 \ + -lrt diff --git a/webrtc_patches/build_at_webrtc_branch_heads_52.patch b/webrtc_patches/build_at_webrtc_branch_heads_52.patch deleted file mode 100644 index 81e08df..0000000 --- a/webrtc_patches/build_at_webrtc_branch_heads_52.patch +++ /dev/null @@ -1,35 +0,0 @@ -From dd503bd0c5696882d6ece760da1ef4865825e55c Mon Sep 17 00:00:00 2001 -From: Cant Stop The Signal -Date: Sun, 4 Dec 2016 16:01:43 -0800 -Subject: [PATCH] Add patches to get webrtc to build from webrtc - branch-heads/52 - -webrtc commit f33698296719f956497d2dbff81b5080864a8804 ---- - webrtc/api/api.gyp | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp -index 377ef8f70..794fdb99c 100644 ---- a/webrtc/api/api.gyp -+++ b/webrtc/api/api.gyp -@@ -129,6 +129,7 @@ - 'dependencies': [ - '<(webrtc_root)/media/media.gyp:rtc_media', - '<(webrtc_root)/pc/pc.gyp:rtc_pc', -+ '<(webrtc_root)/system_wrappers/system_wrappers.gyp:field_trial_default', - ], - 'sources': [ - 'audiotrack.cc', -@@ -199,6 +200,8 @@ - 'webrtcsession.h', - 'webrtcsessiondescriptionfactory.cc', - 'webrtcsessiondescriptionfactory.h', -+ 'test/fakeaudiocapturemodule.cc', -+ 'test/fakeaudiocapturemodule.h', - ], - # TODO(kjellander): Make the code compile without disabling these flags. - # See https://bugs.chromium.org/p/webrtc/issues/detail?id=3307 --- -2.11.0 -