Get VideoCapturer stats via VideoTrackSourceInterface in StatsCollector,
without involving the VideoMediaChannel. BUG=webrtc:5426 Review URL: https://codereview.webrtc.org/1827023002 Cr-Commit-Position: refs/heads/master@{#12193}
This commit is contained in:
parent
86101e9c08
commit
fcc640f8f6
@ -88,6 +88,10 @@ class MediaStreamTrackInterface : public rtc::RefCountInterface,
|
||||
static const char kAudioKind[];
|
||||
static const char kVideoKind[];
|
||||
|
||||
// The kind() method must return kAudioKind only if the object is a
|
||||
// subclass of AudioTrackInterface, and kVideoKind only if the
|
||||
// object is a subclass of VideoTrackInterface. It is typically used
|
||||
// to protect a static_cast<> to the corresponding subclass.
|
||||
virtual std::string kind() const = 0;
|
||||
virtual std::string id() const = 0;
|
||||
virtual bool enabled() const = 0;
|
||||
@ -106,6 +110,11 @@ class VideoTrackSourceInterface
|
||||
: public MediaSourceInterface,
|
||||
public rtc::VideoSourceInterface<cricket::VideoFrame> {
|
||||
public:
|
||||
struct Stats {
|
||||
// Original size of captured frame, before video adaptation.
|
||||
int input_width;
|
||||
int input_height;
|
||||
};
|
||||
// Get access to the source implementation of cricket::VideoCapturer.
|
||||
// This can be used for receiving frames and state notifications.
|
||||
// But it should not be used for starting or stopping capturing.
|
||||
@ -132,6 +141,11 @@ class VideoTrackSourceInterface
|
||||
// the encoder.
|
||||
virtual rtc::Optional<bool> needs_denoising() const = 0;
|
||||
|
||||
// Returns false if no stats are available, e.g, for a remote
|
||||
// source, or a source which has not seen its first frame yet.
|
||||
// Should avoid blocking.
|
||||
virtual bool GetStats(Stats* stats) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoTrackSourceInterface() {}
|
||||
};
|
||||
|
||||
@ -101,6 +101,8 @@ class AudioRtpSender : public ObserverInterface,
|
||||
bool SetParameters(const RtpParameters& parameters);
|
||||
|
||||
private:
|
||||
// TODO(nisse): Since SSRC == 0 is technically valid, figure out
|
||||
// some other way to test if we have a valid SSRC.
|
||||
bool can_send_track() const { return track_ && ssrc_; }
|
||||
// Helper function to construct options for
|
||||
// AudioProviderInterface::SetAudioSend.
|
||||
|
||||
@ -236,11 +236,9 @@ void ExtractStats(const cricket::VideoSenderInfo& info, StatsReport* report) {
|
||||
{ StatsReport::kStatsValueNameEncodeUsagePercent,
|
||||
info.encode_usage_percent },
|
||||
{ StatsReport::kStatsValueNameFirsReceived, info.firs_rcvd },
|
||||
{ StatsReport::kStatsValueNameFrameHeightInput, info.input_frame_height },
|
||||
{ StatsReport::kStatsValueNameFrameHeightSent, info.send_frame_height },
|
||||
{ StatsReport::kStatsValueNameFrameRateInput, info.framerate_input },
|
||||
{ StatsReport::kStatsValueNameFrameRateSent, info.framerate_sent },
|
||||
{ StatsReport::kStatsValueNameFrameWidthInput, info.input_frame_width },
|
||||
{ StatsReport::kStatsValueNameFrameWidthSent, info.send_frame_width },
|
||||
{ StatsReport::kStatsValueNameNacksReceived, info.nacks_rcvd },
|
||||
{ StatsReport::kStatsValueNamePacketsLost, info.packets_lost },
|
||||
@ -474,6 +472,7 @@ StatsCollector::UpdateStats(PeerConnectionInterface::StatsOutputLevel level) {
|
||||
ExtractSessionInfo();
|
||||
ExtractVoiceInfo();
|
||||
ExtractVideoInfo(level);
|
||||
ExtractSenderInfo();
|
||||
ExtractDataInfo();
|
||||
UpdateTrackReports();
|
||||
}
|
||||
@ -828,6 +827,39 @@ void StatsCollector::ExtractVideoInfo(
|
||||
}
|
||||
}
|
||||
|
||||
void StatsCollector::ExtractSenderInfo() {
|
||||
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
|
||||
|
||||
for (const auto& sender : pc_->GetSenders()) {
|
||||
// TODO(nisse): SSRC == 0 currently means none. Delete check when
|
||||
// that is fixed.
|
||||
if (!sender->ssrc()) {
|
||||
continue;
|
||||
}
|
||||
const rtc::scoped_refptr<MediaStreamTrackInterface> track(sender->track());
|
||||
if (!track || track->kind() != MediaStreamTrackInterface::kVideoKind) {
|
||||
continue;
|
||||
}
|
||||
// Safe, because kind() == kVideoKind implies a subclass of
|
||||
// VideoTrackInterface; see mediastreaminterface.h.
|
||||
VideoTrackSourceInterface* source =
|
||||
static_cast<VideoTrackInterface*>(track.get())->GetSource();
|
||||
|
||||
VideoTrackSourceInterface::Stats stats;
|
||||
if (!source->GetStats(&stats)) {
|
||||
continue;
|
||||
}
|
||||
const StatsReport::Id stats_id = StatsReport::NewIdWithDirection(
|
||||
StatsReport::kStatsReportTypeSsrc,
|
||||
rtc::ToString<uint32_t>(sender->ssrc()), StatsReport::kSend);
|
||||
StatsReport* report = reports_.FindOrAddNew(stats_id);
|
||||
report->AddInt(StatsReport::kStatsValueNameFrameWidthInput,
|
||||
stats.input_width);
|
||||
report->AddInt(StatsReport::kStatsValueNameFrameHeightInput,
|
||||
stats.input_height);
|
||||
}
|
||||
}
|
||||
|
||||
void StatsCollector::ExtractDataInfo() {
|
||||
RTC_DCHECK(pc_->session()->signaling_thread()->IsCurrent());
|
||||
|
||||
|
||||
@ -113,6 +113,7 @@ class StatsCollector {
|
||||
void ExtractSessionInfo();
|
||||
void ExtractVoiceInfo();
|
||||
void ExtractVideoInfo(PeerConnectionInterface::StatsOutputLevel level);
|
||||
void ExtractSenderInfo();
|
||||
void BuildSsrcToTransportId();
|
||||
webrtc::StatsReport* GetReport(const StatsReport::StatsType& type,
|
||||
const std::string& id,
|
||||
|
||||
@ -360,6 +360,11 @@ void VideoCapturerTrackSource::Initialize(
|
||||
// Initialize hasn't succeeded until a successful state change has occurred.
|
||||
}
|
||||
|
||||
bool VideoCapturerTrackSource::GetStats(Stats* stats) {
|
||||
return video_capturer_->GetInputSize(&stats->input_width,
|
||||
&stats->input_height);
|
||||
}
|
||||
|
||||
void VideoCapturerTrackSource::Stop() {
|
||||
if (!started_) {
|
||||
return;
|
||||
|
||||
@ -58,6 +58,8 @@ class VideoCapturerTrackSource : public VideoTrackSource,
|
||||
return needs_denoising_;
|
||||
}
|
||||
|
||||
bool GetStats(Stats* stats) override;
|
||||
|
||||
void Stop() override;
|
||||
void Restart() override;
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ PROXY_METHOD0(void, Stop)
|
||||
PROXY_METHOD0(void, Restart)
|
||||
PROXY_CONSTMETHOD0(bool, is_screencast)
|
||||
PROXY_CONSTMETHOD0(rtc::Optional<bool>, needs_denoising)
|
||||
PROXY_METHOD1(bool, GetStats, Stats*)
|
||||
PROXY_METHOD2(void,
|
||||
AddOrUpdateSink,
|
||||
rtc::VideoSinkInterface<cricket::VideoFrame>*,
|
||||
|
||||
@ -40,6 +40,8 @@ class VideoTrackSource : public Notifier<VideoTrackSourceInterface> {
|
||||
virtual rtc::Optional<bool> needs_denoising() const {
|
||||
return rtc::Optional<bool>(); }
|
||||
|
||||
bool GetStats(Stats* stats) override { return false; }
|
||||
|
||||
void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
|
||||
const rtc::VideoSinkWants& wants) override;
|
||||
void RemoveSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink) override;
|
||||
|
||||
@ -660,8 +660,6 @@ struct VideoSenderInfo : public MediaSenderInfo {
|
||||
firs_rcvd(0),
|
||||
plis_rcvd(0),
|
||||
nacks_rcvd(0),
|
||||
input_frame_width(0),
|
||||
input_frame_height(0),
|
||||
send_frame_width(0),
|
||||
send_frame_height(0),
|
||||
framerate_input(0),
|
||||
@ -680,8 +678,6 @@ struct VideoSenderInfo : public MediaSenderInfo {
|
||||
int firs_rcvd;
|
||||
int plis_rcvd;
|
||||
int nacks_rcvd;
|
||||
int input_frame_width;
|
||||
int input_frame_height;
|
||||
int send_frame_width;
|
||||
int send_frame_height;
|
||||
int framerate_input;
|
||||
|
||||
@ -179,9 +179,15 @@ void VideoCapturer::set_frame_factory(VideoFrameFactory* frame_factory) {
|
||||
}
|
||||
}
|
||||
|
||||
void VideoCapturer::GetStats(VideoFormat* last_captured_frame_format) {
|
||||
bool VideoCapturer::GetInputSize(int* width, int* height) {
|
||||
rtc::CritScope cs(&frame_stats_crit_);
|
||||
*last_captured_frame_format = last_captured_frame_format_;
|
||||
if (!input_size_valid_) {
|
||||
return false;
|
||||
}
|
||||
*width = input_width_;
|
||||
*height = input_height_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VideoCapturer::RemoveSink(
|
||||
@ -391,7 +397,7 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
|
||||
}
|
||||
|
||||
OnFrame(this, adapted_frame.get());
|
||||
UpdateStats(captured_frame);
|
||||
UpdateInputSize(captured_frame);
|
||||
}
|
||||
|
||||
void VideoCapturer::OnFrame(VideoCapturer* capturer, const VideoFrame* frame) {
|
||||
@ -536,15 +542,13 @@ bool VideoCapturer::ShouldFilterFormat(const VideoFormat& format) const {
|
||||
format.height > max_format_->height;
|
||||
}
|
||||
|
||||
void VideoCapturer::UpdateStats(const CapturedFrame* captured_frame) {
|
||||
void VideoCapturer::UpdateInputSize(const CapturedFrame* captured_frame) {
|
||||
// Update stats protected from fetches from different thread.
|
||||
rtc::CritScope cs(&frame_stats_crit_);
|
||||
|
||||
last_captured_frame_format_.width = captured_frame->width;
|
||||
last_captured_frame_format_.height = captured_frame->height;
|
||||
// TODO(ronghuawu): Useful to report interval as well?
|
||||
last_captured_frame_format_.interval = 0;
|
||||
last_captured_frame_format_.fourcc = captured_frame->fourcc;
|
||||
input_size_valid_ = true;
|
||||
input_width_ = captured_frame->width;
|
||||
input_height_ = captured_frame->height;
|
||||
}
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -209,9 +209,7 @@ class VideoCapturer : public sigslot::has_slots<>,
|
||||
// Takes ownership.
|
||||
void set_frame_factory(VideoFrameFactory* frame_factory);
|
||||
|
||||
// TODO(nisse): Rename function? Or pass the frame format before
|
||||
// adaptation in some other way.
|
||||
void GetStats(VideoFormat* last_captured_frame_format);
|
||||
bool GetInputSize(int* width, int* height);
|
||||
|
||||
// Implements VideoSourceInterface
|
||||
void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
|
||||
@ -275,7 +273,7 @@ class VideoCapturer : public sigslot::has_slots<>,
|
||||
// Returns true if format doesn't fulfill all applied restrictions.
|
||||
bool ShouldFilterFormat(const VideoFormat& format) const;
|
||||
|
||||
void UpdateStats(const CapturedFrame* captured_frame);
|
||||
void UpdateInputSize(const CapturedFrame* captured_frame);
|
||||
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
std::string id_;
|
||||
@ -298,9 +296,10 @@ class VideoCapturer : public sigslot::has_slots<>,
|
||||
CoordinatedVideoAdapter video_adapter_;
|
||||
|
||||
rtc::CriticalSection frame_stats_crit_;
|
||||
|
||||
// The captured frame format before potential adapation.
|
||||
VideoFormat last_captured_frame_format_;
|
||||
// The captured frame size before potential adapation.
|
||||
bool input_size_valid_ GUARDED_BY(frame_stats_crit_) = false;
|
||||
int input_width_ GUARDED_BY(frame_stats_crit_);
|
||||
int input_height_ GUARDED_BY(frame_stats_crit_);
|
||||
|
||||
// Whether capturer should apply rotation to the frame before signaling it.
|
||||
bool apply_rotation_;
|
||||
|
||||
@ -2089,13 +2089,6 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
|
||||
? CoordinatedVideoAdapter::ADAPTREASON_NONE
|
||||
: CoordinatedVideoAdapter::ADAPTREASON_CPU;
|
||||
|
||||
if (capturer_) {
|
||||
VideoFormat last_captured_frame_format;
|
||||
capturer_->GetStats(&last_captured_frame_format);
|
||||
info.input_frame_width = last_captured_frame_format.width;
|
||||
info.input_frame_height = last_captured_frame_format.height;
|
||||
}
|
||||
|
||||
// Get bandwidth limitation info from stream_->GetStats().
|
||||
// Input resolution (output from video_adapter) can be further scaled down or
|
||||
// higher video layer(s) can be dropped due to bitrate constraints.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user