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  NSMutableArray *_adapters;
21}
22
23@synthesize source = _source;
24
25- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory
26                         source:(RTC_OBJC_TYPE(RTCVideoSource) *)source
27                        trackId:(NSString *)trackId {
28  NSParameterAssert(factory);
29  NSParameterAssert(source);
30  NSParameterAssert(trackId.length);
31  std::string nativeId = [NSString stdStringForString:trackId];
32  rtc::scoped_refptr<webrtc::VideoTrackInterface> track =
33      factory.nativeFactory->CreateVideoTrack(nativeId,
34                                              source.nativeVideoSource);
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  }
51  return self;
52}
53
54- (void)dealloc {
55  for (RTCVideoRendererAdapter *adapter in _adapters) {
56    self.nativeVideoTrack->RemoveSink(adapter.nativeVideoRenderer);
57  }
58}
59
60- (RTC_OBJC_TYPE(RTCVideoSource) *)source {
61  if (!_source) {
62    rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source =
63        self.nativeVideoTrack->GetSource();
64    if (source) {
65      _source = [[RTC_OBJC_TYPE(RTCVideoSource) alloc] initWithFactory:self.factory
66                                                     nativeVideoSource:source.get()];
67    }
68  }
69  return _source;
70}
71
72- (void)addRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
73  // Make sure we don't have this renderer yet.
74  for (RTCVideoRendererAdapter *adapter in _adapters) {
75    if (adapter.videoRenderer == renderer) {
76      NSAssert(NO, @"|renderer| is already attached to this track");
77      return;
78    }
79  }
80  // Create a wrapper that provides a native pointer for us.
81  RTCVideoRendererAdapter* adapter =
82      [[RTCVideoRendererAdapter alloc] initWithNativeRenderer:renderer];
83  [_adapters addObject:adapter];
84  self.nativeVideoTrack->AddOrUpdateSink(adapter.nativeVideoRenderer,
85                                         rtc::VideoSinkWants());
86}
87
88- (void)removeRenderer:(id<RTC_OBJC_TYPE(RTCVideoRenderer)>)renderer {
89  __block NSUInteger indexToRemove = NSNotFound;
90  [_adapters enumerateObjectsUsingBlock:^(RTCVideoRendererAdapter *adapter,
91                                          NSUInteger idx,
92                                          BOOL *stop) {
93    if (adapter.videoRenderer == renderer) {
94      indexToRemove = idx;
95      *stop = YES;
96    }
97  }];
98  if (indexToRemove == NSNotFound) {
99    return;
100  }
101  RTCVideoRendererAdapter *adapterToRemove =
102      [_adapters objectAtIndex:indexToRemove];
103  self.nativeVideoTrack->RemoveSink(adapterToRemove.nativeVideoRenderer);
104  [_adapters removeObjectAtIndex:indexToRemove];
105}
106
107#pragma mark - Private
108
109- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)nativeVideoTrack {
110  return static_cast<webrtc::VideoTrackInterface *>(self.nativeTrack.get());
111}
112
113@end
114