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:
perkj 2016-05-04 11:26:51 -07:00 committed by Commit bot
parent ef00ec1d4e
commit 600246e63f
12 changed files with 150 additions and 152 deletions

View File

@ -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

View File

@ -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);
} }

View File

@ -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();

View File

@ -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(&params_crit_); rtc::CritScope lock(&params_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(&params_crit_); rtc::CritScope params_lock(&params_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

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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() {

View File

@ -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_;

View File

@ -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);
} }

View File

@ -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