Reland of Implemented the GetSources() in native code. (patchset #1 id:1 of https://codereview.webrtc.org/2809613002/ )
Reason for revert: Re-land, reverting did not fix bug. https://bugs.chromium.org/p/webrtc/issues/detail?id=7465 Original issue's description: > Revert of Implemented the GetSources() in native code. (patchset #11 id:510001 of https://codereview.webrtc.org/2770233003/ ) > > Reason for revert: > Suspected of WebRtcApprtcBrowserTest.MANUAL_WorksOnApprtc breakage, see > > https://bugs.chromium.org/p/webrtc/issues/detail?id=7465 > > Original issue's description: > > Added the GetSources() to the RtpReceiverInterface and implemented > > it for the AudioRtpReceiver. > > > > This method returns a vector of RtpSource(both CSRC source and SSRC > > source) which contains the ID of a source, the timestamp, the source > > type (SSRC or CSRC) and the audio level. > > > > The RtpSource objects are buffered and maintained by the > > RtpReceiver in webrtc/modules/rtp_rtcp/. When the method is called, > > the info of the contributing source will be pulled along the object > > chain: > > AudioRtpReceiver -> VoiceChannel -> WebRtcVoiceMediaChannel -> > > AudioReceiveStream -> voe::Channel -> RtpRtcp module > > > > Spec:https://w3c.github.io/webrtc-pc/archives/20151006/webrtc.html#widl-RTCRtpReceiver-getContributingSources-sequence-RTCRtpContributingSource > > > > BUG=chromium:703122 > > TBR=stefan@webrtc.org, danilchap@webrtc.org > > > > Review-Url: https://codereview.webrtc.org/2770233003 > > Cr-Commit-Position: refs/heads/master@{#17591} > > Committed:292084c376> > TBR=deadbeef@webrtc.org,solenberg@webrtc.org,hbos@webrtc.org,philipel@webrtc.org,stefan@webrtc.org,danilchap@webrtc.org,zhihuang@webrtc.org > # Not skipping CQ checks because original CL landed more than 1 days ago. > BUG=chromium:703122 > > Review-Url: https://codereview.webrtc.org/2809613002 > Cr-Commit-Position: refs/heads/master@{#17616} > Committed:fbcc5cb386TBR=deadbeef@webrtc.org,solenberg@webrtc.org,philipel@webrtc.org,stefan@webrtc.org,danilchap@webrtc.org,zhihuang@webrtc.org,olka@webrtc.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=chromium:703122 Review-Url: https://codereview.webrtc.org/2810623003 Cr-Commit-Position: refs/heads/master@{#17621}
This commit is contained in:
parent
b0f7e39fd4
commit
8d609f6b6d
@ -15,6 +15,7 @@
|
||||
#define WEBRTC_API_RTPRECEIVERINTERFACE_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/mediatypes.h"
|
||||
#include "webrtc/api/mediastreaminterface.h"
|
||||
@ -25,6 +26,41 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
enum class RtpSourceType {
|
||||
SSRC,
|
||||
CSRC,
|
||||
};
|
||||
|
||||
class RtpSource {
|
||||
public:
|
||||
RtpSource() = delete;
|
||||
RtpSource(int64_t timestamp_ms, uint32_t source_id, RtpSourceType source_type)
|
||||
: timestamp_ms_(timestamp_ms),
|
||||
source_id_(source_id),
|
||||
source_type_(source_type) {}
|
||||
|
||||
int64_t timestamp_ms() const { return timestamp_ms_; }
|
||||
void update_timestamp_ms(int64_t timestamp_ms) {
|
||||
RTC_DCHECK_LE(timestamp_ms_, timestamp_ms);
|
||||
timestamp_ms_ = timestamp_ms;
|
||||
}
|
||||
|
||||
// The identifier of the source can be the CSRC or the SSRC.
|
||||
uint32_t source_id() const { return source_id_; }
|
||||
|
||||
// The source can be either a contributing source or a synchronization source.
|
||||
RtpSourceType source_type() const { return source_type_; }
|
||||
|
||||
// This isn't implemented yet and will always return an empty Optional.
|
||||
// TODO(zhihuang): Implement this to return real audio level.
|
||||
rtc::Optional<int8_t> audio_level() const { return rtc::Optional<int8_t>(); }
|
||||
|
||||
private:
|
||||
int64_t timestamp_ms_;
|
||||
uint32_t source_id_;
|
||||
RtpSourceType source_type_;
|
||||
};
|
||||
|
||||
class RtpReceiverObserverInterface {
|
||||
public:
|
||||
// Note: Currently if there are multiple RtpReceivers of the same media type,
|
||||
@ -61,6 +97,13 @@ class RtpReceiverInterface : public rtc::RefCountInterface {
|
||||
// Must call SetObserver(nullptr) before the observer is destroyed.
|
||||
virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
|
||||
|
||||
// TODO(zhihuang): Remove the default implementation once the subclasses
|
||||
// implement this. Currently, the only relevant subclass is the
|
||||
// content::FakeRtpReceiver in Chromium.
|
||||
virtual std::vector<RtpSource> GetSources() const {
|
||||
return std::vector<RtpSource>();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~RtpReceiverInterface() {}
|
||||
};
|
||||
@ -76,7 +119,8 @@ BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
|
||||
PROXY_CONSTMETHOD0(RtpParameters, GetParameters);
|
||||
PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
|
||||
PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*);
|
||||
END_PROXY_MAP()
|
||||
PROXY_CONSTMETHOD0(std::vector<RtpSource>, GetSources);
|
||||
END_PROXY_MAP()
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define WEBRTC_API_TEST_MOCK_RTPRECEIVER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
@ -27,6 +28,7 @@ class MockRtpReceiver : public rtc::RefCountedObject<RtpReceiverInterface> {
|
||||
MOCK_CONST_METHOD0(GetParameters, RtpParameters());
|
||||
MOCK_METHOD1(SetParameters, bool(const RtpParameters&));
|
||||
MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*));
|
||||
MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -219,6 +219,11 @@ void AudioReceiveStream::SetGain(float gain) {
|
||||
channel_proxy_->SetChannelOutputVolumeScaling(gain);
|
||||
}
|
||||
|
||||
std::vector<RtpSource> AudioReceiveStream::GetSources() const {
|
||||
RTC_DCHECK_RUN_ON(&worker_thread_checker_);
|
||||
return channel_proxy_->GetSources();
|
||||
}
|
||||
|
||||
AudioMixer::Source::AudioFrameInfo AudioReceiveStream::GetAudioFrameWithInfo(
|
||||
int sample_rate_hz,
|
||||
AudioFrame* audio_frame) {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define WEBRTC_AUDIO_AUDIO_RECEIVE_STREAM_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/audio/audio_mixer.h"
|
||||
#include "webrtc/audio/audio_state.h"
|
||||
@ -49,6 +50,7 @@ class AudioReceiveStream final : public webrtc::AudioReceiveStream,
|
||||
int GetOutputLevel() const override;
|
||||
void SetSink(std::unique_ptr<AudioSinkInterface> sink) override;
|
||||
void SetGain(float gain) override;
|
||||
std::vector<webrtc::RtpSource> GetSources() const override;
|
||||
|
||||
// TODO(nisse): Intended to be part of an RtpPacketReceiver interface.
|
||||
void OnRtpPacket(const RtpPacketReceived& packet);
|
||||
|
||||
@ -23,6 +23,7 @@ rtc_source_set("call_interfaces") {
|
||||
deps = [
|
||||
"..:webrtc_common",
|
||||
"../api:audio_mixer_api",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:transport_api",
|
||||
"../api/audio_codecs:audio_codecs_api",
|
||||
"../base:rtc_base",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
#include "webrtc/api/audio_codecs/audio_decoder_factory.h"
|
||||
#include "webrtc/api/call/transport.h"
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/base/optional.h"
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/common_types.h"
|
||||
@ -133,6 +134,8 @@ class AudioReceiveStream {
|
||||
// is potentially forwarded to any attached AudioSinkInterface implementation.
|
||||
virtual void SetGain(float gain) = 0;
|
||||
|
||||
virtual std::vector<RtpSource> GetSources() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~AudioReceiveStream() {}
|
||||
};
|
||||
|
||||
@ -97,6 +97,9 @@ class FakeAudioReceiveStream final : public webrtc::AudioReceiveStream {
|
||||
int GetOutputLevel() const override { return 0; }
|
||||
void SetSink(std::unique_ptr<webrtc::AudioSinkInterface> sink) override;
|
||||
void SetGain(float gain) override;
|
||||
std::vector<webrtc::RtpSource> GetSources() const override {
|
||||
return std::vector<webrtc::RtpSource>();
|
||||
}
|
||||
|
||||
int id_ = -1;
|
||||
webrtc::AudioReceiveStream::Config config_;
|
||||
|
||||
@ -1581,6 +1581,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream {
|
||||
playout_ = playout;
|
||||
}
|
||||
|
||||
std::vector<webrtc::RtpSource> GetSources() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
RTC_DCHECK(stream_);
|
||||
return stream_->GetSources();
|
||||
}
|
||||
|
||||
private:
|
||||
void RecreateAudioReceiveStream() {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
@ -2600,6 +2606,15 @@ void WebRtcVoiceMediaChannel::SetRawAudioSink(
|
||||
it->second->SetRawAudioSink(std::move(sink));
|
||||
}
|
||||
|
||||
std::vector<webrtc::RtpSource> WebRtcVoiceMediaChannel::GetSources(
|
||||
uint32_t ssrc) const {
|
||||
auto it = recv_streams_.find(ssrc);
|
||||
RTC_DCHECK(it != recv_streams_.end())
|
||||
<< "Attempting to get contributing sources for SSRC:" << ssrc
|
||||
<< " which doesn't exist.";
|
||||
return it->second->GetSources();
|
||||
}
|
||||
|
||||
int WebRtcVoiceMediaChannel::GetReceiveChannelId(uint32_t ssrc) const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
const auto it = recv_streams_.find(ssrc);
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/base/buffer.h"
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/networkroute.h"
|
||||
@ -210,6 +211,8 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel,
|
||||
uint32_t ssrc,
|
||||
std::unique_ptr<webrtc::AudioSinkInterface> sink) override;
|
||||
|
||||
std::vector<webrtc::RtpSource> GetSources(uint32_t ssrc) const;
|
||||
|
||||
// implements Transport interface
|
||||
bool SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
|
||||
@ -167,6 +167,7 @@ rtc_static_library("rtp_rtcp") {
|
||||
|
||||
deps = [
|
||||
"../..:webrtc_common",
|
||||
"../../api:libjingle_peerconnection_api",
|
||||
"../../api:transport_api",
|
||||
"../../api/audio_codecs:audio_codecs_api",
|
||||
"../../base:gtest_prod",
|
||||
@ -274,6 +275,7 @@ if (rtc_include_tests) {
|
||||
"source/rtp_packet_history_unittest.cc",
|
||||
"source/rtp_packet_unittest.cc",
|
||||
"source/rtp_payload_registry_unittest.cc",
|
||||
"source/rtp_receiver_unittest.cc",
|
||||
"source/rtp_rtcp_impl_unittest.cc",
|
||||
"source/rtp_sender_unittest.cc",
|
||||
"source/rtp_utility_unittest.cc",
|
||||
|
||||
@ -11,6 +11,9 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RECEIVER_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_INCLUDE_RTP_RECEIVER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
@ -89,6 +92,8 @@ class RtpReceiver {
|
||||
|
||||
// Returns the current energy of the RTP stream received.
|
||||
virtual int32_t Energy(uint8_t array_of_energy[kRtpCsrcSize]) const = 0;
|
||||
|
||||
virtual std::vector<RtpSource> GetSources() const = 0;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -15,6 +15,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
||||
@ -25,6 +28,9 @@ namespace webrtc {
|
||||
|
||||
using RtpUtility::Payload;
|
||||
|
||||
// Only return the sources in the last 10 seconds.
|
||||
const int64_t kGetSourcesTimeoutMs = 10000;
|
||||
|
||||
RtpReceiver* RtpReceiver::CreateVideoReceiver(
|
||||
Clock* clock,
|
||||
RtpData* incoming_payload_callback,
|
||||
@ -53,11 +59,10 @@ RtpReceiver* RtpReceiver::CreateAudioReceiver(
|
||||
RTPReceiverStrategy::CreateAudioStrategy(incoming_payload_callback));
|
||||
}
|
||||
|
||||
RtpReceiverImpl::RtpReceiverImpl(
|
||||
Clock* clock,
|
||||
RtpFeedback* incoming_messages_callback,
|
||||
RTPPayloadRegistry* rtp_payload_registry,
|
||||
RTPReceiverStrategy* rtp_media_receiver)
|
||||
RtpReceiverImpl::RtpReceiverImpl(Clock* clock,
|
||||
RtpFeedback* incoming_messages_callback,
|
||||
RTPPayloadRegistry* rtp_payload_registry,
|
||||
RTPReceiverStrategy* rtp_media_receiver)
|
||||
: clock_(clock),
|
||||
rtp_payload_registry_(rtp_payload_registry),
|
||||
rtp_media_receiver_(rtp_media_receiver),
|
||||
@ -160,6 +165,8 @@ bool RtpReceiverImpl::IncomingRtpPacket(
|
||||
webrtc_rtp_header.header = rtp_header;
|
||||
CheckCSRC(webrtc_rtp_header);
|
||||
|
||||
UpdateSources();
|
||||
|
||||
size_t payload_data_length = payload_length - rtp_header.paddingLength;
|
||||
|
||||
bool is_first_packet_in_frame = false;
|
||||
@ -203,6 +210,45 @@ TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() {
|
||||
return rtp_media_receiver_->GetTelephoneEventHandler();
|
||||
}
|
||||
|
||||
std::vector<RtpSource> RtpReceiverImpl::GetSources() const {
|
||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
std::vector<RtpSource> sources;
|
||||
|
||||
{
|
||||
rtc::CritScope lock(&critical_section_rtp_receiver_);
|
||||
|
||||
RTC_DCHECK(std::is_sorted(ssrc_sources_.begin(), ssrc_sources_.end(),
|
||||
[](const RtpSource& lhs, const RtpSource& rhs) {
|
||||
return lhs.timestamp_ms() < rhs.timestamp_ms();
|
||||
}));
|
||||
RTC_DCHECK(std::is_sorted(csrc_sources_.begin(), csrc_sources_.end(),
|
||||
[](const RtpSource& lhs, const RtpSource& rhs) {
|
||||
return lhs.timestamp_ms() < rhs.timestamp_ms();
|
||||
}));
|
||||
|
||||
std::set<uint32_t> selected_ssrcs;
|
||||
for (auto rit = ssrc_sources_.rbegin(); rit != ssrc_sources_.rend();
|
||||
++rit) {
|
||||
if ((now_ms - rit->timestamp_ms()) > kGetSourcesTimeoutMs) {
|
||||
break;
|
||||
}
|
||||
if (selected_ssrcs.insert(rit->source_id()).second) {
|
||||
sources.push_back(*rit);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto rit = csrc_sources_.rbegin(); rit != csrc_sources_.rend();
|
||||
++rit) {
|
||||
if ((now_ms - rit->timestamp_ms()) > kGetSourcesTimeoutMs) {
|
||||
break;
|
||||
}
|
||||
sources.push_back(*rit);
|
||||
}
|
||||
} // End critsect.
|
||||
|
||||
return sources;
|
||||
}
|
||||
|
||||
bool RtpReceiverImpl::Timestamp(uint32_t* timestamp) const {
|
||||
rtc::CritScope lock(&critical_section_rtp_receiver_);
|
||||
if (!HaveReceivedFrame())
|
||||
@ -461,4 +507,54 @@ void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) {
|
||||
}
|
||||
}
|
||||
|
||||
void RtpReceiverImpl::UpdateSources() {
|
||||
rtc::CritScope lock(&critical_section_rtp_receiver_);
|
||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
|
||||
for (size_t i = 0; i < num_csrcs_; ++i) {
|
||||
auto map_it = iterator_by_csrc_.find(current_remote_csrc_[i]);
|
||||
if (map_it == iterator_by_csrc_.end()) {
|
||||
// If it is a new CSRC, append a new object to the end of the list.
|
||||
csrc_sources_.emplace_back(now_ms, current_remote_csrc_[i],
|
||||
RtpSourceType::CSRC);
|
||||
} else {
|
||||
// If it is an existing CSRC, move the object to the end of the list.
|
||||
map_it->second->update_timestamp_ms(now_ms);
|
||||
csrc_sources_.splice(csrc_sources_.end(), csrc_sources_, map_it->second);
|
||||
}
|
||||
// Update the unordered_map.
|
||||
iterator_by_csrc_[current_remote_csrc_[i]] = std::prev(csrc_sources_.end());
|
||||
}
|
||||
|
||||
// If this is the first packet or the SSRC is changed, insert a new
|
||||
// contributing source that uses the SSRC.
|
||||
if (ssrc_sources_.empty() || ssrc_sources_.rbegin()->source_id() != ssrc_) {
|
||||
ssrc_sources_.emplace_back(now_ms, ssrc_, RtpSourceType::SSRC);
|
||||
} else {
|
||||
ssrc_sources_.rbegin()->update_timestamp_ms(now_ms);
|
||||
}
|
||||
|
||||
RemoveOutdatedSources(now_ms);
|
||||
}
|
||||
|
||||
void RtpReceiverImpl::RemoveOutdatedSources(int64_t now_ms) {
|
||||
std::list<RtpSource>::iterator it;
|
||||
for (it = csrc_sources_.begin(); it != csrc_sources_.end(); ++it) {
|
||||
if ((now_ms - it->timestamp_ms()) <= kGetSourcesTimeoutMs) {
|
||||
break;
|
||||
}
|
||||
iterator_by_csrc_.erase(it->source_id());
|
||||
}
|
||||
csrc_sources_.erase(csrc_sources_.begin(), it);
|
||||
|
||||
std::vector<RtpSource>::iterator vec_it;
|
||||
for (vec_it = ssrc_sources_.begin(); vec_it != ssrc_sources_.end();
|
||||
++vec_it) {
|
||||
if ((now_ms - vec_it->timestamp_ms()) <= kGetSourcesTimeoutMs) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ssrc_sources_.erase(ssrc_sources_.begin(), vec_it);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -11,7 +11,10 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
|
||||
@ -56,6 +59,16 @@ class RtpReceiverImpl : public RtpReceiver {
|
||||
|
||||
TelephoneEventHandler* GetTelephoneEventHandler() override;
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
|
||||
const std::vector<RtpSource>& ssrc_sources_for_testing() const {
|
||||
return ssrc_sources_;
|
||||
}
|
||||
|
||||
const std::list<RtpSource>& csrc_sources_for_testing() const {
|
||||
return csrc_sources_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool HaveReceivedFrame() const;
|
||||
|
||||
@ -66,6 +79,9 @@ class RtpReceiverImpl : public RtpReceiver {
|
||||
bool* is_red,
|
||||
PayloadUnion* payload);
|
||||
|
||||
void UpdateSources();
|
||||
void RemoveOutdatedSources(int64_t now_ms);
|
||||
|
||||
Clock* clock_;
|
||||
RTPPayloadRegistry* rtp_payload_registry_;
|
||||
std::unique_ptr<RTPReceiverStrategy> rtp_media_receiver_;
|
||||
@ -84,6 +100,12 @@ class RtpReceiverImpl : public RtpReceiver {
|
||||
uint32_t last_received_timestamp_;
|
||||
int64_t last_received_frame_time_ms_;
|
||||
uint16_t last_received_sequence_number_;
|
||||
|
||||
std::unordered_map<uint32_t, std::list<RtpSource>::iterator>
|
||||
iterator_by_csrc_;
|
||||
// The RtpSource objects are sorted chronologically.
|
||||
std::list<RtpSource> csrc_sources_;
|
||||
std::vector<RtpSource> ssrc_sources_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_
|
||||
|
||||
260
webrtc/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
Normal file
260
webrtc/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
const uint32_t kTestRate = 64000u;
|
||||
const uint8_t kTestPayload[] = {'t', 'e', 's', 't'};
|
||||
const uint8_t kPcmuPayloadType = 96;
|
||||
const int64_t kGetSourcesTimeoutMs = 10000;
|
||||
const int kSourceListsSize = 20;
|
||||
|
||||
class RtpReceiverTest : public ::testing::Test {
|
||||
protected:
|
||||
RtpReceiverTest()
|
||||
: fake_clock_(123456),
|
||||
rtp_receiver_(
|
||||
RtpReceiver::CreateAudioReceiver(&fake_clock_,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&rtp_payload_registry_)) {
|
||||
CodecInst voice_codec = {};
|
||||
voice_codec.pltype = kPcmuPayloadType;
|
||||
voice_codec.plfreq = 8000;
|
||||
voice_codec.rate = kTestRate;
|
||||
memcpy(voice_codec.plname, "PCMU", 5);
|
||||
rtp_receiver_->RegisterReceivePayload(voice_codec);
|
||||
}
|
||||
~RtpReceiverTest() {}
|
||||
|
||||
bool FindSourceByIdAndType(const std::vector<RtpSource>& sources,
|
||||
uint32_t source_id,
|
||||
RtpSourceType type,
|
||||
RtpSource* source) {
|
||||
for (size_t i = 0; i < sources.size(); ++i) {
|
||||
if (sources[i].source_id() == source_id &&
|
||||
sources[i].source_type() == type) {
|
||||
(*source) = sources[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SimulatedClock fake_clock_;
|
||||
RTPPayloadRegistry rtp_payload_registry_;
|
||||
std::unique_ptr<RtpReceiver> rtp_receiver_;
|
||||
};
|
||||
|
||||
TEST_F(RtpReceiverTest, GetSources) {
|
||||
RTPHeader header;
|
||||
header.payloadType = kPcmuPayloadType;
|
||||
header.ssrc = 1;
|
||||
header.timestamp = fake_clock_.TimeInMilliseconds();
|
||||
header.numCSRCs = 2;
|
||||
header.arrOfCSRCs[0] = 111;
|
||||
header.arrOfCSRCs[1] = 222;
|
||||
PayloadUnion payload_specific = {AudioPayload()};
|
||||
bool in_order = false;
|
||||
RtpSource source(0, 0, RtpSourceType::SSRC);
|
||||
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
auto sources = rtp_receiver_->GetSources();
|
||||
// One SSRC source and two CSRC sources.
|
||||
ASSERT_EQ(3u, sources.size());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
|
||||
// Advance the fake clock and the method is expected to return the
|
||||
// contributing source object with same source id and updated timestamp.
|
||||
fake_clock_.AdvanceTimeMilliseconds(1);
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(3u, sources.size());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(), source.timestamp_ms());
|
||||
|
||||
// Test the edge case that the sources are still there just before the
|
||||
// timeout.
|
||||
int64_t prev_timestamp = fake_clock_.TimeInMilliseconds();
|
||||
fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs);
|
||||
sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(3u, sources.size());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(prev_timestamp, source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 222u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(prev_timestamp, source.timestamp_ms());
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, 111u, RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(prev_timestamp, source.timestamp_ms());
|
||||
|
||||
// Time out.
|
||||
fake_clock_.AdvanceTimeMilliseconds(1);
|
||||
sources = rtp_receiver_->GetSources();
|
||||
// All the sources should be out of date.
|
||||
ASSERT_EQ(0u, sources.size());
|
||||
}
|
||||
|
||||
// Test the case that the SSRC is changed.
|
||||
TEST_F(RtpReceiverTest, GetSourcesChangeSSRC) {
|
||||
int64_t prev_time = -1;
|
||||
int64_t cur_time = fake_clock_.TimeInMilliseconds();
|
||||
RTPHeader header;
|
||||
header.payloadType = kPcmuPayloadType;
|
||||
header.ssrc = 1;
|
||||
header.timestamp = cur_time;
|
||||
PayloadUnion payload_specific = {AudioPayload()};
|
||||
bool in_order = false;
|
||||
RtpSource source(0, 0, RtpSourceType::SSRC);
|
||||
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
auto sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(1u, sources.size());
|
||||
EXPECT_EQ(1u, sources[0].source_id());
|
||||
EXPECT_EQ(cur_time, sources[0].timestamp_ms());
|
||||
|
||||
// The SSRC is changed and the old SSRC is expected to be returned.
|
||||
fake_clock_.AdvanceTimeMilliseconds(100);
|
||||
prev_time = cur_time;
|
||||
cur_time = fake_clock_.TimeInMilliseconds();
|
||||
header.ssrc = 2;
|
||||
header.timestamp = cur_time;
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(2u, sources.size());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 2u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(cur_time, source.timestamp_ms());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(prev_time, source.timestamp_ms());
|
||||
|
||||
// The SSRC is changed again and happen to be changed back to 1. No
|
||||
// duplication is expected.
|
||||
fake_clock_.AdvanceTimeMilliseconds(100);
|
||||
header.ssrc = 1;
|
||||
header.timestamp = cur_time;
|
||||
prev_time = cur_time;
|
||||
cur_time = fake_clock_.TimeInMilliseconds();
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(2u, sources.size());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 1u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(cur_time, source.timestamp_ms());
|
||||
ASSERT_TRUE(FindSourceByIdAndType(sources, 2u, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(prev_time, source.timestamp_ms());
|
||||
|
||||
// Old SSRC source timeout.
|
||||
fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs);
|
||||
cur_time = fake_clock_.TimeInMilliseconds();
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
sources = rtp_receiver_->GetSources();
|
||||
ASSERT_EQ(1u, sources.size());
|
||||
EXPECT_EQ(1u, sources[0].source_id());
|
||||
EXPECT_EQ(cur_time, sources[0].timestamp_ms());
|
||||
EXPECT_EQ(RtpSourceType::SSRC, sources[0].source_type());
|
||||
}
|
||||
|
||||
TEST_F(RtpReceiverTest, GetSourcesRemoveOutdatedSource) {
|
||||
int64_t timestamp = fake_clock_.TimeInMilliseconds();
|
||||
bool in_order = false;
|
||||
RTPHeader header;
|
||||
header.payloadType = kPcmuPayloadType;
|
||||
header.timestamp = timestamp;
|
||||
PayloadUnion payload_specific = {AudioPayload()};
|
||||
header.numCSRCs = 1;
|
||||
RtpSource source(0, 0, RtpSourceType::SSRC);
|
||||
|
||||
for (size_t i = 0; i < kSourceListsSize; ++i) {
|
||||
header.ssrc = i;
|
||||
header.arrOfCSRCs[0] = (i + 1);
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
}
|
||||
|
||||
auto sources = rtp_receiver_->GetSources();
|
||||
// Expect |kSourceListsSize| SSRC sources and |kSourceListsSize| CSRC sources.
|
||||
ASSERT_TRUE(sources.size() == 2 * kSourceListsSize);
|
||||
for (size_t i = 0; i < kSourceListsSize; ++i) {
|
||||
// The SSRC source IDs are expected to be 19, 18, 17 ... 0
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, i, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(timestamp, source.timestamp_ms());
|
||||
|
||||
// The CSRC source IDs are expected to be 20, 19, 18 ... 1
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, (i + 1), RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(timestamp, source.timestamp_ms());
|
||||
}
|
||||
|
||||
fake_clock_.AdvanceTimeMilliseconds(kGetSourcesTimeoutMs);
|
||||
for (size_t i = 0; i < kSourceListsSize; ++i) {
|
||||
// The SSRC source IDs are expected to be 19, 18, 17 ... 0
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, i, RtpSourceType::SSRC, &source));
|
||||
EXPECT_EQ(timestamp, source.timestamp_ms());
|
||||
|
||||
// The CSRC source IDs are expected to be 20, 19, 18 ... 1
|
||||
ASSERT_TRUE(
|
||||
FindSourceByIdAndType(sources, (i + 1), RtpSourceType::CSRC, &source));
|
||||
EXPECT_EQ(timestamp, source.timestamp_ms());
|
||||
}
|
||||
|
||||
// Timeout. All the existing objects are out of date and are expected to be
|
||||
// removed.
|
||||
fake_clock_.AdvanceTimeMilliseconds(1);
|
||||
header.ssrc = 111;
|
||||
header.arrOfCSRCs[0] = 222;
|
||||
EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(header, kTestPayload, 4,
|
||||
payload_specific, in_order));
|
||||
auto rtp_receiver_impl = static_cast<RtpReceiverImpl*>(rtp_receiver_.get());
|
||||
auto ssrc_sources = rtp_receiver_impl->ssrc_sources_for_testing();
|
||||
ASSERT_EQ(1u, ssrc_sources.size());
|
||||
EXPECT_EQ(111u, ssrc_sources.begin()->source_id());
|
||||
EXPECT_EQ(RtpSourceType::SSRC, ssrc_sources.begin()->source_type());
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(),
|
||||
ssrc_sources.begin()->timestamp_ms());
|
||||
|
||||
auto csrc_sources = rtp_receiver_impl->csrc_sources_for_testing();
|
||||
ASSERT_EQ(1u, csrc_sources.size());
|
||||
EXPECT_EQ(222u, csrc_sources.begin()->source_id());
|
||||
EXPECT_EQ(RtpSourceType::CSRC, csrc_sources.begin()->source_type());
|
||||
EXPECT_EQ(fake_clock_.TimeInMilliseconds(),
|
||||
csrc_sources.begin()->timestamp_ms());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -23,6 +23,7 @@
|
||||
#include "webrtc/base/trace_event.h"
|
||||
#include "webrtc/media/base/mediaconstants.h"
|
||||
#include "webrtc/media/base/rtputils.h"
|
||||
#include "webrtc/media/engine/webrtcvoiceengine.h"
|
||||
#include "webrtc/p2p/base/packettransportinternal.h"
|
||||
#include "webrtc/pc/channelmanager.h"
|
||||
|
||||
@ -1676,6 +1677,13 @@ bool VoiceChannel::GetStats(VoiceMediaInfo* stats) {
|
||||
media_channel(), stats));
|
||||
}
|
||||
|
||||
std::vector<webrtc::RtpSource> VoiceChannel::GetSources(uint32_t ssrc) const {
|
||||
return worker_thread()->Invoke<std::vector<webrtc::RtpSource>>(
|
||||
RTC_FROM_HERE,
|
||||
Bind(&WebRtcVoiceMediaChannel::GetSources,
|
||||
static_cast<WebRtcVoiceMediaChannel*>(media_channel()), ssrc));
|
||||
}
|
||||
|
||||
void VoiceChannel::StartMediaMonitor(int cms) {
|
||||
media_monitor_.reset(new VoiceMediaMonitor(media_channel(), worker_thread(),
|
||||
rtc::Thread::Current()));
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "webrtc/api/call/audio_sink.h"
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/base/asyncinvoker.h"
|
||||
#include "webrtc/base/asyncudpsocket.h"
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
@ -488,6 +489,8 @@ class VoiceChannel : public BaseChannel {
|
||||
// Get statistics about the current media session.
|
||||
bool GetStats(VoiceMediaInfo* stats);
|
||||
|
||||
std::vector<webrtc::RtpSource> GetSources(uint32_t ssrc) const;
|
||||
|
||||
// Monitoring functions
|
||||
sigslot::signal2<VoiceChannel*, const std::vector<ConnectionInfo>&>
|
||||
SignalConnectionMonitor;
|
||||
@ -529,7 +532,6 @@ class VoiceChannel : public BaseChannel {
|
||||
void HandleEarlyMediaTimeout();
|
||||
bool InsertDtmf_w(uint32_t ssrc, int event, int duration);
|
||||
bool SetOutputVolume_w(uint32_t ssrc, double volume);
|
||||
bool GetStats_w(VoiceMediaInfo* stats);
|
||||
|
||||
void OnMessage(rtc::Message* pmsg) override;
|
||||
void GetSrtpCryptoSuites_n(std::vector<int>* crypto_suites) const override;
|
||||
|
||||
@ -2755,6 +2755,24 @@ TEST_F(PeerConnectionIntegrationTest, CodecNamesAreCaseInsensitive) {
|
||||
kMaxWaitForFramesMs);
|
||||
}
|
||||
|
||||
TEST_F(PeerConnectionIntegrationTest, GetSources) {
|
||||
ASSERT_TRUE(CreatePeerConnectionWrappers());
|
||||
ConnectFakeSignaling();
|
||||
caller()->AddAudioOnlyMediaStream();
|
||||
caller()->CreateAndSetAndSignalOffer();
|
||||
ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
|
||||
// Wait for one audio frame received by callee.
|
||||
ExpectNewFramesReceivedWithWait(0, 0, 1, 0, kMaxWaitForFramesMs);
|
||||
ASSERT_GT(callee()->pc()->GetReceivers().size(), 0u);
|
||||
auto receiver = callee()->pc()->GetReceivers()[0];
|
||||
ASSERT_EQ(receiver->media_type(), cricket::MEDIA_TYPE_AUDIO);
|
||||
|
||||
auto contributing_sources = receiver->GetSources();
|
||||
ASSERT_GT(receiver->GetParameters().encodings.size(), 0u);
|
||||
EXPECT_EQ(receiver->GetParameters().encodings[0].ssrc,
|
||||
contributing_sources[0].source_id());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // if !defined(THREAD_SANITIZER)
|
||||
|
||||
@ -97,6 +97,10 @@ void AudioRtpReceiver::Stop() {
|
||||
stopped_ = true;
|
||||
}
|
||||
|
||||
std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
|
||||
return channel_->GetSources(ssrc_);
|
||||
}
|
||||
|
||||
void AudioRtpReceiver::Reconfigure() {
|
||||
RTC_DCHECK(!stopped_);
|
||||
if (!channel_) {
|
||||
|
||||
@ -88,6 +88,8 @@ class AudioRtpReceiver : public ObserverInterface,
|
||||
// Should call SetChannel(nullptr) before |channel| is destroyed.
|
||||
void SetChannel(cricket::VoiceChannel* channel);
|
||||
|
||||
std::vector<RtpSource> GetSources() const override;
|
||||
|
||||
private:
|
||||
void Reconfigure();
|
||||
void OnFirstPacketReceived(cricket::BaseChannel* channel);
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/voice_engine/channel_proxy.h"
|
||||
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
@ -99,6 +99,7 @@ class MockVoEChannelProxy : public voe::ChannelProxy {
|
||||
MOCK_METHOD1(OnTwccBasedUplinkPacketLossRate, void(float packet_loss_rate));
|
||||
MOCK_METHOD1(OnRecoverableUplinkPacketLossRate,
|
||||
void(float recoverable_packet_loss_rate));
|
||||
MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
using DegradationPreference = VideoSendStream::DegradationPreference;
|
||||
|
||||
// Time interval for logging frame counts.
|
||||
const int64_t kFrameLogIntervalMs = 60000;
|
||||
@ -152,11 +151,13 @@ class ViEEncoder::VideoSourceProxy {
|
||||
public:
|
||||
explicit VideoSourceProxy(ViEEncoder* vie_encoder)
|
||||
: vie_encoder_(vie_encoder),
|
||||
degradation_preference_(DegradationPreference::kDegradationDisabled),
|
||||
degradation_preference_(
|
||||
VideoSendStream::DegradationPreference::kDegradationDisabled),
|
||||
source_(nullptr) {}
|
||||
|
||||
void SetSource(rtc::VideoSourceInterface<VideoFrame>* source,
|
||||
const DegradationPreference& degradation_preference) {
|
||||
void SetSource(
|
||||
rtc::VideoSourceInterface<VideoFrame>* source,
|
||||
const VideoSendStream::DegradationPreference& degradation_preference) {
|
||||
// Called on libjingle's worker thread.
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&main_checker_);
|
||||
rtc::VideoSourceInterface<VideoFrame>* old_source = nullptr;
|
||||
@ -192,16 +193,16 @@ class ViEEncoder::VideoSourceProxy {
|
||||
// Clear any constraints from the current sink wants that don't apply to
|
||||
// the used degradation_preference.
|
||||
switch (degradation_preference_) {
|
||||
case DegradationPreference::kBalanced:
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case DegradationPreference::kMaintainFramerate:
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
wants.max_framerate_fps = std::numeric_limits<int>::max();
|
||||
break;
|
||||
case DegradationPreference::kMaintainResolution:
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
wants.max_pixel_count = std::numeric_limits<int>::max();
|
||||
wants.target_pixel_count.reset();
|
||||
break;
|
||||
case DegradationPreference::kDegradationDisabled:
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
wants.max_pixel_count = std::numeric_limits<int>::max();
|
||||
wants.target_pixel_count.reset();
|
||||
wants.max_framerate_fps = std::numeric_limits<int>::max();
|
||||
@ -298,22 +299,24 @@ class ViEEncoder::VideoSourceProxy {
|
||||
bool IsResolutionScalingEnabledLocked() const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
|
||||
return degradation_preference_ ==
|
||||
DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ == DegradationPreference::kBalanced;
|
||||
VideoSendStream::DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ ==
|
||||
VideoSendStream::DegradationPreference::kBalanced;
|
||||
}
|
||||
|
||||
bool IsFramerateScalingEnabledLocked() const
|
||||
EXCLUSIVE_LOCKS_REQUIRED(&crit_) {
|
||||
// TODO(sprang): Also accept kBalanced here?
|
||||
return degradation_preference_ ==
|
||||
DegradationPreference::kMaintainResolution;
|
||||
VideoSendStream::DegradationPreference::kMaintainResolution;
|
||||
}
|
||||
|
||||
rtc::CriticalSection crit_;
|
||||
rtc::SequencedTaskChecker main_checker_;
|
||||
ViEEncoder* const vie_encoder_;
|
||||
rtc::VideoSinkWants sink_wants_ GUARDED_BY(&crit_);
|
||||
DegradationPreference degradation_preference_ GUARDED_BY(&crit_);
|
||||
VideoSendStream::DegradationPreference degradation_preference_
|
||||
GUARDED_BY(&crit_);
|
||||
rtc::VideoSourceInterface<VideoFrame>* source_ GUARDED_BY(&crit_);
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy);
|
||||
@ -347,7 +350,8 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
||||
last_observed_bitrate_bps_(0),
|
||||
encoder_paused_and_dropped_frame_(false),
|
||||
clock_(Clock::GetRealTimeClock()),
|
||||
degradation_preference_(DegradationPreference::kDegradationDisabled),
|
||||
degradation_preference_(
|
||||
VideoSendStream::DegradationPreference::kDegradationDisabled),
|
||||
last_captured_timestamp_(0),
|
||||
delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
|
||||
clock_->TimeInMilliseconds()),
|
||||
@ -373,7 +377,7 @@ ViEEncoder::~ViEEncoder() {
|
||||
|
||||
void ViEEncoder::Stop() {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
source_proxy_->SetSource(nullptr, DegradationPreference());
|
||||
source_proxy_->SetSource(nullptr, VideoSendStream::DegradationPreference());
|
||||
encoder_queue_.PostTask([this] {
|
||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
overuse_detector_.StopCheckForOveruse();
|
||||
@ -413,7 +417,8 @@ void ViEEncoder::SetBitrateObserver(
|
||||
|
||||
void ViEEncoder::SetSource(
|
||||
rtc::VideoSourceInterface<VideoFrame>* source,
|
||||
const VideoSendStream::DegradationPreference& degradation_preference) {
|
||||
const VideoSendStream::VideoSendStream::DegradationPreference&
|
||||
degradation_preference) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
source_proxy_->SetSource(source, degradation_preference);
|
||||
encoder_queue_.PostTask([this, degradation_preference] {
|
||||
@ -425,8 +430,10 @@ void ViEEncoder::SetSource(
|
||||
}
|
||||
degradation_preference_ = degradation_preference;
|
||||
bool allow_scaling =
|
||||
degradation_preference_ == DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ == DegradationPreference::kBalanced;
|
||||
degradation_preference_ ==
|
||||
VideoSendStream::DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ ==
|
||||
VideoSendStream::DegradationPreference::kBalanced;
|
||||
initial_rampup_ = allow_scaling ? 0 : kMaxInitialFramedrop;
|
||||
ConfigureQualityScaler();
|
||||
});
|
||||
@ -530,8 +537,10 @@ void ViEEncoder::ConfigureQualityScaler() {
|
||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
const auto scaling_settings = settings_.encoder->GetScalingSettings();
|
||||
const bool degradation_preference_allows_scaling =
|
||||
degradation_preference_ == DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ == DegradationPreference::kBalanced;
|
||||
degradation_preference_ ==
|
||||
VideoSendStream::DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference_ ==
|
||||
VideoSendStream::DegradationPreference::kBalanced;
|
||||
const bool quality_scaling_allowed =
|
||||
degradation_preference_allows_scaling && scaling_settings.enabled;
|
||||
|
||||
@ -794,9 +803,9 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
|
||||
int max_downgrades = 0;
|
||||
switch (degradation_preference_) {
|
||||
case DegradationPreference::kBalanced:
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case DegradationPreference::kMaintainFramerate:
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
max_downgrades = kMaxCpuResolutionDowngrades;
|
||||
if (downgrade_requested &&
|
||||
adaptation_request.input_pixel_count_ >=
|
||||
@ -806,7 +815,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case DegradationPreference::kMaintainResolution:
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
max_downgrades = kMaxCpuFramerateDowngrades;
|
||||
if (adaptation_request.framerate_fps_ <= 0 ||
|
||||
(downgrade_requested &&
|
||||
@ -820,7 +829,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case DegradationPreference::kDegradationDisabled:
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -843,19 +852,19 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
IncrementScaleCounter(reason, 1);
|
||||
|
||||
switch (degradation_preference_) {
|
||||
case DegradationPreference::kBalanced:
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case DegradationPreference::kMaintainFramerate:
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
source_proxy_->RequestResolutionLowerThan(
|
||||
adaptation_request.input_pixel_count_);
|
||||
LOG(LS_INFO) << "Scaling down resolution.";
|
||||
break;
|
||||
case DegradationPreference::kMaintainResolution:
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
source_proxy_->RequestFramerateLowerThan(
|
||||
adaptation_request.framerate_fps_);
|
||||
LOG(LS_INFO) << "Scaling down framerate.";
|
||||
break;
|
||||
case DegradationPreference::kDegradationDisabled:
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
@ -880,9 +889,9 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
last_adaptation_request_ &&
|
||||
last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp;
|
||||
switch (degradation_preference_) {
|
||||
case DegradationPreference::kBalanced:
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case DegradationPreference::kMaintainFramerate:
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
if (adapt_up_requested &&
|
||||
adaptation_request.input_pixel_count_ <=
|
||||
last_adaptation_request_->input_pixel_count_) {
|
||||
@ -891,11 +900,11 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case DegradationPreference::kMaintainResolution:
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
// TODO(sprang): Don't request higher framerate if we are already at
|
||||
// max requested fps?
|
||||
break;
|
||||
case DegradationPreference::kDegradationDisabled:
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
return;
|
||||
}
|
||||
|
||||
@ -921,9 +930,9 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
const int scale_sum = std::accumulate(current_scale_counters.begin(),
|
||||
current_scale_counters.end(), 0);
|
||||
switch (degradation_preference_) {
|
||||
case DegradationPreference::kBalanced:
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case DegradationPreference::kMaintainFramerate:
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
if (scale_sum == 0) {
|
||||
LOG(LS_INFO) << "Removing resolution down-scaling setting.";
|
||||
source_proxy_->RequestHigherResolutionThan(
|
||||
@ -934,7 +943,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
LOG(LS_INFO) << "Scaling up resolution.";
|
||||
}
|
||||
break;
|
||||
case DegradationPreference::kMaintainResolution:
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
if (scale_sum == 0) {
|
||||
LOG(LS_INFO) << "Removing framerate down-scaling setting.";
|
||||
source_proxy_->RequestHigherFramerateThan(
|
||||
@ -945,7 +954,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
LOG(LS_INFO) << "Scaling up framerate.";
|
||||
}
|
||||
break;
|
||||
case DegradationPreference::kDegradationDisabled:
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
RTC_NOTREACHED();
|
||||
}
|
||||
|
||||
|
||||
@ -134,6 +134,7 @@ rtc_static_library("voice_engine") {
|
||||
"..:webrtc_common",
|
||||
"../api:audio_mixer_api",
|
||||
"../api:call_api",
|
||||
"../api:libjingle_peerconnection_api",
|
||||
"../api:transport_api",
|
||||
"../api/audio_codecs:audio_codecs_api",
|
||||
"../api/audio_codecs:builtin_audio_decoder_factory",
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "webrtc/modules/audio_processing/rms_level.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||
#include "webrtc/voice_engine/audio_level.h"
|
||||
#include "webrtc/voice_engine/file_player.h"
|
||||
@ -53,7 +54,6 @@ class ReceiveStatistics;
|
||||
class RemoteNtpTimeEstimator;
|
||||
class RtcEventLog;
|
||||
class RTPPayloadRegistry;
|
||||
class RtpReceiver;
|
||||
class RTPReceiverAudio;
|
||||
class RtpPacketReceived;
|
||||
class RtpRtcp;
|
||||
@ -403,6 +403,10 @@ class Channel
|
||||
|
||||
void OnRecoverableUplinkPacketLossRate(float recoverable_packet_loss_rate);
|
||||
|
||||
std::vector<RtpSource> GetSources() const {
|
||||
return rtp_receiver_->GetSources();
|
||||
}
|
||||
|
||||
private:
|
||||
class ProcessAndEncodeAudioTask;
|
||||
|
||||
|
||||
@ -402,6 +402,11 @@ void ChannelProxy::RegisterLegacyReceiveCodecs() {
|
||||
channel()->RegisterLegacyReceiveCodecs();
|
||||
}
|
||||
|
||||
std::vector<RtpSource> ChannelProxy::GetSources() const {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
return channel()->GetSources();
|
||||
}
|
||||
|
||||
Channel* ChannelProxy::channel() const {
|
||||
RTC_DCHECK(channel_owner_.channel());
|
||||
return channel_owner_.channel();
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define WEBRTC_VOICE_ENGINE_CHANNEL_PROXY_H_
|
||||
|
||||
#include "webrtc/api/audio/audio_mixer.h"
|
||||
#include "webrtc/api/rtpreceiverinterface.h"
|
||||
#include "webrtc/base/constructormagic.h"
|
||||
#include "webrtc/base/race_checker.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
@ -125,6 +126,7 @@ class ChannelProxy {
|
||||
virtual void OnRecoverableUplinkPacketLossRate(
|
||||
float recoverable_packet_loss_rate);
|
||||
virtual void RegisterLegacyReceiveCodecs();
|
||||
virtual std::vector<webrtc::RtpSource> GetSources() const;
|
||||
|
||||
private:
|
||||
Channel* channel() const;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user