├── LICENSE.md ├── README.md ├── nighthawk-webrtc.podspec └── patches ├── 0001-pooled-capture-pipeline.diff ├── 0002-enable-h264-videotoolbox.diff └── 0003-avaudiosession-mode-videochat.diff /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Christopher Eagleston 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nighthawk WebRTC 2 | ================ 3 | 4 | Custom iOS builds of Google's [Chromium WebRTC project](http://www.webrtc.org). 5 | 6 | ## Setup 7 | 8 | ### Cocoapods 9 | 10 | You can include a pre-built version of Nighthawk via Cocoapods. Only available directly for now. 11 | 12 | ``` 13 | pod 'nighthawk-webrtc', :git => 'https://github.com/ceaglest/nighthawk-webrtc.git' 14 | ``` 15 | 16 | ### Modifying WebRTC 17 | 18 | Patches are currently applied against Chrome 45. See [working with WebRTC release branches](http://www.webrtc.org/native-code/development#TOC-Working-with-Release-Branches) for a primer on how to prepare your working copy. 19 | 20 | TODO -------------------------------------------------------------------------------- /nighthawk-webrtc.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "nighthawk-webrtc" 4 | s.version = "45" 5 | s.platform = :ios, '7.0' 6 | s.summary = "Pre-compiled library for libWebRTC." 7 | 8 | s.homepage = "https://github.com/ceaglest/nighthawk-webrtc" 9 | s.author = { "Chris Eagleston" => "chris.eagleston@icloud.com" } 10 | 11 | s.source = { :http => "https://s3.amazonaws.com/perch-pods/webrtc-ios-chrome-m45-capture-xcode.zip" } 12 | 13 | s.source_files = "include/talk/app/webrtc/*.h", "include/talk/app/webrtc/objc/**/*.h", "include/third_party/libyuv/include/**/*.h", "include/webrtc/video_frame.h", "include/webrtc/typedefs.h", "include/webrtc/common_types.h", "include/webrtc/base/*.h", "include/webrtc/common_video/**/*.h", "include/webrtc/modules/interface/*.h", "include/webrtc/modules/video_capture/**/*.h", "include/webrtc/p2p/base/*.h", "include/webrtc/system_wrappers/interface/*.h", "include/webrtc/system_wrappers/source/*.h", "include/talk/media/base/*.h", "include/talk/media/webrtc/*.h", "include/talk/session/media/*.h", "include/talk/p2p/base/*.h", "include/talk/xmllite/*.h", "include/talk/media/devices/*.h" 14 | s.exclude_files = "include/talk/examples" 15 | 16 | s.requires_arc = true 17 | s.frameworks = 'QuartzCore', 'OpenGLES', 'GLKit', 'CoreAudio', 'CoreMedia', 'CoreVideo', 'AVFoundation', 'AudioToolbox', 'UIKit', 'Foundation', 'CoreGraphics', 'VideoToolbox' 18 | s.libraries = 'c', 'sqlite3', 'stdc++' 19 | s.vendored_libraries = "lib/libWebRTC-#{s.version}-1-arm-intel-Release.a" 20 | 21 | s.preserve_paths = 'include/talk/app/webrtc/objc/*', 'include/talk/app/webrtc/*', 'include/third_party/libyuv/include/*', "include/webrtc/video_frame.h", 'include/webrtc/typedefs.h', 'include/webrtc/common_types.h', 'include/webrtc/base/*', 'include/webrtc/common_video/*', 'include/webrtc/modules/interface/*', 'include/webrtc/modules/video_capture/*', 'include/webrtc/p2p/base/*.h', 'include/webrtc/system_wrappers/interface/*', 'include/webrtc/system_wrappers/source/*', 'include/talk/media/base/*', 'include/talk/media/webrtc/*', 'include/talk/session/media/*', 'include/talk/p2p/base/*', 'include/talk/xmllite/*', 'include/talk/media/devices/*', 'lib/*.a' 22 | 23 | s.xcconfig = { 24 | 'GCC_PREPROCESSOR_DEFINITIONS' => 'V8_DEPRECATION_WARNINGS EXPAT_RELATIVE_PATH FEATURE_ENABLE_VOICEMAIL JSONCPP_RELATIVE_PATH LOGGING=1 SRTP_RELATIVE_PATH FEATURE_ENABLE_SSL FEATURE_ENABLE_PSTN HAVE_SCTP HAVE_SRTP HAVE_WEBRTC_VIDEO HAVE_WEBRTC_VOICE DISABLE_NACL CHROMIUM_BUILD CR_CLANG_REVISION=239765-1 USE_LIBJPEG_TURBO=1 ENABLE_CONFIGURATION_POLICY SYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE DONT_EMBED_BUILD_METADATA CLD_VERSION=2 DISABLE_FTP_SUPPORT=1 V8_USE_EXTERNAL_STARTUP_DATA IOS WEBRTC_MAC WEBRTC_IOS CARBON_DEPRECATED=YES HASH_NAMESPACE=__gnu_cxx WEBRTC_POSIX DISABLE_DYNAMIC_CAST _REENTRANT USE_LIBPCI=1 USE_OPENSSL=1 NDEBUG NVALGRIND DYNAMIC_ANNOTATIONS_ENABLED=0', 25 | 'OTHER_LDFLAGS' => '-ObjC' 26 | } 27 | 28 | s.license = { 29 | :type => 'http://www.webrtc.org/license-rights/license', 30 | :text => <<-LICENSE 31 | Copyright (c) 2011, The WebRTC project authors. All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are 35 | met: 36 | 37 | * Redistributions of source code must retain the above copyright 38 | notice, this list of conditions and the following disclaimer. 39 | 40 | * Redistributions in binary form must reproduce the above copyright 41 | notice, this list of conditions and the following disclaimer in 42 | the documentation and/or other materials provided with the 43 | distribution. 44 | 45 | * Neither the name of Google nor the names of its contributors may 46 | be used to endorse or promote products derived from this software 47 | without specific prior written permission. 48 | 49 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 50 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 51 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 52 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 53 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 54 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 55 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 59 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 | LICENSE 61 | } 62 | 63 | 64 | end 65 | 66 | -------------------------------------------------------------------------------- /patches/0001-pooled-capture-pipeline.diff: -------------------------------------------------------------------------------- 1 | diff --git a/talk/media/base/videocapturer.cc b/talk/media/base/videocapturer.cc 2 | index 653e793..af00cba 100644 3 | --- a/talk/media/base/videocapturer.cc 4 | +++ b/talk/media/base/videocapturer.cc 5 | @@ -85,7 +85,8 @@ CapturedFrame::CapturedFrame() 6 | time_stamp(0), 7 | data_size(0), 8 | rotation(0), 9 | - data(NULL) {} 10 | + data(NULL), 11 | + nativeHandle(NULL) {} 12 | 13 | // TODO(fbarchard): Remove this function once lmimediaengine stops using it. 14 | bool CapturedFrame::GetDataSize(uint32* size) const { 15 | diff --git a/talk/media/base/videocapturer.h b/talk/media/base/videocapturer.h 16 | index ebd8d4a..5ae7073 100644 17 | --- a/talk/media/base/videocapturer.h 18 | +++ b/talk/media/base/videocapturer.h 19 | @@ -104,6 +104,8 @@ struct CapturedFrame { 20 | 21 | void* data; // pointer to the frame data. This object allocates the 22 | // memory or points to an existing memory. 23 | + void* nativeHandle; // pointer to a native texture handle. 24 | + 25 | 26 | private: 27 | DISALLOW_COPY_AND_ASSIGN(CapturedFrame); 28 | diff --git a/talk/media/webrtc/webrtcvideoframefactory.cc b/talk/media/webrtc/webrtcvideoframefactory.cc 29 | index b0c8d16..9a36189 100755 30 | --- a/talk/media/webrtc/webrtcvideoframefactory.cc 31 | +++ b/talk/media/webrtc/webrtcvideoframefactory.cc 32 | @@ -25,9 +25,10 @@ 33 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | -#include "talk/media/webrtc/webrtcvideoframe.h" 37 | #include "talk/media/webrtc/webrtcvideoframefactory.h" 38 | #include "webrtc/base/logging.h" 39 | +#include "libyuv/convert.h" 40 | +#include "talk/media/base/videocapturer.h" 41 | 42 | namespace cricket { 43 | 44 | @@ -42,4 +43,83 @@ VideoFrame* WebRtcVideoFrameFactory::CreateAliasedFrame( 45 | return frame.release(); 46 | } 47 | 48 | +WebRtcPooledVideoFrameFactory::~WebRtcPooledVideoFrameFactory() { 49 | + buffer_pool_.Release(); 50 | +} 51 | + 52 | +VideoFrame* WebRtcPooledVideoFrameFactory::CreateAliasedFrame( 53 | + const CapturedFrame* aliased_frame, 54 | + int width, 55 | + int height) const { 56 | + 57 | + VideoFrame *frame = nullptr; 58 | + 59 | + if (aliased_frame->nativeHandle) { 60 | + CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)aliased_frame->nativeHandle; 61 | + frame = this->CreateAliasedSampleBuffer(sampleBuffer); 62 | + } 63 | + else { 64 | + LOG(LS_ERROR) << "Failed to create WebRtcVideoFrame in CreateAliasedFrame."; 65 | + } 66 | + 67 | + return frame; 68 | +} 69 | + 70 | +WebRtcVideoFrame* WebRtcPooledVideoFrameFactory::CreateAliasedSampleBuffer(CMSampleBufferRef incomingBuffer) const 71 | +{ 72 | + CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(incomingBuffer); 73 | + 74 | + int width = CVPixelBufferGetWidth(pixelBuffer); 75 | + int height = CVPixelBufferGetHeight(pixelBuffer); 76 | + 77 | + rtc::scoped_refptr poolBuffer = buffer_pool_.CreateBuffer(width, height); 78 | + rtc::scoped_ptr poolFrame(new WebRtcVideoFrame(poolBuffer, 79 | + rtc::TimeNanos(), 80 | + 0, 81 | + webrtc::kVideoRotation_0)); 82 | + 83 | + // We have a buffer from the pool, fill it converting from the incoming buffer. 84 | + 85 | + CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); 86 | + 87 | + const int kYPlaneIndex = 0; 88 | + const int kUVPlaneIndex = 1; 89 | + 90 | + const uint8_t *baseAddress = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, kYPlaneIndex); 91 | + size_t yPlaneBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, kYPlaneIndex); 92 | + size_t uvPlaneBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, kUVPlaneIndex); 93 | + size_t uvPlaneHeight = CVPixelBufferGetHeightOfPlane(pixelBuffer, kUVPlaneIndex); 94 | + CMSampleTimingInfo info; 95 | + CMSampleBufferGetSampleTimingInfo(incomingBuffer, 0, &info); 96 | + int64 timestamp = CMTimeGetSeconds(info.presentationTimeStamp) * rtc::kNumNanosecsPerSec; 97 | + 98 | + // Format Conversion 99 | + 100 | + const uint8_t *uvAddress = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, kUVPlaneIndex); 101 | + size_t chromaWidth = CVPixelBufferGetWidthOfPlane(pixelBuffer, kUVPlaneIndex); 102 | + size_t ySize = (size_t)(width * height); 103 | + size_t uSize = (size_t)(chromaWidth * uvPlaneHeight); 104 | + 105 | + const webrtc::VideoFrameBuffer *poolBufferPtr = poolBuffer.get(); 106 | + 107 | + uint8 *yBuffer = (uint8 *)poolBufferPtr->data(webrtc::kYPlane); 108 | + uint8 *uBuffer = (uint8 *)poolBufferPtr->data(webrtc::kUPlane); 109 | + uint8 *vBuffer = (uint8 *)poolBufferPtr->data(webrtc::kVPlane); 110 | + 111 | + int yStride = poolBuffer->stride(webrtc::kYPlane); 112 | + int uStride = poolBuffer->stride(webrtc::kUPlane); 113 | + int vStride = poolBuffer->stride(webrtc::kVPlane); 114 | + 115 | + libyuv::NV12ToI420(baseAddress, (int)yPlaneBytesPerRow, 116 | + uvAddress, (int)uvPlaneBytesPerRow, 117 | + yBuffer, yStride, 118 | + uBuffer, uStride, 119 | + vBuffer, vStride, 120 | + width, height); 121 | + 122 | + CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); 123 | + 124 | + return poolFrame.release(); 125 | +} 126 | + 127 | } // namespace cricket 128 | diff --git a/talk/media/webrtc/webrtcvideoframefactory.h b/talk/media/webrtc/webrtcvideoframefactory.h 129 | index 5557a35..ce9990d 100644 130 | --- a/talk/media/webrtc/webrtcvideoframefactory.h 131 | +++ b/talk/media/webrtc/webrtcvideoframefactory.h 132 | @@ -29,6 +29,11 @@ 133 | #define TALK_MEDIA_WEBRTC_WEBRTCVIDEOFRAMEFACTORY_H_ 134 | 135 | #include "talk/media/base/videoframefactory.h" 136 | +#include "webrtc/common_video/interface/i420_buffer_pool.h" 137 | +#include "talk/media/webrtc/webrtcvideoframe.h" 138 | + 139 | +#import 140 | +#import 141 | 142 | namespace cricket { 143 | 144 | @@ -42,6 +47,20 @@ class WebRtcVideoFrameFactory : public VideoFrameFactory { 145 | int height) const override; 146 | }; 147 | 148 | +class WebRtcPooledVideoFrameFactory : public VideoFrameFactory { 149 | + public: 150 | + VideoFrame* CreateAliasedFrame(const CapturedFrame* aliased_frame, 151 | + int width, 152 | + int height) const override; 153 | +protected: 154 | + virtual ~WebRtcPooledVideoFrameFactory(); 155 | +private: 156 | + 157 | + WebRtcVideoFrame* CreateAliasedSampleBuffer(CMSampleBufferRef sampleBuffer) const; 158 | + 159 | + mutable webrtc::I420BufferPool buffer_pool_; 160 | +}; 161 | + 162 | } // namespace cricket 163 | 164 | #endif // TALK_MEDIA_WEBRTC_WEBRTCVIDEOFRAMEFACTORY_H_ 165 | -------------------------------------------------------------------------------- /patches/0002-enable-h264-videotoolbox.diff: -------------------------------------------------------------------------------- 1 | diff --git a/webrtc/build/common.gypi b/webrtc/build/common.gypi 2 | index 9335d35..e5205b0 100644 3 | --- a/webrtc/build/common.gypi 4 | +++ b/webrtc/build/common.gypi 5 | @@ -126,7 +126,7 @@ 6 | 7 | # Enable this to use HW H.264 encoder/decoder on iOS/Mac PeerConnections. 8 | # Enabling this may break interop with Android clients that support H264. 9 | - 'use_objc_h264%': 0, 10 | + 'use_objc_h264%': 1, 11 | 12 | 'conditions': [ 13 | ['build_with_chromium==1', { 14 | -------------------------------------------------------------------------------- /patches/0003-avaudiosession-mode-videochat.diff: -------------------------------------------------------------------------------- 1 | diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.mm b/webrtc/modules/audio_device/ios/audio_device_ios.mm 2 | index 47503a9..070afff 100644 3 | --- a/webrtc/modules/audio_device/ios/audio_device_ios.mm 4 | +++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm 5 | @@ -1193,8 +1193,8 @@ int32_t AudioDeviceIOS::InitPlayOrRecord() { 6 | // Non-obviously, setting them to the value they already have will clear 7 | // transient properties (such as PortOverride) that some other component may 8 | // have set up. 9 | - if (session.mode != AVAudioSessionModeVoiceChat) { 10 | - [session setMode:AVAudioSessionModeVoiceChat error:&error]; 11 | + if (session.mode != AVAudioSessionModeVideoChat) { 12 | + [session setMode:AVAudioSessionModeVideoChat error:&error]; 13 | if (error != nil) { 14 | const char* errorString = [[error localizedDescription] UTF8String]; 15 | WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, 16 | --------------------------------------------------------------------------------