xref: /aosp_15_r20/external/webrtc/sdk/objc/api/peerconnection/RTCVideoTrack.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1/*
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
11#import "RTCVideoTrack+Private.h"
12
13#import "RTCMediaStreamTrack+Private.h"
14#import "RTCPeerConnectionFactory+Private.h"
15#import "RTCVideoSource+Private.h"
16#import "api/RTCVideoRendererAdapter+Private.h"
17#import "helpers/NSString+StdString.h"
18
19@implementation RTC_OBJC_TYPE (RTCVideoTrack) {
20  rtc::Thread *_workerThread;
21  NSMutableArray *_adapters /* accessed on _workerThread */;
22}
23
24@synthesize source = _source;
25
26- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
27                         source:(RTC_OBJC_TYPE(RTCVideoSource) *)source
28                        trackId:(NSString *)trackId {
29  NSParameterAssert(factory);
30  NSParameterAssert(source);
31  NSParameterAssert(trackId.length);
32  std::string nativeId = [NSString stdStringForString:trackId];
33  rtc::scoped_refptr<webrtc::VideoTrackInterface> track =
34      factory.nativeFactory->CreateVideoTrack(nativeId, source.nativeVideoSource.get());
35  if (self = [self initWithFactory:factory nativeTrack:track type:RTCMediaStreamTrackTypeVideo]) {
36    _source = source;
37  }
38  return self;
39}
40
41- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
42                    nativeTrack:
43                        (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)nativeMediaTrack
44                           type:(RTCMediaStreamTrackType)type {
45  NSParameterAssert(factory);
46  NSParameterAssert(nativeMediaTrack);
47  NSParameterAssert(type == RTCMediaStreamTrackTypeVideo);
48  if (self = [super initWithFactory:factory nativeTrack:nativeMediaTrack type:type]) {
49    _adapters = [NSMutableArray array];
50    _workerThread = factory.workerThread;
51  }
52  return self;
53}
54
55- (void)dealloc {
56  for (RTCVideoRendererAdapter *adapter in _adapters) {
57    self.nativeVideoTrack->RemoveSink(adapter.nativeVideoRenderer);
58  }
59}
60
61- (RTC_OBJC_TYPE(RTCVideoSource) *)source {
62  if (!_source) {
63    rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source(
64        self.nativeVideoTrack->GetSource());
65    if (source) {
66      _source = [[RTC_OBJC_TYPE(RTCVideoSource) alloc] initWithFactory:self.factory
67                                                     nativeVideoSource:source];
68    }
69  }
70  return _source;
71}
72
73- (void)addRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
74  if (!_workerThread->IsCurrent()) {
75    _workerThread->BlockingCall([renderer, self] { [self addRenderer:renderer]; });
76    return;
77  }
78
79  // Make sure we don't have this renderer yet.
80  for (RTCVideoRendererAdapter *adapter in _adapters) {
81    if (adapter.videoRenderer == renderer) {
82      RTC_LOG(LS_INFO) << "|renderer| is already attached to this track";
83      return;
84    }
85  }
86  // Create a wrapper that provides a native pointer for us.
87  RTCVideoRendererAdapter* adapter =
88      [[RTCVideoRendererAdapter alloc] initWithNativeRenderer:renderer];
89  [_adapters addObject:adapter];
90  self.nativeVideoTrack->AddOrUpdateSink(adapter.nativeVideoRenderer,
91                                         rtc::VideoSinkWants());
92}
93
94- (void)removeRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
95  if (!_workerThread->IsCurrent()) {
96    _workerThread->BlockingCall([renderer, self] { [self removeRenderer:renderer]; });
97    return;
98  }
99  __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) {
109    RTC_LOG(LS_INFO) << "removeRenderer called with a renderer that has not been previously added";
110    return;
111  }
112  RTCVideoRendererAdapter *adapterToRemove =
113      [_adapters objectAtIndex:indexToRemove];
114  self.nativeVideoTrack->RemoveSink(adapterToRemove.nativeVideoRenderer);
115  [_adapters removeObjectAtIndex:indexToRemove];
116}
117
118#pragma mark - Private
119
120- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)nativeVideoTrack {
121  return rtc::scoped_refptr<webrtc::VideoTrackInterface>(
122      static_cast<webrtc::VideoTrackInterface *>(self.nativeTrack.get()));
123}
124
125@end
126