Removed SSRC knowledge from ViEEncoder.
SSRC knowledge is contained withing VideoSendStream. That also means that debug recording is moved to VideoSendStream. I think that make sence since that allows debug recording with external encoder implementations one day. BUG=webrtc:5687 Review-Url: https://codereview.webrtc.org/1936503002 Cr-Commit-Position: refs/heads/master@{#12632}
This commit is contained in:
parent
ef00ec1d4e
commit
600246e63f
@ -230,7 +230,7 @@ class VideoCodingModule : public Module {
|
|||||||
//
|
//
|
||||||
// Return value : VCM_OK, on success.
|
// Return value : VCM_OK, on success.
|
||||||
// < 0, on error.
|
// < 0, on error.
|
||||||
virtual int32_t IntraFrameRequest(int stream_index) = 0;
|
virtual int32_t IntraFrameRequest(size_t stream_index) = 0;
|
||||||
|
|
||||||
// Frame Dropper enable. Can be used to disable the frame dropping when the
|
// Frame Dropper enable. Can be used to disable the frame dropping when the
|
||||||
// encoder
|
// encoder
|
||||||
|
|||||||
@ -152,7 +152,7 @@ class VideoCodingModuleImpl : public VideoCodingModule {
|
|||||||
return sender_.AddVideoFrame(videoFrame, contentMetrics, codecSpecificInfo);
|
return sender_.AddVideoFrame(videoFrame, contentMetrics, codecSpecificInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t IntraFrameRequest(int stream_index) override {
|
int32_t IntraFrameRequest(size_t stream_index) override {
|
||||||
return sender_.IntraFrameRequest(stream_index);
|
return sender_.IntraFrameRequest(stream_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class VideoSender : public Module {
|
|||||||
const VideoContentMetrics* _contentMetrics,
|
const VideoContentMetrics* _contentMetrics,
|
||||||
const CodecSpecificInfo* codecSpecificInfo);
|
const CodecSpecificInfo* codecSpecificInfo);
|
||||||
|
|
||||||
int32_t IntraFrameRequest(int stream_index);
|
int32_t IntraFrameRequest(size_t stream_index);
|
||||||
int32_t EnableFrameDropper(bool enable);
|
int32_t EnableFrameDropper(bool enable);
|
||||||
|
|
||||||
void SuspendBelowMinBitrate();
|
void SuspendBelowMinBitrate();
|
||||||
|
|||||||
@ -335,11 +335,10 @@ int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
|
|||||||
return VCM_OK;
|
return VCM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t VideoSender::IntraFrameRequest(int stream_index) {
|
int32_t VideoSender::IntraFrameRequest(size_t stream_index) {
|
||||||
{
|
{
|
||||||
rtc::CritScope lock(¶ms_crit_);
|
rtc::CritScope lock(¶ms_crit_);
|
||||||
if (stream_index < 0 ||
|
if (stream_index >= next_frame_types_.size()) {
|
||||||
static_cast<size_t>(stream_index) >= next_frame_types_.size()) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
next_frame_types_[stream_index] = kVideoFrameKey;
|
next_frame_types_[stream_index] = kVideoFrameKey;
|
||||||
@ -353,7 +352,7 @@ int32_t VideoSender::IntraFrameRequest(int stream_index) {
|
|||||||
// encoder_crit_.
|
// encoder_crit_.
|
||||||
rtc::CritScope lock(&encoder_crit_);
|
rtc::CritScope lock(&encoder_crit_);
|
||||||
rtc::CritScope params_lock(¶ms_crit_);
|
rtc::CritScope params_lock(¶ms_crit_);
|
||||||
if (static_cast<size_t>(stream_index) >= next_frame_types_.size())
|
if (stream_index >= next_frame_types_.size())
|
||||||
return -1;
|
return -1;
|
||||||
if (_encoder != nullptr && _encoder->InternalSource()) {
|
if (_encoder != nullptr && _encoder->InternalSource()) {
|
||||||
// Try to request the frame if we have an external encoder with
|
// Try to request the frame if we have an external encoder with
|
||||||
|
|||||||
@ -290,10 +290,6 @@ TEST_F(TestVideoSenderWithMockEncoder, TestIntraRequests) {
|
|||||||
EXPECT_EQ(-1, sender_->IntraFrameRequest(3));
|
EXPECT_EQ(-1, sender_->IntraFrameRequest(3));
|
||||||
ExpectIntraRequest(-1);
|
ExpectIntraRequest(-1);
|
||||||
AddFrame();
|
AddFrame();
|
||||||
|
|
||||||
EXPECT_EQ(-1, sender_->IntraFrameRequest(-1));
|
|
||||||
ExpectIntraRequest(-1);
|
|
||||||
AddFrame();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVideoSenderWithMockEncoder, TestIntraRequestsInternalCapture) {
|
TEST_F(TestVideoSenderWithMockEncoder, TestIntraRequestsInternalCapture) {
|
||||||
@ -313,7 +309,6 @@ TEST_F(TestVideoSenderWithMockEncoder, TestIntraRequestsInternalCapture) {
|
|||||||
EXPECT_EQ(0, sender_->IntraFrameRequest(2));
|
EXPECT_EQ(0, sender_->IntraFrameRequest(2));
|
||||||
// No requests expected since these indices are out of bounds.
|
// No requests expected since these indices are out of bounds.
|
||||||
EXPECT_EQ(-1, sender_->IntraFrameRequest(3));
|
EXPECT_EQ(-1, sender_->IntraFrameRequest(3));
|
||||||
EXPECT_EQ(-1, sender_->IntraFrameRequest(-1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVideoSenderWithMockEncoder, TestEncoderParametersForInternalSource) {
|
TEST_F(TestVideoSenderWithMockEncoder, TestEncoderParametersForInternalSource) {
|
||||||
|
|||||||
@ -13,16 +13,18 @@
|
|||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/video/vie_encoder.h"
|
#include "webrtc/video/vie_encoder.h"
|
||||||
|
|
||||||
|
static const int kMinKeyFrameRequestIntervalMs = 300;
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
EncoderStateFeedback::EncoderStateFeedback() : vie_encoder_(nullptr) {}
|
EncoderStateFeedback::EncoderStateFeedback(Clock* clock,
|
||||||
|
const std::vector<uint32_t>& ssrcs,
|
||||||
void EncoderStateFeedback::Init(const std::vector<uint32_t>& ssrcs,
|
ViEEncoder* encoder)
|
||||||
ViEEncoder* encoder) {
|
: clock_(clock),
|
||||||
|
ssrcs_(ssrcs),
|
||||||
|
vie_encoder_(encoder),
|
||||||
|
time_last_intra_request_ms_(ssrcs.size(), -1) {
|
||||||
RTC_DCHECK(!ssrcs.empty());
|
RTC_DCHECK(!ssrcs.empty());
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
ssrcs_ = ssrcs;
|
|
||||||
vie_encoder_ = encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EncoderStateFeedback::HasSsrc(uint32_t ssrc) {
|
bool EncoderStateFeedback::HasSsrc(uint32_t ssrc) {
|
||||||
@ -33,41 +35,59 @@ bool EncoderStateFeedback::HasSsrc(uint32_t ssrc) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t EncoderStateFeedback::GetStreamIndex(uint32_t ssrc) {
|
||||||
|
for (size_t i = 0; i < ssrcs_.size(); ++i) {
|
||||||
|
if (ssrcs_[i] == ssrc)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
RTC_NOTREACHED() << "Unknown ssrc " << ssrc;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void EncoderStateFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) {
|
void EncoderStateFeedback::OnReceivedIntraFrameRequest(uint32_t ssrc) {
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
if (!HasSsrc(ssrc))
|
if (!HasSsrc(ssrc))
|
||||||
return;
|
return;
|
||||||
RTC_DCHECK(vie_encoder_);
|
|
||||||
|
|
||||||
vie_encoder_->OnReceivedIntraFrameRequest(ssrc);
|
size_t index = GetStreamIndex(ssrc);
|
||||||
|
{
|
||||||
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
|
rtc::CritScope lock(&crit_);
|
||||||
|
if (time_last_intra_request_ms_[index] + kMinKeyFrameRequestIntervalMs >
|
||||||
|
now_ms) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
time_last_intra_request_ms_[index] = now_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
vie_encoder_->OnReceivedIntraFrameRequest(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncoderStateFeedback::OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) {
|
void EncoderStateFeedback::OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) {
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
if (!HasSsrc(ssrc))
|
if (!HasSsrc(ssrc))
|
||||||
return;
|
return;
|
||||||
RTC_DCHECK(vie_encoder_);
|
|
||||||
|
|
||||||
vie_encoder_->OnReceivedSLI(ssrc, picture_id);
|
vie_encoder_->OnReceivedSLI(picture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EncoderStateFeedback::OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) {
|
void EncoderStateFeedback::OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) {
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
if (!HasSsrc(ssrc))
|
if (!HasSsrc(ssrc))
|
||||||
return;
|
return;
|
||||||
RTC_DCHECK(vie_encoder_);
|
|
||||||
|
|
||||||
vie_encoder_->OnReceivedRPSI(ssrc, picture_id);
|
vie_encoder_->OnReceivedRPSI(picture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sending SSRCs for this encoder should never change since they are configured
|
// Sending SSRCs for this encoder should never change since they are configured
|
||||||
// once and not reconfigured.
|
// once and not reconfigured, however, OnLocalSsrcChanged is called when the
|
||||||
|
// RtpModules are created with a different SSRC than what will be used in the
|
||||||
|
// end.
|
||||||
|
// TODO(perkj): Can we make sure the RTP module is created with the right SSRC
|
||||||
|
// from the beginning so this method is not triggered during creation ?
|
||||||
void EncoderStateFeedback::OnLocalSsrcChanged(uint32_t old_ssrc,
|
void EncoderStateFeedback::OnLocalSsrcChanged(uint32_t old_ssrc,
|
||||||
uint32_t new_ssrc) {
|
uint32_t new_ssrc) {
|
||||||
if (!RTC_DCHECK_IS_ON)
|
if (!RTC_DCHECK_IS_ON)
|
||||||
return;
|
return;
|
||||||
rtc::CritScope lock(&crit_);
|
|
||||||
if (ssrcs_.empty()) // Encoder not yet attached (or detached for teardown).
|
if (old_ssrc == 0) // old_ssrc == 0 during creation.
|
||||||
return;
|
return;
|
||||||
// SSRC shouldn't change to something we haven't already registered with the
|
// SSRC shouldn't change to something we haven't already registered with the
|
||||||
// encoder.
|
// encoder.
|
||||||
|
|||||||
@ -7,10 +7,6 @@
|
|||||||
* in the file PATENTS. All contributing project authors may
|
* in the file PATENTS. All contributing project authors may
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO(mflodman) ViEEncoder has a time check to not send key frames too often,
|
|
||||||
// move the logic to this class.
|
|
||||||
|
|
||||||
#ifndef WEBRTC_VIDEO_ENCODER_STATE_FEEDBACK_H_
|
#ifndef WEBRTC_VIDEO_ENCODER_STATE_FEEDBACK_H_
|
||||||
#define WEBRTC_VIDEO_ENCODER_STATE_FEEDBACK_H_
|
#define WEBRTC_VIDEO_ENCODER_STATE_FEEDBACK_H_
|
||||||
|
|
||||||
@ -18,6 +14,7 @@
|
|||||||
|
|
||||||
#include "webrtc/base/criticalsection.h"
|
#include "webrtc/base/criticalsection.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
|
#include "webrtc/system_wrappers/include/clock.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -26,22 +23,24 @@ class ViEEncoder;
|
|||||||
|
|
||||||
class EncoderStateFeedback : public RtcpIntraFrameObserver {
|
class EncoderStateFeedback : public RtcpIntraFrameObserver {
|
||||||
public:
|
public:
|
||||||
EncoderStateFeedback();
|
EncoderStateFeedback(Clock* clock,
|
||||||
|
const std::vector<uint32_t>& ssrcs,
|
||||||
// Adds an encoder to receive feedback for a set of SSRCs.
|
ViEEncoder* encoder);
|
||||||
void Init(const std::vector<uint32_t>& ssrc, ViEEncoder* encoder);
|
|
||||||
|
|
||||||
void OnReceivedIntraFrameRequest(uint32_t ssrc) override;
|
void OnReceivedIntraFrameRequest(uint32_t ssrc) override;
|
||||||
void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override;
|
void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id) override;
|
||||||
void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override;
|
void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id) override;
|
||||||
void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) override;
|
void OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool HasSsrc(uint32_t ssrc) EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
bool HasSsrc(uint32_t ssrc);
|
||||||
rtc::CriticalSection crit_;
|
size_t GetStreamIndex(uint32_t ssrc);
|
||||||
|
|
||||||
std::vector<uint32_t> ssrcs_ GUARDED_BY(crit_);
|
Clock* const clock_;
|
||||||
ViEEncoder* vie_encoder_ GUARDED_BY(crit_);
|
const std::vector<uint32_t> ssrcs_;
|
||||||
|
ViEEncoder* const vie_encoder_;
|
||||||
|
|
||||||
|
rtc::CriticalSection crit_;
|
||||||
|
std::vector<int64_t> time_last_intra_request_ms_ GUARDED_BY(crit_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -12,10 +12,6 @@
|
|||||||
|
|
||||||
#include "testing/gmock/include/gmock/gmock.h"
|
#include "testing/gmock/include/gmock/gmock.h"
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
|
|
||||||
#include "webrtc/modules/pacing/paced_sender.h"
|
|
||||||
#include "webrtc/modules/pacing/packet_router.h"
|
|
||||||
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
|
#include "webrtc/modules/utility/include/mock/mock_process_thread.h"
|
||||||
#include "webrtc/video/vie_encoder.h"
|
#include "webrtc/video/vie_encoder.h"
|
||||||
|
|
||||||
@ -27,42 +23,59 @@ class MockVieEncoder : public ViEEncoder {
|
|||||||
public:
|
public:
|
||||||
explicit MockVieEncoder(ProcessThread* process_thread)
|
explicit MockVieEncoder(ProcessThread* process_thread)
|
||||||
: ViEEncoder(1,
|
: ViEEncoder(1,
|
||||||
std::vector<uint32_t>(),
|
|
||||||
process_thread,
|
process_thread,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr) {}
|
nullptr) {}
|
||||||
~MockVieEncoder() {}
|
~MockVieEncoder() {}
|
||||||
|
|
||||||
MOCK_METHOD1(OnReceivedIntraFrameRequest,
|
MOCK_METHOD1(OnReceivedIntraFrameRequest, void(size_t));
|
||||||
void(uint32_t));
|
MOCK_METHOD1(OnReceivedSLI, void(uint8_t picture_id));
|
||||||
MOCK_METHOD2(OnReceivedSLI,
|
MOCK_METHOD1(OnReceivedRPSI, void(uint64_t picture_id));
|
||||||
void(uint32_t ssrc, uint8_t picture_id));
|
|
||||||
MOCK_METHOD2(OnReceivedRPSI,
|
|
||||||
void(uint32_t ssrc, uint64_t picture_id));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(VieKeyRequestTest, CreateAndTriggerRequests) {
|
class VieKeyRequestTest : public ::testing::Test {
|
||||||
static const uint32_t kSsrc = 1234;
|
public:
|
||||||
NiceMock<MockProcessThread> process_thread;
|
VieKeyRequestTest()
|
||||||
PacketRouter router;
|
: encoder_(&process_thread_),
|
||||||
MockVieEncoder encoder(&process_thread);
|
simulated_clock_(123456789),
|
||||||
|
encoder_state_feedback_(
|
||||||
|
&simulated_clock_,
|
||||||
|
std::vector<uint32_t>(1, VieKeyRequestTest::kSsrc),
|
||||||
|
&encoder_) {}
|
||||||
|
|
||||||
EncoderStateFeedback encoder_state_feedback;
|
protected:
|
||||||
encoder_state_feedback.Init(std::vector<uint32_t>(1, kSsrc), &encoder);
|
const uint32_t kSsrc = 1234;
|
||||||
|
NiceMock<MockProcessThread> process_thread_;
|
||||||
|
MockVieEncoder encoder_;
|
||||||
|
SimulatedClock simulated_clock_;
|
||||||
|
EncoderStateFeedback encoder_state_feedback_;
|
||||||
|
};
|
||||||
|
|
||||||
EXPECT_CALL(encoder, OnReceivedIntraFrameRequest(kSsrc))
|
TEST_F(VieKeyRequestTest, CreateAndTriggerRequests) {
|
||||||
.Times(1);
|
EXPECT_CALL(encoder_, OnReceivedIntraFrameRequest(0)).Times(1);
|
||||||
encoder_state_feedback.OnReceivedIntraFrameRequest(kSsrc);
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
|
||||||
const uint8_t sli_picture_id = 3;
|
const uint8_t sli_picture_id = 3;
|
||||||
EXPECT_CALL(encoder, OnReceivedSLI(kSsrc, sli_picture_id))
|
EXPECT_CALL(encoder_, OnReceivedSLI(sli_picture_id)).Times(1);
|
||||||
.Times(1);
|
encoder_state_feedback_.OnReceivedSLI(kSsrc, sli_picture_id);
|
||||||
encoder_state_feedback.OnReceivedSLI(kSsrc, sli_picture_id);
|
|
||||||
|
|
||||||
const uint64_t rpsi_picture_id = 9;
|
const uint64_t rpsi_picture_id = 9;
|
||||||
EXPECT_CALL(encoder, OnReceivedRPSI(kSsrc, rpsi_picture_id))
|
EXPECT_CALL(encoder_, OnReceivedRPSI(rpsi_picture_id)).Times(1);
|
||||||
.Times(1);
|
encoder_state_feedback_.OnReceivedRPSI(kSsrc, rpsi_picture_id);
|
||||||
encoder_state_feedback.OnReceivedRPSI(kSsrc, rpsi_picture_id);
|
}
|
||||||
|
|
||||||
|
TEST_F(VieKeyRequestTest, TooManyOnReceivedIntraFrameRequest) {
|
||||||
|
EXPECT_CALL(encoder_, OnReceivedIntraFrameRequest(0)).Times(1);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
simulated_clock_.AdvanceTimeMilliseconds(10);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
|
||||||
|
EXPECT_CALL(encoder_, OnReceivedIntraFrameRequest(0)).Times(1);
|
||||||
|
simulated_clock_.AdvanceTimeMilliseconds(300);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
|
encoder_state_feedback_.OnReceivedIntraFrameRequest(kSsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "webrtc/modules/pacing/packet_router.h"
|
#include "webrtc/modules/pacing/packet_router.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||||
#include "webrtc/modules/utility/include/process_thread.h"
|
#include "webrtc/modules/utility/include/process_thread.h"
|
||||||
|
#include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
|
||||||
#include "webrtc/video/call_stats.h"
|
#include "webrtc/video/call_stats.h"
|
||||||
#include "webrtc/video/video_capture_input.h"
|
#include "webrtc/video/video_capture_input.h"
|
||||||
#include "webrtc/video/vie_remb.h"
|
#include "webrtc/video/vie_remb.h"
|
||||||
@ -376,10 +377,12 @@ VideoSendStream::VideoSendStream(
|
|||||||
config.post_encode_callback,
|
config.post_encode_callback,
|
||||||
&stats_proxy_),
|
&stats_proxy_),
|
||||||
vie_encoder_(num_cpu_cores,
|
vie_encoder_(num_cpu_cores,
|
||||||
config_.rtp.ssrcs,
|
|
||||||
module_process_thread_,
|
module_process_thread_,
|
||||||
&stats_proxy_,
|
&stats_proxy_,
|
||||||
&overuse_detector_),
|
&overuse_detector_),
|
||||||
|
encoder_feedback_(Clock::GetRealTimeClock(),
|
||||||
|
config.rtp.ssrcs,
|
||||||
|
&vie_encoder_),
|
||||||
video_sender_(vie_encoder_.video_sender()),
|
video_sender_(vie_encoder_.video_sender()),
|
||||||
bandwidth_observer_(congestion_controller_->GetBitrateController()
|
bandwidth_observer_(congestion_controller_->GetBitrateController()
|
||||||
->CreateRtcpBandwidthObserver()),
|
->CreateRtcpBandwidthObserver()),
|
||||||
@ -407,7 +410,6 @@ VideoSendStream::VideoSendStream(
|
|||||||
RTC_DCHECK(congestion_controller_);
|
RTC_DCHECK(congestion_controller_);
|
||||||
RTC_DCHECK(remb_);
|
RTC_DCHECK(remb_);
|
||||||
|
|
||||||
encoder_feedback_.Init(config_.rtp.ssrcs, &vie_encoder_);
|
|
||||||
|
|
||||||
// RTP/RTCP initialization.
|
// RTP/RTCP initialization.
|
||||||
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
|
||||||
@ -567,6 +569,13 @@ void VideoSendStream::EncoderProcess() {
|
|||||||
vie_encoder_.SetEncoder(encoder_settings->video_codec,
|
vie_encoder_.SetEncoder(encoder_settings->video_codec,
|
||||||
encoder_settings->min_transmit_bitrate_bps,
|
encoder_settings->min_transmit_bitrate_bps,
|
||||||
payload_router_.MaxPayloadLength(), this);
|
payload_router_.MaxPayloadLength(), this);
|
||||||
|
|
||||||
|
// Clear stats for disabled layers.
|
||||||
|
for (size_t i = encoder_settings->streams.size();
|
||||||
|
i < config_.rtp.ssrcs.size(); ++i) {
|
||||||
|
stats_proxy_.OnInactiveSsrc(config_.rtp.ssrcs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (config_.suspend_below_min_bitrate) {
|
if (config_.suspend_below_min_bitrate) {
|
||||||
video_sender_->SuspendBelowMinBitrate();
|
video_sender_->SuspendBelowMinBitrate();
|
||||||
bitrate_allocator_->EnforceMinBitrate(false);
|
bitrate_allocator_->EnforceMinBitrate(false);
|
||||||
@ -627,8 +636,33 @@ int32_t VideoSendStream::Encoded(const EncodedImage& encoded_image,
|
|||||||
// |encoded_frame_proxy_| forwards frames to |config_.post_encode_callback|;
|
// |encoded_frame_proxy_| forwards frames to |config_.post_encode_callback|;
|
||||||
encoded_frame_proxy_.Encoded(encoded_image, codec_specific_info,
|
encoded_frame_proxy_.Encoded(encoded_image, codec_specific_info,
|
||||||
fragmentation);
|
fragmentation);
|
||||||
return payload_router_.Encoded(encoded_image, codec_specific_info,
|
int32_t return_value = payload_router_.Encoded(
|
||||||
fragmentation);
|
encoded_image, codec_specific_info, fragmentation);
|
||||||
|
|
||||||
|
if (kEnableFrameRecording) {
|
||||||
|
int layer = codec_specific_info->codecType == kVideoCodecVP8
|
||||||
|
? codec_specific_info->codecSpecific.VP8.simulcastIdx
|
||||||
|
: 0;
|
||||||
|
IvfFileWriter* file_writer;
|
||||||
|
{
|
||||||
|
if (file_writers_[layer] == nullptr) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "send_bitstream_ssrc";
|
||||||
|
for (uint32_t ssrc : config_.rtp.ssrcs)
|
||||||
|
oss << "_" << ssrc;
|
||||||
|
oss << "_layer" << layer << ".ivf";
|
||||||
|
file_writers_[layer] =
|
||||||
|
IvfFileWriter::Open(oss.str(), codec_specific_info->codecType);
|
||||||
|
}
|
||||||
|
file_writer = file_writers_[layer].get();
|
||||||
|
}
|
||||||
|
if (file_writer) {
|
||||||
|
bool ok = file_writer->WriteFrame(encoded_image);
|
||||||
|
RTC_DCHECK(ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSendStream::ConfigureProtection() {
|
void VideoSendStream::ConfigureProtection() {
|
||||||
|
|||||||
@ -34,6 +34,7 @@ namespace webrtc {
|
|||||||
class BitrateAllocator;
|
class BitrateAllocator;
|
||||||
class CallStats;
|
class CallStats;
|
||||||
class CongestionController;
|
class CongestionController;
|
||||||
|
class IvfFileWriter;
|
||||||
class ProcessThread;
|
class ProcessThread;
|
||||||
class RtpRtcp;
|
class RtpRtcp;
|
||||||
class ViEEncoder;
|
class ViEEncoder;
|
||||||
@ -126,6 +127,10 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
|||||||
BitrateAllocator* const bitrate_allocator_;
|
BitrateAllocator* const bitrate_allocator_;
|
||||||
VieRemb* const remb_;
|
VieRemb* const remb_;
|
||||||
|
|
||||||
|
static const bool kEnableFrameRecording = false;
|
||||||
|
static const int kMaxLayers = 3;
|
||||||
|
std::unique_ptr<IvfFileWriter> file_writers_[kMaxLayers];
|
||||||
|
|
||||||
rtc::PlatformThread encoder_thread_;
|
rtc::PlatformThread encoder_thread_;
|
||||||
rtc::Event encoder_wakeup_event_;
|
rtc::Event encoder_wakeup_event_;
|
||||||
volatile int stop_encoder_thread_;
|
volatile int stop_encoder_thread_;
|
||||||
@ -134,8 +139,8 @@ class VideoSendStream : public webrtc::VideoSendStream,
|
|||||||
GUARDED_BY(encoder_settings_crit_);
|
GUARDED_BY(encoder_settings_crit_);
|
||||||
|
|
||||||
OveruseFrameDetector overuse_detector_;
|
OveruseFrameDetector overuse_detector_;
|
||||||
EncoderStateFeedback encoder_feedback_;
|
|
||||||
ViEEncoder vie_encoder_;
|
ViEEncoder vie_encoder_;
|
||||||
|
EncoderStateFeedback encoder_feedback_;
|
||||||
vcm::VideoSender* const video_sender_;
|
vcm::VideoSender* const video_sender_;
|
||||||
|
|
||||||
const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
|
const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
|
||||||
|
|||||||
@ -17,26 +17,18 @@
|
|||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
#include "webrtc/base/trace_event.h"
|
#include "webrtc/base/trace_event.h"
|
||||||
#include "webrtc/common_video/include/frame_callback.h"
|
|
||||||
#include "webrtc/common_video/include/video_image.h"
|
|
||||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
|
||||||
#include "webrtc/modules/pacing/paced_sender.h"
|
#include "webrtc/modules/pacing/paced_sender.h"
|
||||||
#include "webrtc/modules/utility/include/process_thread.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/include/video_coding.h"
|
||||||
#include "webrtc/modules/video_coding/include/video_coding_defines.h"
|
#include "webrtc/modules/video_coding/include/video_coding_defines.h"
|
||||||
#include "webrtc/system_wrappers/include/clock.h"
|
|
||||||
#include "webrtc/system_wrappers/include/metrics.h"
|
#include "webrtc/system_wrappers/include/metrics.h"
|
||||||
#include "webrtc/system_wrappers/include/tick_util.h"
|
#include "webrtc/system_wrappers/include/tick_util.h"
|
||||||
#include "webrtc/video/overuse_frame_detector.h"
|
#include "webrtc/video/overuse_frame_detector.h"
|
||||||
#include "webrtc/video/payload_router.h"
|
|
||||||
#include "webrtc/video/send_statistics_proxy.h"
|
#include "webrtc/video/send_statistics_proxy.h"
|
||||||
#include "webrtc/video_frame.h"
|
#include "webrtc/video_frame.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
static const float kStopPaddingThresholdMs = 2000;
|
static const float kStopPaddingThresholdMs = 2000;
|
||||||
static const int kMinKeyFrameRequestIntervalMs = 300;
|
|
||||||
|
|
||||||
class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
||||||
public:
|
public:
|
||||||
@ -54,12 +46,10 @@ class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
||||||
const std::vector<uint32_t>& ssrcs,
|
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
SendStatisticsProxy* stats_proxy,
|
SendStatisticsProxy* stats_proxy,
|
||||||
OveruseFrameDetector* overuse_detector)
|
OveruseFrameDetector* overuse_detector)
|
||||||
: number_of_cores_(number_of_cores),
|
: number_of_cores_(number_of_cores),
|
||||||
ssrcs_(ssrcs),
|
|
||||||
vp_(VideoProcessing::Create()),
|
vp_(VideoProcessing::Create()),
|
||||||
qm_callback_(new QMVideoSettingsCallback(vp_.get())),
|
qm_callback_(new QMVideoSettingsCallback(vp_.get())),
|
||||||
video_sender_(Clock::GetRealTimeClock(),
|
video_sender_(Clock::GetRealTimeClock(),
|
||||||
@ -76,7 +66,6 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
|||||||
network_is_transmitting_(true),
|
network_is_transmitting_(true),
|
||||||
encoder_paused_(true),
|
encoder_paused_(true),
|
||||||
encoder_paused_and_dropped_frame_(false),
|
encoder_paused_and_dropped_frame_(false),
|
||||||
time_last_intra_request_ms_(ssrcs.size(), -1),
|
|
||||||
module_process_thread_(module_process_thread),
|
module_process_thread_(module_process_thread),
|
||||||
has_received_sli_(false),
|
has_received_sli_(false),
|
||||||
picture_id_sli_(0),
|
picture_id_sli_(0),
|
||||||
@ -156,11 +145,6 @@ void ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stats_proxy_) {
|
if (stats_proxy_) {
|
||||||
// Clear stats for disabled layers.
|
|
||||||
for (size_t i = video_codec.numberOfSimulcastStreams; i < ssrcs_.size();
|
|
||||||
++i) {
|
|
||||||
stats_proxy_->OnInactiveSsrc(ssrcs_[i]);
|
|
||||||
}
|
|
||||||
VideoEncoderConfig::ContentType content_type =
|
VideoEncoderConfig::ContentType content_type =
|
||||||
VideoEncoderConfig::ContentType::kRealtimeVideo;
|
VideoEncoderConfig::ContentType::kRealtimeVideo;
|
||||||
switch (video_codec.mode) {
|
switch (video_codec.mode) {
|
||||||
@ -353,30 +337,6 @@ int32_t ViEEncoder::Encoded(const EncodedImage& encoded_image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
overuse_detector_->FrameSent(encoded_image._timeStamp);
|
overuse_detector_->FrameSent(encoded_image._timeStamp);
|
||||||
if (kEnableFrameRecording) {
|
|
||||||
int layer = codec_specific_info->codecType == kVideoCodecVP8
|
|
||||||
? codec_specific_info->codecSpecific.VP8.simulcastIdx
|
|
||||||
: 0;
|
|
||||||
IvfFileWriter* file_writer;
|
|
||||||
{
|
|
||||||
rtc::CritScope lock(&data_cs_);
|
|
||||||
if (file_writers_[layer] == nullptr) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "send_bitstream_ssrc";
|
|
||||||
for (uint32_t ssrc : ssrcs_)
|
|
||||||
oss << "_" << ssrc;
|
|
||||||
oss << "_layer" << layer << ".ivf";
|
|
||||||
file_writers_[layer] =
|
|
||||||
IvfFileWriter::Open(oss.str(), codec_specific_info->codecType);
|
|
||||||
}
|
|
||||||
file_writer = file_writers_[layer].get();
|
|
||||||
}
|
|
||||||
if (file_writer) {
|
|
||||||
bool ok = file_writer->WriteFrame(encoded_image);
|
|
||||||
RTC_DCHECK(ok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,40 +347,22 @@ void ViEEncoder::SendStatistics(uint32_t bit_rate,
|
|||||||
stats_proxy_->OnEncoderStatsUpdate(frame_rate, bit_rate, encoder_name);
|
stats_proxy_->OnEncoderStatsUpdate(frame_rate, bit_rate, encoder_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::OnReceivedSLI(uint32_t /*ssrc*/,
|
void ViEEncoder::OnReceivedSLI(uint8_t picture_id) {
|
||||||
uint8_t picture_id) {
|
|
||||||
rtc::CritScope lock(&data_cs_);
|
rtc::CritScope lock(&data_cs_);
|
||||||
picture_id_sli_ = picture_id;
|
picture_id_sli_ = picture_id;
|
||||||
has_received_sli_ = true;
|
has_received_sli_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::OnReceivedRPSI(uint32_t /*ssrc*/,
|
void ViEEncoder::OnReceivedRPSI(uint64_t picture_id) {
|
||||||
uint64_t picture_id) {
|
|
||||||
rtc::CritScope lock(&data_cs_);
|
rtc::CritScope lock(&data_cs_);
|
||||||
picture_id_rpsi_ = picture_id;
|
picture_id_rpsi_ = picture_id;
|
||||||
has_received_rpsi_ = true;
|
has_received_rpsi_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::OnReceivedIntraFrameRequest(uint32_t ssrc) {
|
void ViEEncoder::OnReceivedIntraFrameRequest(size_t stream_index) {
|
||||||
// Key frame request from remote side, signal to VCM.
|
// Key frame request from remote side, signal to VCM.
|
||||||
TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
|
TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
|
||||||
|
video_sender_.IntraFrameRequest(stream_index);
|
||||||
for (size_t i = 0; i < ssrcs_.size(); ++i) {
|
|
||||||
if (ssrcs_[i] != ssrc)
|
|
||||||
continue;
|
|
||||||
int64_t now_ms = TickTime::MillisecondTimestamp();
|
|
||||||
{
|
|
||||||
rtc::CritScope lock(&data_cs_);
|
|
||||||
if (time_last_intra_request_ms_[i] + kMinKeyFrameRequestIntervalMs >
|
|
||||||
now_ms) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
time_last_intra_request_ms_[i] = now_ms;
|
|
||||||
}
|
|
||||||
video_sender_.IntraFrameRequest(static_cast<int>(i));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RTC_NOTREACHED() << "Should not receive keyframe requests on unknown SSRCs.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
||||||
@ -443,8 +385,8 @@ void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps,
|
|||||||
if (!video_suspension_changed)
|
if (!video_suspension_changed)
|
||||||
return;
|
return;
|
||||||
// Video suspend-state changed, inform codec observer.
|
// Video suspend-state changed, inform codec observer.
|
||||||
LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended
|
LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended;
|
||||||
<< " for ssrc " << ssrcs_[0];
|
|
||||||
if (stats_proxy_)
|
if (stats_proxy_)
|
||||||
stats_proxy_->OnSuspendChange(video_is_suspended);
|
stats_proxy_->OnSuspendChange(video_is_suspended);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
#include "webrtc/media/base/videosinkinterface.h"
|
#include "webrtc/media/base/videosinkinterface.h"
|
||||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
#include "webrtc/modules/video_coding/include/video_coding_defines.h"
|
#include "webrtc/modules/video_coding/include/video_coding_defines.h"
|
||||||
#include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
|
|
||||||
#include "webrtc/modules/video_coding/video_coding_impl.h"
|
#include "webrtc/modules/video_coding/video_coding_impl.h"
|
||||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
@ -58,7 +57,6 @@ class ViEEncoder : public VideoEncoderRateObserver,
|
|||||||
friend class ViEBitrateObserver;
|
friend class ViEBitrateObserver;
|
||||||
|
|
||||||
ViEEncoder(uint32_t number_of_cores,
|
ViEEncoder(uint32_t number_of_cores,
|
||||||
const std::vector<uint32_t>& ssrcs,
|
|
||||||
ProcessThread* module_process_thread,
|
ProcessThread* module_process_thread,
|
||||||
SendStatisticsProxy* stats_proxy,
|
SendStatisticsProxy* stats_proxy,
|
||||||
OveruseFrameDetector* overuse_detector);
|
OveruseFrameDetector* overuse_detector);
|
||||||
@ -108,9 +106,9 @@ class ViEEncoder : public VideoEncoderRateObserver,
|
|||||||
const std::string& encoder_name) override;
|
const std::string& encoder_name) override;
|
||||||
|
|
||||||
// virtual to test EncoderStateFeedback with mocks.
|
// virtual to test EncoderStateFeedback with mocks.
|
||||||
virtual void OnReceivedIntraFrameRequest(uint32_t ssrc);
|
virtual void OnReceivedIntraFrameRequest(size_t stream_index);
|
||||||
virtual void OnReceivedSLI(uint32_t ssrc, uint8_t picture_id);
|
virtual void OnReceivedSLI(uint8_t picture_id);
|
||||||
virtual void OnReceivedRPSI(uint32_t ssrc, uint64_t picture_id);
|
virtual void OnReceivedRPSI(uint64_t picture_id);
|
||||||
|
|
||||||
int GetPaddingNeededBps() const;
|
int GetPaddingNeededBps() const;
|
||||||
|
|
||||||
@ -119,15 +117,11 @@ class ViEEncoder : public VideoEncoderRateObserver,
|
|||||||
int64_t round_trip_time_ms);
|
int64_t round_trip_time_ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const bool kEnableFrameRecording = false;
|
|
||||||
static const int kMaxLayers = 3;
|
|
||||||
|
|
||||||
bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
bool EncoderPaused() const EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
void TraceFrameDropStart() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
void TraceFrameDropEnd() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
void TraceFrameDropEnd() EXCLUSIVE_LOCKS_REQUIRED(data_cs_);
|
||||||
|
|
||||||
const uint32_t number_of_cores_;
|
const uint32_t number_of_cores_;
|
||||||
const std::vector<uint32_t> ssrcs_;
|
|
||||||
|
|
||||||
const std::unique_ptr<VideoProcessing> vp_;
|
const std::unique_ptr<VideoProcessing> vp_;
|
||||||
const std::unique_ptr<QMVideoSettingsCallback> qm_callback_;
|
const std::unique_ptr<QMVideoSettingsCallback> qm_callback_;
|
||||||
@ -148,7 +142,6 @@ class ViEEncoder : public VideoEncoderRateObserver,
|
|||||||
bool network_is_transmitting_ GUARDED_BY(data_cs_);
|
bool network_is_transmitting_ GUARDED_BY(data_cs_);
|
||||||
bool encoder_paused_ GUARDED_BY(data_cs_);
|
bool encoder_paused_ GUARDED_BY(data_cs_);
|
||||||
bool encoder_paused_and_dropped_frame_ GUARDED_BY(data_cs_);
|
bool encoder_paused_and_dropped_frame_ GUARDED_BY(data_cs_);
|
||||||
std::vector<int64_t> time_last_intra_request_ms_ GUARDED_BY(data_cs_);
|
|
||||||
|
|
||||||
rtc::CriticalSection sink_cs_;
|
rtc::CriticalSection sink_cs_;
|
||||||
EncodedImageCallback* sink_ GUARDED_BY(sink_cs_);
|
EncodedImageCallback* sink_ GUARDED_BY(sink_cs_);
|
||||||
@ -161,8 +154,6 @@ class ViEEncoder : public VideoEncoderRateObserver,
|
|||||||
uint64_t picture_id_rpsi_ GUARDED_BY(data_cs_);
|
uint64_t picture_id_rpsi_ GUARDED_BY(data_cs_);
|
||||||
|
|
||||||
bool video_suspended_ GUARDED_BY(data_cs_);
|
bool video_suspended_ GUARDED_BY(data_cs_);
|
||||||
|
|
||||||
std::unique_ptr<IvfFileWriter> file_writers_[kMaxLayers] GUARDED_BY(data_cs_);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user