Route min/max FPS constraints to VideoStreamEncoder.
This change - adds new type VideoTrackSourceConstraints expressing min/max FPS constraints. - adds new method VideoTrackSourceInterface::ProcessConstraints. - adds new method VideoSinkInterface<>::OnConstraintsChanged. - updates AdaptedVideoTrackSource and VideoBroadcaster to forward the constraints to sinks. - adds several unit tests for the added functionality. - and finally, implements OnConstraintsChanged in VideoStreamEncoder. Chromium will be updated in coming CLs to supply constraints set through the MediaStream module. go/rtc-0hz-present Bug: chromium:1255737 No-Try: true Change-Id: Iffef239217269c332a1aaa902ddeae2440929e22 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/235040 Commit-Queue: Markus Handell <handellm@webrtc.org> Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Reviewed-by: Henrik Andreassson <henrika@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35197}
This commit is contained in:
parent
8caac81390
commit
6fa9e68da9
@ -98,6 +98,12 @@ rtc_library("rtp_packet_info") {
|
|||||||
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("video_track_source_constraints") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
sources = [ "video_track_source_constraints.h" ]
|
||||||
|
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_library("media_stream_interface") {
|
rtc_library("media_stream_interface") {
|
||||||
visibility = [ "*" ]
|
visibility = [ "*" ]
|
||||||
sources = [
|
sources = [
|
||||||
@ -110,6 +116,7 @@ rtc_library("media_stream_interface") {
|
|||||||
":audio_options_api",
|
":audio_options_api",
|
||||||
":rtp_parameters",
|
":rtp_parameters",
|
||||||
":scoped_refptr",
|
":scoped_refptr",
|
||||||
|
":video_track_source_constraints",
|
||||||
"../modules/audio_processing:audio_processing_statistics",
|
"../modules/audio_processing:audio_processing_statistics",
|
||||||
"../rtc_base:checks",
|
"../rtc_base:checks",
|
||||||
"../rtc_base:refcount",
|
"../rtc_base:refcount",
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "api/video/video_frame.h"
|
#include "api/video/video_frame.h"
|
||||||
#include "api/video/video_sink_interface.h"
|
#include "api/video/video_sink_interface.h"
|
||||||
#include "api/video/video_source_interface.h"
|
#include "api/video/video_source_interface.h"
|
||||||
|
#include "api/video_track_source_constraints.h"
|
||||||
#include "modules/audio_processing/include/audio_processing_statistics.h"
|
#include "modules/audio_processing/include/audio_processing_statistics.h"
|
||||||
#include "rtc_base/ref_count.h"
|
#include "rtc_base/ref_count.h"
|
||||||
#include "rtc_base/system/rtc_export.h"
|
#include "rtc_base/system/rtc_export.h"
|
||||||
@ -146,8 +147,6 @@ class VideoTrackSourceInterface : public MediaSourceInterface,
|
|||||||
// Add an encoded video sink to the source and additionally cause
|
// Add an encoded video sink to the source and additionally cause
|
||||||
// a key frame to be generated from the source. The sink will be
|
// a key frame to be generated from the source. The sink will be
|
||||||
// invoked from a decoder queue.
|
// invoked from a decoder queue.
|
||||||
// TODO(bugs.webrtc.org/11114): make pure virtual once downstream project
|
|
||||||
// adapts.
|
|
||||||
virtual void AddEncodedSink(
|
virtual void AddEncodedSink(
|
||||||
rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0;
|
rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0;
|
||||||
|
|
||||||
@ -155,6 +154,13 @@ class VideoTrackSourceInterface : public MediaSourceInterface,
|
|||||||
virtual void RemoveEncodedSink(
|
virtual void RemoveEncodedSink(
|
||||||
rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0;
|
rtc::VideoSinkInterface<RecordableEncodedFrame>* sink) = 0;
|
||||||
|
|
||||||
|
// Notify about constraints set on the source. The information eventually gets
|
||||||
|
// routed to attached sinks via VideoSinkInterface<>::OnConstraintsChanged.
|
||||||
|
// The call is expected to happen on the network thread.
|
||||||
|
// TODO(crbug/1255737): make pure virtual once downstream project adapts.
|
||||||
|
virtual void ProcessConstraints(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~VideoTrackSourceInterface() override = default;
|
~VideoTrackSourceInterface() override = default;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -60,6 +60,7 @@ rtc_library("video_frame") {
|
|||||||
"..:array_view",
|
"..:array_view",
|
||||||
"..:rtp_packet_info",
|
"..:rtp_packet_info",
|
||||||
"..:scoped_refptr",
|
"..:scoped_refptr",
|
||||||
|
"..:video_track_source_constraints",
|
||||||
"../../rtc_base:checks",
|
"../../rtc_base:checks",
|
||||||
"../../rtc_base:rtc_base_approved",
|
"../../rtc_base:rtc_base_approved",
|
||||||
"../../rtc_base/memory:aligned_malloc",
|
"../../rtc_base/memory:aligned_malloc",
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#ifndef API_VIDEO_VIDEO_SINK_INTERFACE_H_
|
#ifndef API_VIDEO_VIDEO_SINK_INTERFACE_H_
|
||||||
#define API_VIDEO_VIDEO_SINK_INTERFACE_H_
|
#define API_VIDEO_VIDEO_SINK_INTERFACE_H_
|
||||||
|
|
||||||
|
#include "absl/types/optional.h"
|
||||||
|
#include "api/video_track_source_constraints.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
namespace rtc {
|
namespace rtc {
|
||||||
@ -25,6 +27,11 @@ class VideoSinkInterface {
|
|||||||
// Should be called by the source when it discards the frame due to rate
|
// Should be called by the source when it discards the frame due to rate
|
||||||
// limiting.
|
// limiting.
|
||||||
virtual void OnDiscardedFrame() {}
|
virtual void OnDiscardedFrame() {}
|
||||||
|
|
||||||
|
// Called on the network thread when video constraints change.
|
||||||
|
// TODO(crbug/1255737): make pure virtual once downstream project adapts.
|
||||||
|
virtual void OnConstraintsChanged(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|||||||
32
api/video_track_source_constraints.h
Normal file
32
api/video_track_source_constraints.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This file contains interfaces for MediaStream, MediaTrack and MediaSource.
|
||||||
|
// These interfaces are used for implementing MediaStream and MediaTrack as
|
||||||
|
// defined in http://dev.w3.org/2011/webrtc/editor/webrtc.html#stream-api. These
|
||||||
|
// interfaces must be used only with PeerConnection.
|
||||||
|
|
||||||
|
#ifndef API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_
|
||||||
|
#define API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_
|
||||||
|
|
||||||
|
#include "absl/types/optional.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This struct definition describes constraints on the video source that may be
|
||||||
|
// set with VideoTrackSourceInterface::ProcessConstraints.
|
||||||
|
struct VideoTrackSourceConstraints {
|
||||||
|
absl::optional<double> min_fps;
|
||||||
|
absl::optional<double> max_fps;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // API_VIDEO_TRACK_SOURCE_CONSTRAINTS_H_
|
||||||
@ -114,4 +114,9 @@ bool AdaptedVideoTrackSource::AdaptFrame(int width,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdaptedVideoTrackSource::ProcessConstraints(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) {
|
||||||
|
broadcaster_.ProcessConstraints(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|||||||
@ -86,6 +86,8 @@ class RTC_EXPORT AdaptedVideoTrackSource
|
|||||||
rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
|
rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
|
||||||
void RemoveEncodedSink(
|
void RemoveEncodedSink(
|
||||||
rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
|
rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame>* sink) override {}
|
||||||
|
void ProcessConstraints(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) override;
|
||||||
|
|
||||||
cricket::VideoAdapter video_adapter_;
|
cricket::VideoAdapter video_adapter_;
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,13 @@ void VideoBroadcaster::AddOrUpdateSink(
|
|||||||
if (!FindSinkPair(sink)) {
|
if (!FindSinkPair(sink)) {
|
||||||
// `Sink` is a new sink, which didn't receive previous frame.
|
// `Sink` is a new sink, which didn't receive previous frame.
|
||||||
previous_frame_sent_to_all_sinks_ = false;
|
previous_frame_sent_to_all_sinks_ = false;
|
||||||
|
|
||||||
|
if (last_constraints_.has_value()) {
|
||||||
|
RTC_LOG(LS_INFO) << __func__ << " forwarding stored constraints min_fps "
|
||||||
|
<< last_constraints_->min_fps.value_or(-1) << " max_fps "
|
||||||
|
<< last_constraints_->max_fps.value_or(-1);
|
||||||
|
sink->OnConstraintsChanged(*last_constraints_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
VideoSourceBase::AddOrUpdateSink(sink, wants);
|
VideoSourceBase::AddOrUpdateSink(sink, wants);
|
||||||
UpdateWants();
|
UpdateWants();
|
||||||
@ -100,6 +107,18 @@ void VideoBroadcaster::OnDiscardedFrame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoBroadcaster::ProcessConstraints(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) {
|
||||||
|
webrtc::MutexLock lock(&sinks_and_wants_lock_);
|
||||||
|
RTC_LOG(LS_INFO) << __func__ << " min_fps "
|
||||||
|
<< constraints.min_fps.value_or(-1) << " max_fps "
|
||||||
|
<< constraints.max_fps.value_or(-1) << " broadcasting to "
|
||||||
|
<< sink_pairs().size() << " sinks.";
|
||||||
|
last_constraints_ = constraints;
|
||||||
|
for (auto& sink_pair : sink_pairs())
|
||||||
|
sink_pair.sink->OnConstraintsChanged(constraints);
|
||||||
|
}
|
||||||
|
|
||||||
void VideoBroadcaster::UpdateWants() {
|
void VideoBroadcaster::UpdateWants() {
|
||||||
VideoSinkWants wants;
|
VideoSinkWants wants;
|
||||||
wants.rotation_applied = false;
|
wants.rotation_applied = false;
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#ifndef MEDIA_BASE_VIDEO_BROADCASTER_H_
|
#ifndef MEDIA_BASE_VIDEO_BROADCASTER_H_
|
||||||
#define MEDIA_BASE_VIDEO_BROADCASTER_H_
|
#define MEDIA_BASE_VIDEO_BROADCASTER_H_
|
||||||
|
|
||||||
|
#include "api/media_stream_interface.h"
|
||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "api/sequence_checker.h"
|
#include "api/sequence_checker.h"
|
||||||
#include "api/video/video_frame_buffer.h"
|
#include "api/video/video_frame_buffer.h"
|
||||||
@ -31,6 +32,11 @@ class VideoBroadcaster : public VideoSourceBase,
|
|||||||
public:
|
public:
|
||||||
VideoBroadcaster();
|
VideoBroadcaster();
|
||||||
~VideoBroadcaster() override;
|
~VideoBroadcaster() override;
|
||||||
|
|
||||||
|
// Adds a new, or updates an already existing sink. If the sink is new and
|
||||||
|
// ProcessConstraints has been called previously, the new sink's
|
||||||
|
// OnConstraintsCalled method will be invoked with the most recent
|
||||||
|
// constraints.
|
||||||
void AddOrUpdateSink(VideoSinkInterface<webrtc::VideoFrame>* sink,
|
void AddOrUpdateSink(VideoSinkInterface<webrtc::VideoFrame>* sink,
|
||||||
const VideoSinkWants& wants) override;
|
const VideoSinkWants& wants) override;
|
||||||
void RemoveSink(VideoSinkInterface<webrtc::VideoFrame>* sink) override;
|
void RemoveSink(VideoSinkInterface<webrtc::VideoFrame>* sink) override;
|
||||||
@ -50,6 +56,11 @@ class VideoBroadcaster : public VideoSourceBase,
|
|||||||
|
|
||||||
void OnDiscardedFrame() override;
|
void OnDiscardedFrame() override;
|
||||||
|
|
||||||
|
// Called on the network thread when constraints change. Forwards the
|
||||||
|
// constraints to sinks added with AddOrUpdateSink via OnConstraintsChanged.
|
||||||
|
void ProcessConstraints(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateWants() RTC_EXCLUSIVE_LOCKS_REQUIRED(sinks_and_wants_lock_);
|
void UpdateWants() RTC_EXCLUSIVE_LOCKS_REQUIRED(sinks_and_wants_lock_);
|
||||||
const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& GetBlackFrameBuffer(
|
const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& GetBlackFrameBuffer(
|
||||||
@ -62,6 +73,8 @@ class VideoBroadcaster : public VideoSourceBase,
|
|||||||
rtc::scoped_refptr<webrtc::VideoFrameBuffer> black_frame_buffer_;
|
rtc::scoped_refptr<webrtc::VideoFrameBuffer> black_frame_buffer_;
|
||||||
bool previous_frame_sent_to_all_sinks_ RTC_GUARDED_BY(sinks_and_wants_lock_) =
|
bool previous_frame_sent_to_all_sinks_ RTC_GUARDED_BY(sinks_and_wants_lock_) =
|
||||||
true;
|
true;
|
||||||
|
absl::optional<webrtc::VideoTrackSourceConstraints> last_constraints_
|
||||||
|
RTC_GUARDED_BY(sinks_and_wants_lock_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rtc
|
} // namespace rtc
|
||||||
|
|||||||
@ -16,13 +16,31 @@
|
|||||||
#include "api/video/i420_buffer.h"
|
#include "api/video/i420_buffer.h"
|
||||||
#include "api/video/video_frame.h"
|
#include "api/video/video_frame.h"
|
||||||
#include "api/video/video_rotation.h"
|
#include "api/video/video_rotation.h"
|
||||||
|
#include "api/video/video_source_interface.h"
|
||||||
#include "media/base/fake_video_renderer.h"
|
#include "media/base/fake_video_renderer.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
|
|
||||||
using cricket::FakeVideoRenderer;
|
using cricket::FakeVideoRenderer;
|
||||||
using rtc::VideoBroadcaster;
|
using rtc::VideoBroadcaster;
|
||||||
using rtc::VideoSinkWants;
|
using rtc::VideoSinkWants;
|
||||||
|
|
||||||
|
using ::testing::AllOf;
|
||||||
|
using ::testing::Eq;
|
||||||
|
using ::testing::Field;
|
||||||
|
using ::testing::Mock;
|
||||||
|
using ::testing::Optional;
|
||||||
|
|
||||||
|
class MockSink : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
|
||||||
|
public:
|
||||||
|
void OnFrame(const webrtc::VideoFrame&) override {}
|
||||||
|
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
OnConstraintsChanged,
|
||||||
|
(const webrtc::VideoTrackSourceConstraints& constraints),
|
||||||
|
(override));
|
||||||
|
};
|
||||||
|
|
||||||
TEST(VideoBroadcasterTest, frame_wanted) {
|
TEST(VideoBroadcasterTest, frame_wanted) {
|
||||||
VideoBroadcaster broadcaster;
|
VideoBroadcaster broadcaster;
|
||||||
EXPECT_FALSE(broadcaster.frame_wanted());
|
EXPECT_FALSE(broadcaster.frame_wanted());
|
||||||
@ -232,3 +250,83 @@ TEST(VideoBroadcasterTest, SinkWantsBlackFrames) {
|
|||||||
EXPECT_TRUE(sink2.black_frame());
|
EXPECT_TRUE(sink2.black_frame());
|
||||||
EXPECT_EQ(30, sink2.timestamp_us());
|
EXPECT_EQ(30, sink2.timestamp_us());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VideoBroadcasterTest, ConstraintsChangedNotCalledOnSinkAddition) {
|
||||||
|
MockSink sink;
|
||||||
|
VideoBroadcaster broadcaster;
|
||||||
|
EXPECT_CALL(sink, OnConstraintsChanged).Times(0);
|
||||||
|
broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoBroadcasterTest, ForwardsLastConstraintsOnAdd) {
|
||||||
|
MockSink sink;
|
||||||
|
VideoBroadcaster broadcaster;
|
||||||
|
broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{2, 3});
|
||||||
|
broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{1, 4});
|
||||||
|
EXPECT_CALL(
|
||||||
|
sink,
|
||||||
|
OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(1)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(4)))));
|
||||||
|
broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoBroadcasterTest, UpdatesOnlyNewSinksWithConstraints) {
|
||||||
|
MockSink sink1;
|
||||||
|
VideoBroadcaster broadcaster;
|
||||||
|
broadcaster.AddOrUpdateSink(&sink1, VideoSinkWants());
|
||||||
|
broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{1, 4});
|
||||||
|
Mock::VerifyAndClearExpectations(&sink1);
|
||||||
|
EXPECT_CALL(sink1, OnConstraintsChanged).Times(0);
|
||||||
|
MockSink sink2;
|
||||||
|
EXPECT_CALL(
|
||||||
|
sink2,
|
||||||
|
OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(1)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(4)))));
|
||||||
|
broadcaster.AddOrUpdateSink(&sink2, VideoSinkWants());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(VideoBroadcasterTest, ForwardsConstraintsToSink) {
|
||||||
|
MockSink sink;
|
||||||
|
VideoBroadcaster broadcaster;
|
||||||
|
EXPECT_CALL(sink, OnConstraintsChanged).Times(0);
|
||||||
|
broadcaster.AddOrUpdateSink(&sink, VideoSinkWants());
|
||||||
|
Mock::VerifyAndClearExpectations(&sink);
|
||||||
|
|
||||||
|
EXPECT_CALL(sink, OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps,
|
||||||
|
Eq(absl::nullopt)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps,
|
||||||
|
Eq(absl::nullopt)))));
|
||||||
|
broadcaster.ProcessConstraints(
|
||||||
|
webrtc::VideoTrackSourceConstraints{absl::nullopt, absl::nullopt});
|
||||||
|
Mock::VerifyAndClearExpectations(&sink);
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
sink,
|
||||||
|
OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps,
|
||||||
|
Eq(absl::nullopt)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(3)))));
|
||||||
|
broadcaster.ProcessConstraints(
|
||||||
|
webrtc::VideoTrackSourceConstraints{absl::nullopt, 3});
|
||||||
|
Mock::VerifyAndClearExpectations(&sink);
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
sink,
|
||||||
|
OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(2)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps,
|
||||||
|
Eq(absl::nullopt)))));
|
||||||
|
broadcaster.ProcessConstraints(
|
||||||
|
webrtc::VideoTrackSourceConstraints{2, absl::nullopt});
|
||||||
|
Mock::VerifyAndClearExpectations(&sink);
|
||||||
|
|
||||||
|
EXPECT_CALL(
|
||||||
|
sink,
|
||||||
|
OnConstraintsChanged(AllOf(
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::min_fps, Optional(2)),
|
||||||
|
Field(&webrtc::VideoTrackSourceConstraints::max_fps, Optional(3)))));
|
||||||
|
broadcaster.ProcessConstraints(webrtc::VideoTrackSourceConstraints{2, 3});
|
||||||
|
}
|
||||||
|
|||||||
@ -42,6 +42,9 @@ PROXY_SECONDARY_METHOD1(void,
|
|||||||
PROXY_SECONDARY_METHOD1(void,
|
PROXY_SECONDARY_METHOD1(void,
|
||||||
RemoveEncodedSink,
|
RemoveEncodedSink,
|
||||||
rtc::VideoSinkInterface<RecordableEncodedFrame>*)
|
rtc::VideoSinkInterface<RecordableEncodedFrame>*)
|
||||||
|
PROXY_SECONDARY_METHOD1(void,
|
||||||
|
ProcessConstraints,
|
||||||
|
const webrtc::VideoTrackSourceConstraints&)
|
||||||
END_PROXY_MAP(VideoTrackSource)
|
END_PROXY_MAP(VideoTrackSource)
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -1372,6 +1372,18 @@ void VideoStreamEncoder::OnDiscardedFrame() {
|
|||||||
VideoStreamEncoderObserver::DropReason::kSource);
|
VideoStreamEncoderObserver::DropReason::kSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoStreamEncoder::OnConstraintsChanged(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) {
|
||||||
|
// This method is called on the network thread.
|
||||||
|
RTC_LOG(LS_INFO) << __func__ << " min_fps "
|
||||||
|
<< constraints.min_fps.value_or(-1) << " max_fps "
|
||||||
|
<< constraints.max_fps.value_or(-1);
|
||||||
|
main_queue_->PostTask(ToQueuedTask(task_safety_, [this, constraints] {
|
||||||
|
RTC_DCHECK_RUN_ON(main_queue_);
|
||||||
|
source_constraints_ = constraints;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
bool VideoStreamEncoder::EncoderPaused() const {
|
bool VideoStreamEncoder::EncoderPaused() const {
|
||||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||||
// Pause video if paused by caller or as long as the network is down or the
|
// Pause video if paused by caller or as long as the network is down or the
|
||||||
|
|||||||
@ -176,6 +176,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
|||||||
// Implements VideoSinkInterface.
|
// Implements VideoSinkInterface.
|
||||||
void OnFrame(const VideoFrame& video_frame) override;
|
void OnFrame(const VideoFrame& video_frame) override;
|
||||||
void OnDiscardedFrame() override;
|
void OnDiscardedFrame() override;
|
||||||
|
void OnConstraintsChanged(
|
||||||
|
const webrtc::VideoTrackSourceConstraints& constraints) override;
|
||||||
|
|
||||||
void MaybeEncodeVideoFrame(const VideoFrame& frame,
|
void MaybeEncodeVideoFrame(const VideoFrame& frame,
|
||||||
int64_t time_when_posted_in_ms);
|
int64_t time_when_posted_in_ms);
|
||||||
@ -239,6 +241,10 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
|||||||
encoder_selector_;
|
encoder_selector_;
|
||||||
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
||||||
|
|
||||||
|
// The source's constraints.
|
||||||
|
absl::optional<VideoTrackSourceConstraints> source_constraints_
|
||||||
|
RTC_GUARDED_BY(main_queue_);
|
||||||
|
|
||||||
VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
|
VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
|
||||||
std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
|
std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
|
||||||
RTC_PT_GUARDED_BY(&encoder_queue_);
|
RTC_PT_GUARDED_BY(&encoder_queue_);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user