Cleanup RTCVideoRenderer interface.
RTCVideoRenderer should be a protocol not a class. This change includes an adapter for use with the C++ apis. The video views have been refactored to implement that protocol. BUG=3795 R=glaznev@webrtc.org Review URL: https://webrtc-codereview.appspot.com/23279004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7626 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b8425bc4f3
commit
8125744a5f
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* libjingle
|
|
||||||
* Copyright 2014, Google Inc.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
||||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
||||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
||||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
||||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
#import "RTCEAGLVideoView.h"
|
|
||||||
#import "RTCVideoRenderer.h"
|
|
||||||
|
|
||||||
// TODO(tkchin): Move declaration to implementation file. Exposed here in order
|
|
||||||
// to support deprecated methods in RTCVideoRenderer.
|
|
||||||
@interface RTCEAGLVideoView (Internal) <RTCVideoRendererDelegate>
|
|
||||||
@end
|
|
@ -29,13 +29,12 @@
|
|||||||
#error "This file requires ARC support."
|
#error "This file requires ARC support."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#import "RTCEAGLVideoView+Internal.h"
|
#import "RTCEAGLVideoView.h"
|
||||||
|
|
||||||
#import <GLKit/GLKit.h>
|
#import <GLKit/GLKit.h>
|
||||||
|
|
||||||
|
#import "RTCI420Frame.h"
|
||||||
#import "RTCOpenGLVideoRenderer.h"
|
#import "RTCOpenGLVideoRenderer.h"
|
||||||
#import "RTCVideoRenderer.h"
|
|
||||||
#import "RTCVideoTrack.h"
|
|
||||||
|
|
||||||
// RTCDisplayLinkTimer wraps a CADisplayLink and is set to fire every two screen
|
// RTCDisplayLinkTimer wraps a CADisplayLink and is set to fire every two screen
|
||||||
// refreshes, which should be 30fps. We wrap the display link in order to avoid
|
// refreshes, which should be 30fps. We wrap the display link in order to avoid
|
||||||
@ -105,7 +104,6 @@
|
|||||||
RTCDisplayLinkTimer* _timer;
|
RTCDisplayLinkTimer* _timer;
|
||||||
GLKView* _glkView;
|
GLKView* _glkView;
|
||||||
RTCOpenGLVideoRenderer* _glRenderer;
|
RTCOpenGLVideoRenderer* _glRenderer;
|
||||||
RTCVideoRenderer* _videoRenderer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(CGRect)frame {
|
- (instancetype)initWithFrame:(CGRect)frame {
|
||||||
@ -152,7 +150,6 @@
|
|||||||
// GLKViewDelegate method implemented below.
|
// GLKViewDelegate method implemented below.
|
||||||
[strongSelf.glkView setNeedsDisplay];
|
[strongSelf.glkView setNeedsDisplay];
|
||||||
}];
|
}];
|
||||||
_videoRenderer = [[RTCVideoRenderer alloc] initWithDelegate:self];
|
|
||||||
[self setupGL];
|
[self setupGL];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@ -168,18 +165,6 @@
|
|||||||
[_timer invalidate];
|
[_timer invalidate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setVideoTrack:(RTCVideoTrack*)videoTrack {
|
|
||||||
if (_videoTrack == videoTrack) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
[_videoTrack removeRenderer:_videoRenderer];
|
|
||||||
self.i420Frame = nil;
|
|
||||||
_videoTrack = videoTrack;
|
|
||||||
[_videoTrack addRenderer:_videoRenderer];
|
|
||||||
// TODO(tkchin): potentially handle changes in track state - e.g. render
|
|
||||||
// black if track fails.
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - UIView
|
#pragma mark - UIView
|
||||||
|
|
||||||
- (void)layoutSubviews {
|
- (void)layoutSubviews {
|
||||||
@ -197,14 +182,31 @@
|
|||||||
[_glRenderer drawFrame:self.i420Frame];
|
[_glRenderer drawFrame:self.i420Frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - RTCVideoRenderer
|
||||||
|
|
||||||
|
// These methods may be called on non-main thread.
|
||||||
|
- (void)setSize:(CGSize)size {
|
||||||
|
__weak RTCEAGLVideoView* weakSelf = self;
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
RTCEAGLVideoView* strongSelf = weakSelf;
|
||||||
|
[strongSelf.delegate videoView:strongSelf didChangeVideoSize:size];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)renderFrame:(RTCI420Frame*)frame {
|
||||||
|
self.i420Frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Private
|
#pragma mark - Private
|
||||||
|
|
||||||
- (void)setupGL {
|
- (void)setupGL {
|
||||||
|
self.i420Frame = nil;
|
||||||
[_glRenderer setupGL];
|
[_glRenderer setupGL];
|
||||||
_timer.isPaused = NO;
|
_timer.isPaused = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)teardownGL {
|
- (void)teardownGL {
|
||||||
|
self.i420Frame = nil;
|
||||||
_timer.isPaused = YES;
|
_timer.isPaused = YES;
|
||||||
[_glkView deleteDrawable];
|
[_glkView deleteDrawable];
|
||||||
[_glRenderer teardownGL];
|
[_glRenderer teardownGL];
|
||||||
@ -219,25 +221,3 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation RTCEAGLVideoView (Internal)
|
|
||||||
|
|
||||||
#pragma mark - RTCVideoRendererDelegate
|
|
||||||
|
|
||||||
// These methods are called when the video track has frame information to
|
|
||||||
// provide. This occurs on non-main thread.
|
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer
|
|
||||||
didSetSize:(CGSize)size {
|
|
||||||
__weak RTCEAGLVideoView* weakSelf = self;
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
|
||||||
RTCEAGLVideoView* strongSelf = weakSelf;
|
|
||||||
[strongSelf.delegate videoView:strongSelf didChangeVideoSize:size];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer
|
|
||||||
didReceiveFrame:(RTCI420Frame*)frame {
|
|
||||||
self.i420Frame = frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
@ -78,6 +78,10 @@
|
|||||||
return _videoFrame->GetVPitch();
|
return _videoFrame->GetVPitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)makeExclusive {
|
||||||
|
return _videoFrame->MakeExclusive();
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation RTCI420Frame (Internal)
|
@implementation RTCI420Frame (Internal)
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)addVideoTrack:(RTCVideoTrack*)track {
|
- (BOOL)addVideoTrack:(RTCVideoTrack*)track {
|
||||||
if (self.mediaStream->AddTrack(track.videoTrack)) {
|
if (self.mediaStream->AddTrack(track.nativeVideoTrack)) {
|
||||||
[_videoTracks addObject:track];
|
[_videoTracks addObject:track];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@ -93,7 +93,8 @@
|
|||||||
NSUInteger index = [_videoTracks indexOfObjectIdenticalTo:track];
|
NSUInteger index = [_videoTracks indexOfObjectIdenticalTo:track];
|
||||||
NSAssert(index != NSNotFound,
|
NSAssert(index != NSNotFound,
|
||||||
@"|removeAudioTrack| called on unexpected RTCVideoTrack");
|
@"|removeAudioTrack| called on unexpected RTCVideoTrack");
|
||||||
if (index != NSNotFound && self.mediaStream->RemoveTrack(track.videoTrack)) {
|
if (index != NSNotFound &&
|
||||||
|
self.mediaStream->RemoveTrack(track.nativeVideoTrack)) {
|
||||||
[_videoTracks removeObjectAtIndex:index];
|
[_videoTracks removeObjectAtIndex:index];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,10 @@
|
|||||||
|
|
||||||
#import <CoreVideo/CVDisplayLink.h>
|
#import <CoreVideo/CVDisplayLink.h>
|
||||||
#import <OpenGL/gl3.h>
|
#import <OpenGL/gl3.h>
|
||||||
|
#import "RTCI420Frame.h"
|
||||||
#import "RTCOpenGLVideoRenderer.h"
|
#import "RTCOpenGLVideoRenderer.h"
|
||||||
#import "RTCVideoRenderer.h"
|
|
||||||
|
|
||||||
@interface RTCNSGLVideoView () <RTCVideoRendererDelegate>
|
@interface RTCNSGLVideoView ()
|
||||||
// |i420Frame| is set when we receive a frame from a worker thread and is read
|
// |i420Frame| is set when we receive a frame from a worker thread and is read
|
||||||
// from the display link callback so atomicity is required.
|
// from the display link callback so atomicity is required.
|
||||||
@property(atomic, strong) RTCI420Frame* i420Frame;
|
@property(atomic, strong) RTCI420Frame* i420Frame;
|
||||||
@ -57,15 +57,6 @@ static CVReturn OnDisplayLinkFired(CVDisplayLinkRef displayLink,
|
|||||||
|
|
||||||
@implementation RTCNSGLVideoView {
|
@implementation RTCNSGLVideoView {
|
||||||
CVDisplayLinkRef _displayLink;
|
CVDisplayLinkRef _displayLink;
|
||||||
RTCVideoRenderer* _videoRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (instancetype)initWithFrame:(NSRect)frame
|
|
||||||
pixelFormat:(NSOpenGLPixelFormat*)format {
|
|
||||||
if (self = [super initWithFrame:frame pixelFormat:format]) {
|
|
||||||
_videoRenderer = [[RTCVideoRenderer alloc] initWithDelegate:self];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
@ -109,37 +100,16 @@ static CVReturn OnDisplayLinkFired(CVDisplayLinkRef displayLink,
|
|||||||
[super clearGLContext];
|
[super clearGLContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setVideoTrack:(RTCVideoTrack*)videoTrack {
|
#pragma mark - RTCVideoRenderer
|
||||||
if (_videoTrack == videoTrack) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_videoTrack) {
|
|
||||||
[_videoTrack removeRenderer:_videoRenderer];
|
|
||||||
CVDisplayLinkStop(_displayLink);
|
|
||||||
// Clear contents.
|
|
||||||
self.i420Frame = nil;
|
|
||||||
[self drawFrame];
|
|
||||||
}
|
|
||||||
_videoTrack = videoTrack;
|
|
||||||
if (_videoTrack) {
|
|
||||||
[_videoTrack addRenderer:_videoRenderer];
|
|
||||||
CVDisplayLinkStart(_displayLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - RTCVideoRendererDelegate
|
// These methods may be called on non-main thread.
|
||||||
|
- (void)setSize:(CGSize)size {
|
||||||
// These methods are called when the video track has frame information to
|
|
||||||
// provide. This occurs on non-main thread.
|
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer
|
|
||||||
didSetSize:(CGSize)size {
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self.delegate videoView:self didChangeVideoSize:size];
|
[self.delegate videoView:self didChangeVideoSize:size];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer
|
- (void)renderFrame:(RTCI420Frame*)frame {
|
||||||
didReceiveFrame:(RTCI420Frame*)frame {
|
|
||||||
self.i420Frame = frame;
|
self.i420Frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,9 +144,7 @@ static CVReturn OnDisplayLinkFired(CVDisplayLinkRef displayLink,
|
|||||||
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
|
CGLPixelFormatObj cglPixelFormat = [[self pixelFormat] CGLPixelFormatObj];
|
||||||
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(
|
CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(
|
||||||
_displayLink, cglContext, cglPixelFormat);
|
_displayLink, cglContext, cglPixelFormat);
|
||||||
if (_videoTrack) {
|
CVDisplayLinkStart(_displayLink);
|
||||||
CVDisplayLinkStart(_displayLink);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)teardownDisplayLink {
|
- (void)teardownDisplayLink {
|
||||||
|
@ -29,8 +29,12 @@
|
|||||||
|
|
||||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||||
|
|
||||||
@interface RTCVideoRenderer (Internal)
|
@interface RTCVideoRendererAdapter : NSObject
|
||||||
|
|
||||||
@property(nonatomic, readonly) webrtc::VideoRendererInterface* videoRenderer;
|
@property(nonatomic, readonly) id<RTCVideoRenderer> videoRenderer;
|
||||||
|
@property(nonatomic, readonly)
|
||||||
|
webrtc::VideoRendererInterface* nativeVideoRenderer;
|
||||||
|
|
||||||
|
- (instancetype)initWithVideoRenderer:(id<RTCVideoRenderer>)videoRenderer;
|
||||||
|
|
||||||
@end
|
@end
|
@ -29,50 +29,46 @@
|
|||||||
#error "This file requires ARC support."
|
#error "This file requires ARC support."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#import "RTCVideoRenderer+Internal.h"
|
#import "RTCVideoRendererAdapter.h"
|
||||||
#import "RTCI420Frame+Internal.h"
|
#import "RTCI420Frame+Internal.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class RTCVideoRendererAdapter : public VideoRendererInterface {
|
class RTCVideoRendererNativeAdapter : public VideoRendererInterface {
|
||||||
public:
|
public:
|
||||||
RTCVideoRendererAdapter(RTCVideoRenderer* renderer) { _renderer = renderer; }
|
RTCVideoRendererNativeAdapter(RTCVideoRendererAdapter* adapter) {
|
||||||
|
_adapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void SetSize(int width, int height) OVERRIDE {
|
virtual void SetSize(int width, int height) OVERRIDE {
|
||||||
[_renderer.delegate renderer:_renderer
|
[_adapter.videoRenderer setSize:CGSizeMake(width, height)];
|
||||||
didSetSize:CGSizeMake(width, height)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
|
virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE {
|
||||||
if (!_renderer.delegate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RTCI420Frame* i420Frame = [[RTCI420Frame alloc] initWithVideoFrame:frame];
|
RTCI420Frame* i420Frame = [[RTCI420Frame alloc] initWithVideoFrame:frame];
|
||||||
[_renderer.delegate renderer:_renderer didReceiveFrame:i420Frame];
|
[_adapter.videoRenderer renderFrame:i420Frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
__weak RTCVideoRenderer* _renderer;
|
__weak RTCVideoRendererAdapter* _adapter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@implementation RTCVideoRenderer {
|
@implementation RTCVideoRendererAdapter {
|
||||||
rtc::scoped_ptr<webrtc::RTCVideoRendererAdapter> _adapter;
|
id<RTCVideoRenderer> _videoRenderer;
|
||||||
|
rtc::scoped_ptr<webrtc::RTCVideoRendererNativeAdapter> _adapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithDelegate:(id<RTCVideoRendererDelegate>)delegate {
|
- (instancetype)initWithVideoRenderer:(id<RTCVideoRenderer>)videoRenderer {
|
||||||
|
NSParameterAssert(videoRenderer);
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
_delegate = delegate;
|
_videoRenderer = videoRenderer;
|
||||||
_adapter.reset(new webrtc::RTCVideoRendererAdapter(self));
|
_adapter.reset(new webrtc::RTCVideoRendererNativeAdapter(self));
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
- (webrtc::VideoRendererInterface*)nativeVideoRenderer {
|
||||||
|
|
||||||
@implementation RTCVideoRenderer (Internal)
|
|
||||||
|
|
||||||
- (webrtc::VideoRendererInterface*)videoRenderer {
|
|
||||||
return _adapter.get();
|
return _adapter.get();
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
@interface RTCVideoTrack (Internal)
|
@interface RTCVideoTrack (Internal)
|
||||||
|
|
||||||
@property(nonatomic, assign, readonly)
|
@property(nonatomic, readonly)
|
||||||
rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack;
|
rtc::scoped_refptr<webrtc::VideoTrackInterface> nativeVideoTrack;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -32,46 +32,55 @@
|
|||||||
#import "RTCVideoTrack+Internal.h"
|
#import "RTCVideoTrack+Internal.h"
|
||||||
|
|
||||||
#import "RTCMediaStreamTrack+Internal.h"
|
#import "RTCMediaStreamTrack+Internal.h"
|
||||||
#import "RTCVideoRenderer+Internal.h"
|
#import "RTCVideoRendererAdapter.h"
|
||||||
|
|
||||||
@implementation RTCVideoTrack {
|
@implementation RTCVideoTrack {
|
||||||
NSMutableArray* _rendererArray;
|
NSMutableArray* _adapters;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithMediaTrack:
|
- (id)initWithMediaTrack:
|
||||||
(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)
|
(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)
|
||||||
mediaTrack {
|
mediaTrack {
|
||||||
if (self = [super initWithMediaTrack:mediaTrack]) {
|
if (self = [super initWithMediaTrack:mediaTrack]) {
|
||||||
_rendererArray = [NSMutableArray array];
|
_adapters = [NSMutableArray array];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)addRenderer:(RTCVideoRenderer*)renderer {
|
- (void)addRenderer:(id<RTCVideoRenderer>)renderer {
|
||||||
NSAssert1(![self.renderers containsObject:renderer],
|
// Make sure we don't have this renderer yet.
|
||||||
@"renderers already contains object [%@]",
|
for (RTCVideoRendererAdapter* adapter in _adapters) {
|
||||||
[renderer description]);
|
NSParameterAssert(adapter.videoRenderer != renderer);
|
||||||
[_rendererArray addObject:renderer];
|
|
||||||
self.videoTrack->AddRenderer(renderer.videoRenderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)removeRenderer:(RTCVideoRenderer*)renderer {
|
|
||||||
NSUInteger index = [self.renderers indexOfObjectIdenticalTo:renderer];
|
|
||||||
if (index != NSNotFound) {
|
|
||||||
[_rendererArray removeObjectAtIndex:index];
|
|
||||||
self.videoTrack->RemoveRenderer(renderer.videoRenderer);
|
|
||||||
}
|
}
|
||||||
|
// Create a wrapper that provides a native pointer for us.
|
||||||
|
RTCVideoRendererAdapter* adapter =
|
||||||
|
[[RTCVideoRendererAdapter alloc] initWithVideoRenderer:renderer];
|
||||||
|
[_adapters addObject:adapter];
|
||||||
|
self.nativeVideoTrack->AddRenderer(adapter.nativeVideoRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*)renderers {
|
- (void)removeRenderer:(id<RTCVideoRenderer>)renderer {
|
||||||
return [_rendererArray copy];
|
RTCVideoRendererAdapter* adapter = nil;
|
||||||
|
NSUInteger indexToRemove = NSNotFound;
|
||||||
|
for (NSUInteger i = 0; i < _adapters.count; i++) {
|
||||||
|
adapter = _adapters[i];
|
||||||
|
if (adapter.videoRenderer == renderer) {
|
||||||
|
indexToRemove = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indexToRemove == NSNotFound) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.nativeVideoTrack->RemoveRenderer(adapter.nativeVideoRenderer);
|
||||||
|
[_adapters removeObjectAtIndex:indexToRemove];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation RTCVideoTrack (Internal)
|
@implementation RTCVideoTrack (Internal)
|
||||||
|
|
||||||
- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)videoTrack {
|
- (rtc::scoped_refptr<webrtc::VideoTrackInterface>)nativeVideoTrack {
|
||||||
return static_cast<webrtc::VideoTrackInterface*>(self.mediaTrack.get());
|
return static_cast<webrtc::VideoTrackInterface*>(self.mediaTrack.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,11 +37,10 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@class RTCVideoTrack;
|
// RTCEAGLVideoView is an RTCVideoRenderer which renders i420 frames in its
|
||||||
// RTCEAGLVideoView renders |videoTrack| onto itself using OpenGLES.
|
// bounds using OpenGLES 2.0.
|
||||||
@interface RTCEAGLVideoView : UIView
|
@interface RTCEAGLVideoView : UIView <RTCVideoRenderer>
|
||||||
|
|
||||||
@property(nonatomic, strong) RTCVideoTrack* videoTrack;
|
|
||||||
@property(nonatomic, weak) id<RTCEAGLVideoViewDelegate> delegate;
|
@property(nonatomic, weak) id<RTCEAGLVideoViewDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
@property(nonatomic, readonly) NSInteger uPitch;
|
@property(nonatomic, readonly) NSInteger uPitch;
|
||||||
@property(nonatomic, readonly) NSInteger vPitch;
|
@property(nonatomic, readonly) NSInteger vPitch;
|
||||||
|
|
||||||
|
- (BOOL)makeExclusive;
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
// Disallow init and don't add to documentation
|
// Disallow init and don't add to documentation
|
||||||
- (id)init __attribute__((
|
- (id)init __attribute__((
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#import <AppKit/NSOpenGLView.h>
|
#import <AppKit/NSOpenGLView.h>
|
||||||
|
|
||||||
#import "RTCVideoTrack.h"
|
#import "RTCVideoRenderer.h"
|
||||||
|
|
||||||
@class RTCNSGLVideoView;
|
@class RTCNSGLVideoView;
|
||||||
@protocol RTCNSGLVideoViewDelegate
|
@protocol RTCNSGLVideoViewDelegate
|
||||||
@ -40,9 +40,8 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface RTCNSGLVideoView : NSOpenGLView
|
@interface RTCNSGLVideoView : NSOpenGLView <RTCVideoRenderer>
|
||||||
|
|
||||||
@property(nonatomic, strong) RTCVideoTrack* videoTrack;
|
|
||||||
@property(nonatomic, weak) id<RTCNSGLVideoViewDelegate> delegate;
|
@property(nonatomic, weak) id<RTCNSGLVideoViewDelegate> delegate;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -31,34 +31,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
@class RTCI420Frame;
|
@class RTCI420Frame;
|
||||||
@class RTCVideoRenderer;
|
|
||||||
|
|
||||||
// RTCVideoRendererDelegate is a protocol for an object that must be
|
@protocol RTCVideoRenderer<NSObject>
|
||||||
// implemented to get messages when rendering.
|
|
||||||
@protocol RTCVideoRendererDelegate<NSObject>
|
|
||||||
|
|
||||||
// The size of the frame.
|
// The size of the frame.
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer didSetSize:(CGSize)size;
|
- (void)setSize:(CGSize)size;
|
||||||
|
|
||||||
// The frame to be displayed.
|
// The frame to be displayed.
|
||||||
- (void)renderer:(RTCVideoRenderer*)renderer
|
- (void)renderFrame:(RTCI420Frame*)frame;
|
||||||
didReceiveFrame:(RTCI420Frame*)frame;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
// Interface for rendering VideoFrames from a VideoTrack
|
|
||||||
@interface RTCVideoRenderer : NSObject
|
|
||||||
|
|
||||||
@property(nonatomic, weak) id<RTCVideoRendererDelegate> delegate;
|
|
||||||
|
|
||||||
// Initialize the renderer. Requires a delegate which does the actual drawing
|
|
||||||
// of frames.
|
|
||||||
- (instancetype)initWithDelegate:(id<RTCVideoRendererDelegate>)delegate;
|
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
||||||
// Disallow init and don't add to documentation
|
|
||||||
- (id)init __attribute__((
|
|
||||||
unavailable("init is not a supported initializer for this class.")));
|
|
||||||
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -27,19 +27,16 @@
|
|||||||
|
|
||||||
#import "RTCMediaStreamTrack.h"
|
#import "RTCMediaStreamTrack.h"
|
||||||
|
|
||||||
@class RTCVideoRenderer;
|
@protocol RTCVideoRenderer;
|
||||||
|
|
||||||
// RTCVideoTrack is an ObjectiveC wrapper for VideoTrackInterface.
|
// RTCVideoTrack is an ObjectiveC wrapper for VideoTrackInterface.
|
||||||
@interface RTCVideoTrack : RTCMediaStreamTrack
|
@interface RTCVideoTrack : RTCMediaStreamTrack
|
||||||
|
|
||||||
// The currently registered renderers.
|
|
||||||
@property(nonatomic, strong, readonly) NSArray *renderers;
|
|
||||||
|
|
||||||
// Register a renderer that will render all frames received on this track.
|
// Register a renderer that will render all frames received on this track.
|
||||||
- (void)addRenderer:(RTCVideoRenderer *)renderer;
|
- (void)addRenderer:(id<RTCVideoRenderer>)renderer;
|
||||||
|
|
||||||
// Deregister a renderer.
|
// Deregister a renderer.
|
||||||
- (void)removeRenderer:(RTCVideoRenderer *)renderer;
|
- (void)removeRenderer:(id<RTCVideoRenderer>)renderer;
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
// Disallow init and don't add to documentation
|
// Disallow init and don't add to documentation
|
||||||
|
@ -46,6 +46,16 @@
|
|||||||
#error "This file requires ARC support."
|
#error "This file requires ARC support."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@interface RTCFakeRenderer : NSObject <RTCVideoRenderer>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation RTCFakeRenderer
|
||||||
|
|
||||||
|
- (void)setSize:(CGSize)size {}
|
||||||
|
- (void)renderFrame:(RTCI420Frame*)frame {}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface RTCPeerConnectionTest : NSObject
|
@interface RTCPeerConnectionTest : NSObject
|
||||||
|
|
||||||
// Returns whether the two sessions are of the same type.
|
// Returns whether the two sessions are of the same type.
|
||||||
@ -80,8 +90,7 @@
|
|||||||
RTCMediaStream* localMediaStream = [factory mediaStreamWithLabel:streamLabel];
|
RTCMediaStream* localMediaStream = [factory mediaStreamWithLabel:streamLabel];
|
||||||
RTCVideoTrack* videoTrack =
|
RTCVideoTrack* videoTrack =
|
||||||
[factory videoTrackWithID:videoTrackID source:videoSource];
|
[factory videoTrackWithID:videoTrackID source:videoSource];
|
||||||
RTCVideoRenderer* videoRenderer =
|
RTCFakeRenderer* videoRenderer = [[RTCFakeRenderer alloc] init];
|
||||||
[[RTCVideoRenderer alloc] initWithDelegate:nil];
|
|
||||||
[videoTrack addRenderer:videoRenderer];
|
[videoTrack addRenderer:videoRenderer];
|
||||||
[localMediaStream addVideoTrack:videoTrack];
|
[localMediaStream addVideoTrack:videoTrack];
|
||||||
// Test that removal/re-add works.
|
// Test that removal/re-add works.
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
#import "APPRTCConnectionManager.h"
|
#import "APPRTCConnectionManager.h"
|
||||||
#import "RTCEAGLVideoView.h"
|
#import "RTCEAGLVideoView.h"
|
||||||
|
#import "RTCVideoTrack.h"
|
||||||
|
|
||||||
// Padding space for local video view with its parent.
|
// Padding space for local video view with its parent.
|
||||||
static CGFloat const kLocalViewPadding = 20;
|
static CGFloat const kLocalViewPadding = 20;
|
||||||
@ -47,6 +48,8 @@ static CGFloat const kLocalViewPadding = 20;
|
|||||||
|
|
||||||
@implementation APPRTCViewController {
|
@implementation APPRTCViewController {
|
||||||
APPRTCConnectionManager* _connectionManager;
|
APPRTCConnectionManager* _connectionManager;
|
||||||
|
RTCVideoTrack* _localVideoTrack;
|
||||||
|
RTCVideoTrack* _remoteVideoTrack;
|
||||||
CGSize _localVideoSize;
|
CGSize _localVideoSize;
|
||||||
CGSize _remoteVideoSize;
|
CGSize _remoteVideoSize;
|
||||||
}
|
}
|
||||||
@ -101,13 +104,15 @@ static CGFloat const kLocalViewPadding = 20;
|
|||||||
|
|
||||||
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
||||||
didReceiveLocalVideoTrack:(RTCVideoTrack*)localVideoTrack {
|
didReceiveLocalVideoTrack:(RTCVideoTrack*)localVideoTrack {
|
||||||
|
_localVideoTrack = localVideoTrack;
|
||||||
|
[_localVideoTrack addRenderer:self.localVideoView];
|
||||||
self.localVideoView.hidden = NO;
|
self.localVideoView.hidden = NO;
|
||||||
self.localVideoView.videoTrack = localVideoTrack;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
||||||
didReceiveRemoteVideoTrack:(RTCVideoTrack*)remoteVideoTrack {
|
didReceiveRemoteVideoTrack:(RTCVideoTrack*)remoteVideoTrack {
|
||||||
self.remoteVideoView.videoTrack = remoteVideoTrack;
|
_remoteVideoTrack = remoteVideoTrack;
|
||||||
|
[_remoteVideoTrack addRenderer:self.remoteVideoView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionManagerDidReceiveHangup:(APPRTCConnectionManager*)manager {
|
- (void)connectionManagerDidReceiveHangup:(APPRTCConnectionManager*)manager {
|
||||||
@ -193,8 +198,16 @@ static CGFloat const kLocalViewPadding = 20;
|
|||||||
self.instructionsView.hidden = NO;
|
self.instructionsView.hidden = NO;
|
||||||
self.logView.hidden = YES;
|
self.logView.hidden = YES;
|
||||||
self.logView.text = nil;
|
self.logView.text = nil;
|
||||||
self.localVideoView.videoTrack = nil;
|
if (_localVideoTrack) {
|
||||||
self.remoteVideoView.videoTrack = nil;
|
[_localVideoTrack removeRenderer:self.localVideoView];
|
||||||
|
_localVideoTrack = nil;
|
||||||
|
[self.localVideoView renderFrame:nil];
|
||||||
|
}
|
||||||
|
if (_remoteVideoTrack) {
|
||||||
|
[_remoteVideoTrack removeRenderer:self.remoteVideoView];
|
||||||
|
_remoteVideoTrack = nil;
|
||||||
|
[self.remoteVideoView renderFrame:nil];
|
||||||
|
}
|
||||||
self.blackView.hidden = YES;
|
self.blackView.hidden = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
#import "APPRTCConnectionManager.h"
|
#import "APPRTCConnectionManager.h"
|
||||||
#import "RTCNSGLVideoView.h"
|
#import "RTCNSGLVideoView.h"
|
||||||
|
#import "RTCVideoTrack.h"
|
||||||
|
|
||||||
static NSUInteger const kContentWidth = 1280;
|
static NSUInteger const kContentWidth = 1280;
|
||||||
static NSUInteger const kContentHeight = 720;
|
static NSUInteger const kContentHeight = 720;
|
||||||
@ -227,6 +228,8 @@ static NSUInteger const kLogViewHeight = 280;
|
|||||||
|
|
||||||
@implementation APPRTCViewController {
|
@implementation APPRTCViewController {
|
||||||
APPRTCConnectionManager* _connectionManager;
|
APPRTCConnectionManager* _connectionManager;
|
||||||
|
RTCVideoTrack* _localVideoTrack;
|
||||||
|
RTCVideoTrack* _remoteVideoTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithNibName:(NSString*)nibName
|
- (instancetype)initWithNibName:(NSString*)nibName
|
||||||
@ -258,12 +261,13 @@ static NSUInteger const kLogViewHeight = 280;
|
|||||||
|
|
||||||
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
||||||
didReceiveLocalVideoTrack:(RTCVideoTrack*)localVideoTrack {
|
didReceiveLocalVideoTrack:(RTCVideoTrack*)localVideoTrack {
|
||||||
self.mainView.localVideoView.videoTrack = localVideoTrack;
|
_localVideoTrack = localVideoTrack;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
- (void)connectionManager:(APPRTCConnectionManager*)manager
|
||||||
didReceiveRemoteVideoTrack:(RTCVideoTrack*)remoteVideoTrack {
|
didReceiveRemoteVideoTrack:(RTCVideoTrack*)remoteVideoTrack {
|
||||||
self.mainView.remoteVideoView.videoTrack = remoteVideoTrack;
|
_remoteVideoTrack = remoteVideoTrack;
|
||||||
|
[_remoteVideoTrack addRenderer:self.mainView.remoteVideoView];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)connectionManagerDidReceiveHangup:(APPRTCConnectionManager*)manager {
|
- (void)connectionManagerDidReceiveHangup:(APPRTCConnectionManager*)manager {
|
||||||
@ -305,7 +309,9 @@ static NSUInteger const kLogViewHeight = 280;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)disconnect {
|
- (void)disconnect {
|
||||||
self.mainView.remoteVideoView.videoTrack = nil;
|
[_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView];
|
||||||
|
_remoteVideoTrack = nil;
|
||||||
|
[self.mainView.remoteVideoView renderFrame:nil];
|
||||||
[_connectionManager disconnect];
|
[_connectionManager disconnect];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,8 +204,8 @@
|
|||||||
'app/webrtc/objc/RTCStatsReport.mm',
|
'app/webrtc/objc/RTCStatsReport.mm',
|
||||||
'app/webrtc/objc/RTCVideoCapturer+Internal.h',
|
'app/webrtc/objc/RTCVideoCapturer+Internal.h',
|
||||||
'app/webrtc/objc/RTCVideoCapturer.mm',
|
'app/webrtc/objc/RTCVideoCapturer.mm',
|
||||||
'app/webrtc/objc/RTCVideoRenderer+Internal.h',
|
'app/webrtc/objc/RTCVideoRendererAdapter.h',
|
||||||
'app/webrtc/objc/RTCVideoRenderer.mm',
|
'app/webrtc/objc/RTCVideoRendererAdapter.mm',
|
||||||
'app/webrtc/objc/RTCVideoSource+Internal.h',
|
'app/webrtc/objc/RTCVideoSource+Internal.h',
|
||||||
'app/webrtc/objc/RTCVideoSource.mm',
|
'app/webrtc/objc/RTCVideoSource.mm',
|
||||||
'app/webrtc/objc/RTCVideoTrack+Internal.h',
|
'app/webrtc/objc/RTCVideoTrack+Internal.h',
|
||||||
@ -259,7 +259,6 @@
|
|||||||
'conditions': [
|
'conditions': [
|
||||||
['OS=="ios"', {
|
['OS=="ios"', {
|
||||||
'sources': [
|
'sources': [
|
||||||
'app/webrtc/objc/RTCEAGLVideoView+Internal.h',
|
|
||||||
'app/webrtc/objc/RTCEAGLVideoView.m',
|
'app/webrtc/objc/RTCEAGLVideoView.m',
|
||||||
'app/webrtc/objc/public/RTCEAGLVideoView.h',
|
'app/webrtc/objc/public/RTCEAGLVideoView.h',
|
||||||
],
|
],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user