blob: d4862e37483769bb66328967935e95fff7c2e0ef [file] [log] [blame]
Jon Hjelleca91e382016-01-21 15:36:47 -08001/*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
tkchin9eeb6242016-04-27 01:54:20 -070011#import "RTCVideoTrack+Private.h"
Jon Hjelleca91e382016-01-21 15:36:47 -080012
tkchin9eeb6242016-04-27 01:54:20 -070013#import "RTCMediaStreamTrack+Private.h"
14#import "RTCPeerConnectionFactory+Private.h"
tkchin9eeb6242016-04-27 01:54:20 -070015#import "RTCVideoSource+Private.h"
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020016#import "api/RTCVideoRendererAdapter+Private.h"
Artem Titov63ee39d2022-05-13 14:46:42 +000017#import "helpers/NSString+StdString.h"
Jon Hjelleca91e382016-01-21 15:36:47 -080018
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020019@implementation RTC_OBJC_TYPE (RTCVideoTrack) {
Byoungchan Lee2b46a582022-06-21 09:19:34 +090020 rtc::Thread *_workerThread;
21 NSMutableArray *_adapters /* accessed on _workerThread */;
Jon Hjelleca91e382016-01-21 15:36:47 -080022}
23
24@synthesize source = _source;
25
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020026- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
27 source:(RTC_OBJC_TYPE(RTCVideoSource) *)source
Jon Hjelleca91e382016-01-21 15:36:47 -080028 trackId:(NSString *)trackId {
29 NSParameterAssert(factory);
30 NSParameterAssert(source);
31 NSParameterAssert(trackId.length);
Artem Titov63ee39d2022-05-13 14:46:42 +000032 std::string nativeId = [NSString stdStringForString:trackId];
Jon Hjelleca91e382016-01-21 15:36:47 -080033 rtc::scoped_refptr<webrtc::VideoTrackInterface> track =
Niels Möller03486fc2022-04-25 10:46:59 +020034 factory.nativeFactory->CreateVideoTrack(nativeId, source.nativeVideoSource.get());
Yura Yaroshevich01cee072018-07-11 15:35:40 +030035 if (self = [self initWithFactory:factory nativeTrack:track type:RTCMediaStreamTrackTypeVideo]) {
hjona2f77982016-03-04 07:09:09 -080036 _source = source;
37 }
38 return self;
Jon Hjelleca91e382016-01-21 15:36:47 -080039}
40
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020041- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
Yura Yaroshevich01cee072018-07-11 15:35:40 +030042 nativeTrack:
43 (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)nativeMediaTrack
44 type:(RTCMediaStreamTrackType)type {
45 NSParameterAssert(factory);
Jon Hjelleca91e382016-01-21 15:36:47 -080046 NSParameterAssert(nativeMediaTrack);
47 NSParameterAssert(type == RTCMediaStreamTrackTypeVideo);
Yura Yaroshevich01cee072018-07-11 15:35:40 +030048 if (self = [super initWithFactory:factory nativeTrack:nativeMediaTrack type:type]) {
Jon Hjelleca91e382016-01-21 15:36:47 -080049 _adapters = [NSMutableArray array];
Byoungchan Lee2b46a582022-06-21 09:19:34 +090050 _workerThread = factory.workerThread;
Jon Hjelleca91e382016-01-21 15:36:47 -080051 }
52 return self;
53}
54
55- (void)dealloc {
56 for (RTCVideoRendererAdapter *adapter in _adapters) {
Niels Möller8f597622016-03-23 10:33:07 +010057 self.nativeVideoTrack->RemoveSink(adapter.nativeVideoRenderer);
Jon Hjelleca91e382016-01-21 15:36:47 -080058 }
59}
60
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020061- (RTC_OBJC_TYPE(RTCVideoSource) *)source {
hjona2f77982016-03-04 07:09:09 -080062 if (!_source) {
Niels Möllerac0d1832022-01-17 15:26:54 +010063 rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source(
64 self.nativeVideoTrack->GetSource());
hjona2f77982016-03-04 07:09:09 -080065 if (source) {
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020066 _source = [[RTC_OBJC_TYPE(RTCVideoSource) alloc] initWithFactory:self.factory
Niels Möllerac0d1832022-01-17 15:26:54 +010067 nativeVideoSource:source];
hjona2f77982016-03-04 07:09:09 -080068 }
69 }
70 return _source;
71}
72
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020073- (void)addRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
Byoungchan Lee2b46a582022-06-21 09:19:34 +090074 if (!_workerThread->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +020075 _workerThread->BlockingCall([renderer, self] { [self addRenderer:renderer]; });
Byoungchan Lee2b46a582022-06-21 09:19:34 +090076 return;
77 }
78
Jon Hjelleca91e382016-01-21 15:36:47 -080079 // Make sure we don't have this renderer yet.
80 for (RTCVideoRendererAdapter *adapter in _adapters) {
tkchin5fa51e22016-10-05 13:16:03 -070081 if (adapter.videoRenderer == renderer) {
Byoungchan Lee2b46a582022-06-21 09:19:34 +090082 RTC_LOG(LS_INFO) << "|renderer| is already attached to this track";
tkchin5fa51e22016-10-05 13:16:03 -070083 return;
Jon Hjelleca91e382016-01-21 15:36:47 -080084 }
85 }
86 // Create a wrapper that provides a native pointer for us.
87 RTCVideoRendererAdapter* adapter =
88 [[RTCVideoRendererAdapter alloc] initWithNativeRenderer:renderer];
89 [_adapters addObject:adapter];
Niels Möller8f597622016-03-23 10:33:07 +010090 self.nativeVideoTrack->AddOrUpdateSink(adapter.nativeVideoRenderer,
91 rtc::VideoSinkWants());
Jon Hjelleca91e382016-01-21 15:36:47 -080092}
93
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020094- (void)removeRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
Byoungchan Lee2b46a582022-06-21 09:19:34 +090095 if (!_workerThread->IsCurrent()) {
Danil Chapovalov9e09a1f2022-09-08 18:38:10 +020096 _workerThread->BlockingCall([renderer, self] { [self removeRenderer:renderer]; });
Byoungchan Lee2b46a582022-06-21 09:19:34 +090097 return;
98 }
Jon Hjelleca91e382016-01-21 15:36:47 -080099 __block NSUInteger indexToRemove = NSNotFound;
100 [_adapters enumerateObjectsUsingBlock:^(RTCVideoRendererAdapter *adapter,
101 NSUInteger idx,
102 BOOL *stop) {
103 if (adapter.videoRenderer == renderer) {
104 indexToRemove = idx;
105 *stop = YES;
106 }
107 }];
108 if (indexToRemove == NSNotFound) {
Byoungchan Lee2b46a582022-06-21 09:19:34 +0900109 RTC_LOG(LS_INFO) << "removeRenderer called with a renderer that has not been previously added";
Jon Hjelleca91e382016-01-21 15:36:47 -0800110 return;
111 }
hjona2f77982016-03-04 07:09:09 -0800112 RTCVideoRendererAdapter *adapterToRemove =
113 [_adapters objectAtIndex:indexToRemove];
Niels Möller8f597622016-03-23 10:33:07 +0100114 self.nativeVideoTrack->RemoveSink(adapterToRemove.nativeVideoRenderer);
Jon Hjelleca91e382016-01-21 15:36:47 -0800115 [_adapters removeObjectAtIndex:indexToRemove];
116}
117
118#pragma mark - Private
119
120- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)nativeVideoTrack {
Niels Möllerac0d1832022-01-17 15:26:54 +0100121 return rtc::scoped_refptr<webrtc::VideoTrackInterface>(
122 static_cast<webrtc::VideoTrackInterface *>(self.nativeTrack.get()));
Jon Hjelleca91e382016-01-21 15:36:47 -0800123}
124
125@end