xref: /aosp_15_r20/external/webrtc/sdk/objc/api/peerconnection/RTCVideoTrack.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker/*
2*d9f75844SAndroid Build Coastguard Worker *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker#import "RTCVideoTrack+Private.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker#import "RTCMediaStreamTrack+Private.h"
14*d9f75844SAndroid Build Coastguard Worker#import "RTCPeerConnectionFactory+Private.h"
15*d9f75844SAndroid Build Coastguard Worker#import "RTCVideoSource+Private.h"
16*d9f75844SAndroid Build Coastguard Worker#import "api/RTCVideoRendererAdapter+Private.h"
17*d9f75844SAndroid Build Coastguard Worker#import "helpers/NSString+StdString.h"
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCVideoTrack) {
20*d9f75844SAndroid Build Coastguard Worker  rtc::Thread *_workerThread;
21*d9f75844SAndroid Build Coastguard Worker  NSMutableArray *_adapters /* accessed on _workerThread */;
22*d9f75844SAndroid Build Coastguard Worker}
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker@synthesize source = _source;
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
27*d9f75844SAndroid Build Coastguard Worker                         source:(RTC_OBJC_TYPE(RTCVideoSource) *)source
28*d9f75844SAndroid Build Coastguard Worker                        trackId:(NSString *)trackId {
29*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(factory);
30*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(source);
31*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(trackId.length);
32*d9f75844SAndroid Build Coastguard Worker  std::string nativeId = [NSString stdStringForString:trackId];
33*d9f75844SAndroid Build Coastguard Worker  rtc::scoped_refptr<webrtc::VideoTrackInterface> track =
34*d9f75844SAndroid Build Coastguard Worker      factory.nativeFactory->CreateVideoTrack(nativeId, source.nativeVideoSource.get());
35*d9f75844SAndroid Build Coastguard Worker  if (self = [self initWithFactory:factory nativeTrack:track type:RTCMediaStreamTrackTypeVideo]) {
36*d9f75844SAndroid Build Coastguard Worker    _source = source;
37*d9f75844SAndroid Build Coastguard Worker  }
38*d9f75844SAndroid Build Coastguard Worker  return self;
39*d9f75844SAndroid Build Coastguard Worker}
40*d9f75844SAndroid Build Coastguard Worker
41*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
42*d9f75844SAndroid Build Coastguard Worker                    nativeTrack:
43*d9f75844SAndroid Build Coastguard Worker                        (rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)nativeMediaTrack
44*d9f75844SAndroid Build Coastguard Worker                           type:(RTCMediaStreamTrackType)type {
45*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(factory);
46*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(nativeMediaTrack);
47*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(type == RTCMediaStreamTrackTypeVideo);
48*d9f75844SAndroid Build Coastguard Worker  if (self = [super initWithFactory:factory nativeTrack:nativeMediaTrack type:type]) {
49*d9f75844SAndroid Build Coastguard Worker    _adapters = [NSMutableArray array];
50*d9f75844SAndroid Build Coastguard Worker    _workerThread = factory.workerThread;
51*d9f75844SAndroid Build Coastguard Worker  }
52*d9f75844SAndroid Build Coastguard Worker  return self;
53*d9f75844SAndroid Build Coastguard Worker}
54*d9f75844SAndroid Build Coastguard Worker
55*d9f75844SAndroid Build Coastguard Worker- (void)dealloc {
56*d9f75844SAndroid Build Coastguard Worker  for (RTCVideoRendererAdapter *adapter in _adapters) {
57*d9f75844SAndroid Build Coastguard Worker    self.nativeVideoTrack->RemoveSink(adapter.nativeVideoRenderer);
58*d9f75844SAndroid Build Coastguard Worker  }
59*d9f75844SAndroid Build Coastguard Worker}
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker- (RTC_OBJC_TYPE(RTCVideoSource) *)source {
62*d9f75844SAndroid Build Coastguard Worker  if (!_source) {
63*d9f75844SAndroid Build Coastguard Worker    rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source(
64*d9f75844SAndroid Build Coastguard Worker        self.nativeVideoTrack->GetSource());
65*d9f75844SAndroid Build Coastguard Worker    if (source) {
66*d9f75844SAndroid Build Coastguard Worker      _source = [[RTC_OBJC_TYPE(RTCVideoSource) alloc] initWithFactory:self.factory
67*d9f75844SAndroid Build Coastguard Worker                                                     nativeVideoSource:source];
68*d9f75844SAndroid Build Coastguard Worker    }
69*d9f75844SAndroid Build Coastguard Worker  }
70*d9f75844SAndroid Build Coastguard Worker  return _source;
71*d9f75844SAndroid Build Coastguard Worker}
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker- (void)addRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
74*d9f75844SAndroid Build Coastguard Worker  if (!_workerThread->IsCurrent()) {
75*d9f75844SAndroid Build Coastguard Worker    _workerThread->BlockingCall([renderer, self] { [self addRenderer:renderer]; });
76*d9f75844SAndroid Build Coastguard Worker    return;
77*d9f75844SAndroid Build Coastguard Worker  }
78*d9f75844SAndroid Build Coastguard Worker
79*d9f75844SAndroid Build Coastguard Worker  // Make sure we don't have this renderer yet.
80*d9f75844SAndroid Build Coastguard Worker  for (RTCVideoRendererAdapter *adapter in _adapters) {
81*d9f75844SAndroid Build Coastguard Worker    if (adapter.videoRenderer == renderer) {
82*d9f75844SAndroid Build Coastguard Worker      RTC_LOG(LS_INFO) << "|renderer| is already attached to this track";
83*d9f75844SAndroid Build Coastguard Worker      return;
84*d9f75844SAndroid Build Coastguard Worker    }
85*d9f75844SAndroid Build Coastguard Worker  }
86*d9f75844SAndroid Build Coastguard Worker  // Create a wrapper that provides a native pointer for us.
87*d9f75844SAndroid Build Coastguard Worker  RTCVideoRendererAdapter* adapter =
88*d9f75844SAndroid Build Coastguard Worker      [[RTCVideoRendererAdapter alloc] initWithNativeRenderer:renderer];
89*d9f75844SAndroid Build Coastguard Worker  [_adapters addObject:adapter];
90*d9f75844SAndroid Build Coastguard Worker  self.nativeVideoTrack->AddOrUpdateSink(adapter.nativeVideoRenderer,
91*d9f75844SAndroid Build Coastguard Worker                                         rtc::VideoSinkWants());
92*d9f75844SAndroid Build Coastguard Worker}
93*d9f75844SAndroid Build Coastguard Worker
94*d9f75844SAndroid Build Coastguard Worker- (void)removeRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
95*d9f75844SAndroid Build Coastguard Worker  if (!_workerThread->IsCurrent()) {
96*d9f75844SAndroid Build Coastguard Worker    _workerThread->BlockingCall([renderer, self] { [self removeRenderer:renderer]; });
97*d9f75844SAndroid Build Coastguard Worker    return;
98*d9f75844SAndroid Build Coastguard Worker  }
99*d9f75844SAndroid Build Coastguard Worker  __block NSUInteger indexToRemove = NSNotFound;
100*d9f75844SAndroid Build Coastguard Worker  [_adapters enumerateObjectsUsingBlock:^(RTCVideoRendererAdapter *adapter,
101*d9f75844SAndroid Build Coastguard Worker                                          NSUInteger idx,
102*d9f75844SAndroid Build Coastguard Worker                                          BOOL *stop) {
103*d9f75844SAndroid Build Coastguard Worker    if (adapter.videoRenderer == renderer) {
104*d9f75844SAndroid Build Coastguard Worker      indexToRemove = idx;
105*d9f75844SAndroid Build Coastguard Worker      *stop = YES;
106*d9f75844SAndroid Build Coastguard Worker    }
107*d9f75844SAndroid Build Coastguard Worker  }];
108*d9f75844SAndroid Build Coastguard Worker  if (indexToRemove == NSNotFound) {
109*d9f75844SAndroid Build Coastguard Worker    RTC_LOG(LS_INFO) << "removeRenderer called with a renderer that has not been previously added";
110*d9f75844SAndroid Build Coastguard Worker    return;
111*d9f75844SAndroid Build Coastguard Worker  }
112*d9f75844SAndroid Build Coastguard Worker  RTCVideoRendererAdapter *adapterToRemove =
113*d9f75844SAndroid Build Coastguard Worker      [_adapters objectAtIndex:indexToRemove];
114*d9f75844SAndroid Build Coastguard Worker  self.nativeVideoTrack->RemoveSink(adapterToRemove.nativeVideoRenderer);
115*d9f75844SAndroid Build Coastguard Worker  [_adapters removeObjectAtIndex:indexToRemove];
116*d9f75844SAndroid Build Coastguard Worker}
117*d9f75844SAndroid Build Coastguard Worker
118*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
119*d9f75844SAndroid Build Coastguard Worker
120*d9f75844SAndroid Build Coastguard Worker- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)nativeVideoTrack {
121*d9f75844SAndroid Build Coastguard Worker  return rtc::scoped_refptr<webrtc::VideoTrackInterface>(
122*d9f75844SAndroid Build Coastguard Worker      static_cast<webrtc::VideoTrackInterface *>(self.nativeTrack.get()));
123*d9f75844SAndroid Build Coastguard Worker}
124*d9f75844SAndroid Build Coastguard Worker
125*d9f75844SAndroid Build Coastguard Worker@end
126