Skip to content

Commit 760a0e3

Browse files
authored
Fix screen-share memory leak (#174)
* fix: memory leak in VideoTrackDesktopSource * fix: memory leak in VideoTrackDesktopSource * fix: compile on Windows with clang-cl
1 parent a424be3 commit 760a0e3

File tree

3 files changed

+118
-12
lines changed

3 files changed

+118
-12
lines changed

webrtc-jni/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@
146146
</profile>
147147
<profile>
148148
<id>windows-clang</id>
149+
<activation>
150+
<os>
151+
<family>windows</family>
152+
<arch>amd64</arch>
153+
</os>
154+
</activation>
149155
<properties>
150156
<cmake.clang>-T ClangCL</cmake.clang>
151157
</properties>

webrtc-jni/src/main/cpp/include/media/video/VideoTrackDesktopSource.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818
#define JNI_WEBRTC_MEDIA_VIDEO_TRACK_DESKTOP_SOURCE_H_
1919

2020
#include "api/video/i420_buffer.h"
21-
#include "media/base/adapted_video_track_source.h"
21+
#include "api/video/video_frame.h"
22+
#include "api/video/video_sink_interface.h"
23+
#include "media/base/video_adapter.h"
24+
#include "media/base/video_broadcaster.h"
25+
#include "pc/video_track_source.h"
2226
#include "modules/desktop_capture/desktop_capturer.h"
2327
#include "rtc_base/thread.h"
2428

2529
namespace jni
2630
{
27-
class VideoTrackDesktopSource : public rtc::AdaptedVideoTrackSource, public webrtc::DesktopCapturer::Callback
31+
class VideoTrackDesktopSource : public webrtc::VideoTrackSource, public webrtc::DesktopCapturer::Callback
2832
{
2933
public:
3034
VideoTrackDesktopSource();
@@ -39,7 +43,16 @@ namespace jni
3943
void stop();
4044
void terminate();
4145

42-
// AdaptedVideoTrackSource implementation.
46+
// VideoSourceInterface implementation.
47+
void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink, const rtc::VideoSinkWants & wants) override;
48+
void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink) override;
49+
50+
// VideoTrackSource implementation.
51+
rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override;
52+
53+
// VideoTrackSourceInterface implementation.
54+
bool GetStats(webrtc::VideoTrackSourceInterface::Stats * stats) override;
55+
void ProcessConstraints(const webrtc::VideoTrackSourceConstraints & constraints) override;
4356
virtual bool is_screencast() const override;
4457
virtual std::optional<bool> needs_denoising() const override;
4558
SourceState state() const override;
@@ -48,9 +61,14 @@ namespace jni
4861
// DesktopCapturer::Callback implementation.
4962
void OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr<webrtc::DesktopFrame> frame) override;
5063

64+
protected:
65+
bool AdaptFrame(int width, int height, int64_t time_us, int* out_width, int* out_height, int* crop_width, int* crop_height, int* crop_x, int* crop_y);
66+
void OnFrameDropped();
67+
5168
private:
5269
void capture();
5370
void process(std::unique_ptr<webrtc::DesktopFrame> & frame);
71+
void updateVideoAdapter();
5472

5573
private:
5674
uint16_t frameRate;
@@ -59,6 +77,9 @@ namespace jni
5977

6078
webrtc::DesktopSize maxFrameSize;
6179

80+
rtc::VideoBroadcaster broadcaster;
81+
cricket::VideoAdapter videoAdapter;
82+
6283
webrtc::MediaSourceInterface::SourceState sourceState;
6384

6485
webrtc::DesktopCapturer::SourceId sourceId;
@@ -69,6 +90,9 @@ namespace jni
6990
std::unique_ptr<rtc::Thread> captureThread;
7091

7192
rtc::scoped_refptr<webrtc::I420Buffer> buffer;
93+
94+
webrtc::Mutex statsMutex;
95+
std::optional<Stats> stats RTC_GUARDED_BY(statsMutex);
7296
};
7397
}
7498

webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
namespace jni
3434
{
3535
VideoTrackDesktopSource::VideoTrackDesktopSource() :
36-
AdaptedVideoTrackSource(),
36+
VideoTrackSource(/*remote=*/false),
3737
frameRate(20),
3838
isCapturing(false),
3939
focusSelectedSource(true),
@@ -88,29 +88,104 @@ namespace jni
8888
}
8989
}
9090

91+
void VideoTrackDesktopSource::AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink, const rtc::VideoSinkWants& wants)
92+
{
93+
if (wants.is_active) {
94+
broadcaster.AddOrUpdateSink(sink, wants);
95+
96+
updateVideoAdapter();
97+
}
98+
}
99+
100+
void VideoTrackDesktopSource::RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink)
101+
{
102+
broadcaster.RemoveSink(sink);
103+
104+
updateVideoAdapter();
105+
}
106+
107+
void VideoTrackDesktopSource::updateVideoAdapter()
108+
{
109+
videoAdapter.OnSinkWants(broadcaster.wants());
110+
}
111+
112+
void VideoTrackDesktopSource::OnFrameDropped()
113+
{
114+
broadcaster.OnDiscardedFrame();
115+
}
116+
117+
rtc::VideoSourceInterface<webrtc::VideoFrame>* VideoTrackDesktopSource::source()
118+
{
119+
return this;
120+
}
121+
91122
void VideoTrackDesktopSource::terminate()
92123
{
93124
// Notify the track that we are permanently done.
94125
sourceState = kEnded;
95126
FireOnChanged();
96127
}
97128

98-
bool VideoTrackDesktopSource::is_screencast() const {
129+
bool VideoTrackDesktopSource::GetStats(webrtc::VideoTrackSourceInterface::Stats * stats)
130+
{
131+
webrtc::MutexLock lock(&statsMutex);
132+
133+
if (!stats) {
134+
return false;
135+
}
136+
137+
*stats = *stats;
138+
139+
return true;
140+
}
141+
142+
void VideoTrackDesktopSource::ProcessConstraints(const webrtc::VideoTrackSourceConstraints & constraints)
143+
{
144+
broadcaster.ProcessConstraints(constraints);
145+
}
146+
147+
bool VideoTrackDesktopSource::is_screencast() const
148+
{
99149
return true;
100150
}
101151

102-
std::optional<bool> VideoTrackDesktopSource::needs_denoising() const {
152+
std::optional<bool> VideoTrackDesktopSource::needs_denoising() const
153+
{
103154
return false;
104155
}
105156

106-
webrtc::MediaSourceInterface::SourceState VideoTrackDesktopSource::state() const {
157+
webrtc::MediaSourceInterface::SourceState VideoTrackDesktopSource::state() const
158+
{
107159
return sourceState;
108160
}
109161

110-
bool VideoTrackDesktopSource::remote() const {
162+
bool VideoTrackDesktopSource::remote() const
163+
{
111164
return false;
112165
}
113166

167+
bool VideoTrackDesktopSource::AdaptFrame(int width, int height, int64_t time_us, int* out_width, int* out_height, int* crop_width, int* crop_height, int* crop_x, int* crop_y)
168+
{
169+
{
170+
webrtc::MutexLock lock(&statsMutex);
171+
stats = Stats{ width, height };
172+
}
173+
174+
if (!broadcaster.frame_wanted()) {
175+
return false;
176+
}
177+
178+
if (!videoAdapter.AdaptFrameResolution(width, height, time_us * rtc::kNumNanosecsPerMicrosec, crop_width, crop_height, out_width, out_height)) {
179+
broadcaster.OnDiscardedFrame();
180+
return false;
181+
}
182+
183+
*crop_x = (width - *crop_width) / 2;
184+
*crop_y = (height - *crop_height) / 2;
185+
186+
return true;
187+
}
188+
114189
void VideoTrackDesktopSource::OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr<webrtc::DesktopFrame> frame)
115190
{
116191
if (result != webrtc::DesktopCapturer::Result::SUCCESS) {
@@ -149,8 +224,8 @@ namespace jni
149224
int width = frame->size().width();
150225
int height = frame->size().height();
151226

152-
int adapted_width;
153-
int adapted_height;
227+
int adapted_width = width;
228+
int adapted_height = height;
154229

155230
int crop_x = 0;
156231
int crop_y = 0;
@@ -216,18 +291,19 @@ namespace jni
216291

217292
scaled_buffer->ScaleFrom(*buffer);
218293

219-
OnFrame(webrtc::VideoFrame::Builder()
294+
broadcaster.OnFrame(webrtc::VideoFrame::Builder()
220295
.set_video_frame_buffer(scaled_buffer)
221296
.set_rotation(webrtc::kVideoRotation_0)
222297
.set_timestamp_us(time)
223298
.build());
224299
}
225300
else {
226301
// No adaptations needed, just return the frame as is.
227-
OnFrame(webrtc::VideoFrame::Builder()
302+
broadcaster.OnFrame(webrtc::VideoFrame::Builder()
228303
.set_video_frame_buffer(buffer)
229304
.set_rotation(webrtc::kVideoRotation_0)
230305
.set_timestamp_us(time)
306+
.set_timestamp_rtp(0)
231307
.build());
232308
}
233309
}

0 commit comments

Comments
 (0)