Reland of Injectable Obj-C video codecs (patchset #1 id:1 of https://codereview.webrtc.org/2980173002/ )

Reason for revert:
Relanding after fixing issues with no video.

Original issue's description:
> Revert of Injectable Obj-C video codecs (patchset #2 id:370001 of https://codereview.webrtc.org/2979983002/ )
>
> Reason for revert:
> Still having problems with no video. Reverting.
> Once no video is visible, no video is available from then on even if the callee app is in the foreground.
>
>
> Original issue's description:
> > Reland of Injectable Obj-C video codecs (patchset #1 id:1 of https://codereview.webrtc.org/2979973002/ )
> >
> > Reason for revert:
> > Fix the broken build file
> >
> > Original issue's description:
> > > Revert of Injectable Obj-C video codecs (patchset #3 id:400001 of https://codereview.webrtc.org/2981583002/ )
> > >
> > > Reason for revert:
> > > Breaks bots. Build file incorrect.
> > >
> > > Original issue's description:
> > > > Reland of Injectable Obj-C video codecs (patchset #1 id:1 of https://codereview.webrtc.org/2975963002/ )
> > > >
> > > > Reason for revert:
> > > > New CL for fixing the issues
> > > >
> > > > Original issue's description:
> > > > > Revert of Injectable Obj-C video codecs (patchset #8 id:140001 of https://codereview.webrtc.org/2966023002/ )
> > > > >
> > > > > Reason for revert:
> > > > > Causes no video in certain scenarios. Please come up with a test plan or unit test to prevent such problems in the future.
> > > > >
> > > > > Original issue's description:
> > > > > > Injectable Obj-C video codecs
> > > > > >
> > > > > > Initial CL for this effort, with a working RTCVideoEncoder/Decoder for H264
> > > > > > (wrapping the VideoToolbox codec).
> > > > > >
> > > > > > Some notes / things left to do:
> > > > > >   - There are some hard-coded references to codec types that are supported by
> > > > > >     webrtc::VideoCodec, cricket::VideoCodec, webrtc::CodecSpecificInfo etc
> > > > > >     since we need to convert to/from these types in ObjCVideoEncoder/Decoder.
> > > > > >     These types would need to be more codec agnostic to avoid this.
> > > > > >   - Most interfaces are borrowed from the design document for injectable
> > > > > >     codecs in Android. Some data in the corresponding C++ classes is discarded
> > > > > >     when converting to the Obj-C version, since it has fewer fields. I have not
> > > > > >     verified whether all data that we do keep is needed, or whether we might be
> > > > > >     losing anything useful in these conversions.
> > > > > >   - Implement the VideoToolbox codec code directly in the RTCVideoEncoderH264
> > > > > >     classes, instead of wrapping webrtc::H264VideoToolboxEncoder / decoder.
> > > > > >     Eliminates converting between ObjC/C++ types outside the ObjCVideoEncoder/
> > > > > >     Decoder wrapper classes.
> > > > > >   - List the injected codec factory's supported codecs in the list of codecs in
> > > > > >     AppRTCMobile.
> > > > > >
> > > > > > BUG=webrtc:7924
> > > > > > R=magjed@webrtc.org
> > > > > >
> > > > > > Review-Url: https://codereview.webrtc.org/2966023002 .
> > > > > > Cr-Commit-Position: refs/heads/master@{#18928}
> > > > > > Committed: a0349c138d
> > > > >
> > > > > TBR=magjed@webrtc.org,andersc@webrtc.org
> > > > > # Not skipping CQ checks because original CL landed more than 1 days ago.
> > > > > BUG=webrtc:7924
> > > > > NOTRY=true
> > > > >
> > > > > Review-Url: https://codereview.webrtc.org/2975963002
> > > > > Cr-Commit-Position: refs/heads/master@{#18979}
> > > > > Committed: 1095ada7ad
> > > >
> > > > R=magjed@webrtc.org
> > > > TBR=tkchin@webrtc.org
> > > > # Skipping CQ checks because original CL landed less than 1 days ago.
> > > > NOPRESUBMIT=true
> > > > NOTREECHECKS=true
> > > > NOTRY=true
> > > > BUG=webrtc:7924
> > > >
> > > > Review-Url: https://codereview.webrtc.org/2981583002 .
> > > > Cr-Commit-Position: refs/heads/master@{#19002}
> > > > Committed: a5f1de1e65
> > >
> > > TBR=magjed@webrtc.org,tkchin@webrtc.org,jtteh@webrtc.org,andersc@webrtc.org
> > > # Skipping CQ checks because original CL landed less than 1 days ago.
> > > NOPRESUBMIT=true
> > > NOTREECHECKS=true
> > > NOTRY=true
> > > BUG=webrtc:7924
> > >
> > > Review-Url: https://codereview.webrtc.org/2979973002
> > > Cr-Commit-Position: refs/heads/master@{#19004}
> > > Committed: 81d40ee149
> >
> > TBR=magjed@webrtc.org,tkchin@webrtc.org,jtteh@webrtc.org,sprang@webrtc.org
> > BUG=webrtc:7924
> >
> > Review-Url: https://codereview.webrtc.org/2979983002
> > Cr-Commit-Position: refs/heads/master@{#19005}
> > Committed: 732a3437da
>
> TBR=magjed@webrtc.org,tkchin@webrtc.org,sprang@webrtc.org,haysc@webrtc.org,andersc@webrtc.org
> # Not skipping CQ checks because original CL landed more than 1 days ago.
> BUG=webrtc:7924
>
> Review-Url: https://codereview.webrtc.org/2980173002
> Cr-Commit-Position: refs/heads/master@{#19036}
> Committed: 860f729816

TBR=magjed@webrtc.org,tkchin@webrtc.org,sprang@webrtc.org,haysc@webrtc.org,andersc@webrtc.org,jtteh@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:7924

Review-Url: https://codereview.webrtc.org/2977213002
Cr-Commit-Position: refs/heads/master@{#19135}
This commit is contained in:
kthelgason
2017-07-25 07:55:58 -07:00
committed by Commit Bot
parent 83377270dc
commit fb143127d7
24 changed files with 1506 additions and 173 deletions

View File

@ -0,0 +1,74 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodec.h"
#import "RTCVideoCodec+Private.h"
@implementation RTCEncodedImage
@synthesize buffer = _buffer;
@synthesize encodedWidth = _encodedWidth;
@synthesize encodedHeight = _encodedHeight;
@synthesize timeStamp = _timeStamp;
@synthesize captureTimeMs = _captureTimeMs;
@synthesize ntpTimeMs = _ntpTimeMs;
@synthesize isTimingFrame = _isTimingFrame;
@synthesize encodeStartMs = _encodeStartMs;
@synthesize encodeFinishMs = _encodeFinishMs;
@synthesize frameType = _frameType;
@synthesize rotation = _rotation;
@synthesize completeFrame = _completeFrame;
@synthesize qp = _qp;
- (instancetype)initWithNativeEncodedImage:(webrtc::EncodedImage)encodedImage {
if (self = [super init]) {
// Wrap the buffer in NSData without copying, do not take ownership.
_buffer = [NSData dataWithBytesNoCopy:encodedImage._buffer
length:encodedImage._length
freeWhenDone:NO];
_encodedWidth = encodedImage._encodedWidth;
_encodedHeight = encodedImage._encodedHeight;
_timeStamp = encodedImage._timeStamp;
_captureTimeMs = encodedImage.capture_time_ms_;
_ntpTimeMs = encodedImage.ntp_time_ms_;
_isTimingFrame = encodedImage.timing_.is_timing_frame;
_encodeStartMs = encodedImage.timing_.encode_start_ms;
_encodeFinishMs = encodedImage.timing_.encode_finish_ms;
_frameType = (RTCFrameType)encodedImage._frameType;
_rotation = encodedImage.rotation_;
_completeFrame = encodedImage._completeFrame;
_qp = encodedImage.qp_ == -1 ? nil : @(encodedImage.qp_);
}
return self;
}
- (webrtc::EncodedImage)toCpp {
// Return the pointer without copying.
webrtc::EncodedImage encodedImage(
(uint8_t *)_buffer.bytes, (size_t)_buffer.length, (size_t)_buffer.length);
encodedImage._encodedWidth = _encodedWidth;
encodedImage._encodedHeight = _encodedHeight;
encodedImage._timeStamp = _timeStamp;
encodedImage.capture_time_ms_ = _captureTimeMs;
encodedImage.ntp_time_ms_ = _ntpTimeMs;
encodedImage.timing_.is_timing_frame = _isTimingFrame;
encodedImage.timing_.encode_start_ms = _encodeStartMs;
encodedImage.timing_.encode_finish_ms = _encodeFinishMs;
encodedImage._frameType = webrtc::FrameType(_frameType);
encodedImage.rotation_ = webrtc::VideoRotation(_rotation);
encodedImage._completeFrame = _completeFrame;
encodedImage.qp_ = _qp ? _qp.intValue : -1;
return encodedImage;
}
@end

View File

@ -11,6 +11,7 @@
#import "RTCPeerConnectionFactory+Private.h"
#import "NSString+StdString.h"
#import "RTCAVFoundationVideoSource+Private.h"
#import "RTCAudioSource+Private.h"
#import "RTCAudioTrack+Private.h"
#import "RTCMediaConstraints+Private.h"
@ -18,11 +19,15 @@
#import "RTCPeerConnection+Private.h"
#import "RTCVideoSource+Private.h"
#import "RTCVideoTrack+Private.h"
#import "RTCAVFoundationVideoSource+Private.h"
#import "WebRTC/RTCLogging.h"
#import "WebRTC/RTCVideoCodecFactory.h"
#ifndef HAVE_NO_MEDIA
#import "WebRTC/RTCVideoCodecH264.h"
#endif
#include "Video/objcvideotracksource.h"
#include "VideoToolbox/videocodecfactory.h"
#include "VideoToolbox/objc_video_decoder_factory.h"
#include "VideoToolbox/objc_video_encoder_factory.h"
#include "webrtc/api/videosourceproxy.h"
// Adding the nogncheck to disable the including header check.
// The no-media version PeerConnectionFactory doesn't depend on media related
@ -41,7 +46,17 @@
@synthesize nativeFactory = _nativeFactory;
- (instancetype)init {
if ((self = [super init])) {
#ifdef HAVE_NO_MEDIA
return [self initWithEncoderFactory:nil decoderFactory:nil];
#else
return [self initWithEncoderFactory:[[RTCVideoEncoderFactoryH264 alloc] init]
decoderFactory:[[RTCVideoDecoderFactoryH264 alloc] init]];
#endif
}
- (instancetype)initWithEncoderFactory:(nullable id<RTCVideoEncoderFactory>)encoderFactory
decoderFactory:(nullable id<RTCVideoDecoderFactory>)decoderFactory {
if (self = [super init]) {
_networkThread = rtc::Thread::CreateWithSocketServer();
BOOL result = _networkThread->Start();
NSAssert(result, @"Failed to start network thread.");
@ -68,14 +83,23 @@
std::unique_ptr<webrtc::CallFactoryInterface>(),
std::unique_ptr<webrtc::RtcEventLogFactoryInterface>());
#else
const auto encoder_factory = new webrtc::VideoToolboxVideoEncoderFactory();
const auto decoder_factory = new webrtc::VideoToolboxVideoDecoderFactory();
cricket::WebRtcVideoEncoderFactory *platform_encoder_factory = nullptr;
cricket::WebRtcVideoDecoderFactory *platform_decoder_factory = nullptr;
if (encoderFactory) {
platform_encoder_factory = new webrtc::ObjCVideoEncoderFactory(encoderFactory);
}
if (decoderFactory) {
platform_decoder_factory = new webrtc::ObjCVideoDecoderFactory(decoderFactory);
}
// Ownership of encoder/decoder factories is passed on to the
// peerconnectionfactory, that handles deleting them.
_nativeFactory = webrtc::CreatePeerConnectionFactory(
_networkThread.get(), _workerThread.get(), _signalingThread.get(),
nullptr, encoder_factory, decoder_factory);
_nativeFactory = webrtc::CreatePeerConnectionFactory(_networkThread.get(),
_workerThread.get(),
_signalingThread.get(),
nullptr,
platform_encoder_factory,
platform_decoder_factory);
#endif
NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!");
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodec.h"
#include "webrtc/modules/include/module_common_types.h"
@implementation RTCRtpFragmentationHeader
@synthesize fragmentationOffset = _fragmentationOffset;
@synthesize fragmentationLength = _fragmentationLength;
@synthesize fragmentationTimeDiff = _fragmentationTimeDiff;
@synthesize fragmentationPlType = _fragmentationPlType;
- (instancetype)initWithFragmentationHeader:
(const webrtc::RTPFragmentationHeader *)fragmentationHeader {
if (self = [super init]) {
if (fragmentationHeader) {
int count = fragmentationHeader->fragmentationVectorSize;
NSMutableArray *offsets = [NSMutableArray array];
NSMutableArray *lengths = [NSMutableArray array];
NSMutableArray *timeDiffs = [NSMutableArray array];
NSMutableArray *plTypes = [NSMutableArray array];
for (int i = 0; i < count; ++i) {
[offsets addObject:@(fragmentationHeader->fragmentationOffset[i])];
[lengths addObject:@(fragmentationHeader->fragmentationLength[i])];
[timeDiffs addObject:@(fragmentationHeader->fragmentationTimeDiff[i])];
[plTypes addObject:@(fragmentationHeader->fragmentationPlType[i])];
}
_fragmentationOffset = [offsets copy];
_fragmentationLength = [lengths copy];
_fragmentationTimeDiff = [timeDiffs copy];
_fragmentationPlType = [plTypes copy];
}
}
return self;
}
- (std::unique_ptr<webrtc::RTPFragmentationHeader>)toCpp {
auto fragmentationHeader =
std::unique_ptr<webrtc::RTPFragmentationHeader>(new webrtc::RTPFragmentationHeader);
fragmentationHeader->VerifyAndAllocateFragmentationHeader(_fragmentationOffset.count);
for (NSUInteger i = 0; i < _fragmentationOffset.count; ++i) {
fragmentationHeader->fragmentationOffset[i] = (size_t)_fragmentationOffset[i].unsignedIntValue;
fragmentationHeader->fragmentationLength[i] = (size_t)_fragmentationLength[i].unsignedIntValue;
fragmentationHeader->fragmentationTimeDiff[i] =
(uint16_t)_fragmentationOffset[i].unsignedIntValue;
fragmentationHeader->fragmentationPlType[i] = (uint8_t)_fragmentationOffset[i].unsignedIntValue;
}
return fragmentationHeader;
}
@end

View File

@ -0,0 +1,57 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodec.h"
#import "WebRTC/RTCVideoCodecH264.h"
#include "webrtc/common_video/include/video_frame.h"
#include "webrtc/media/base/codec.h"
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
NS_ASSUME_NONNULL_BEGIN
/* Interfaces for converting to/from internal C++ formats. */
@interface RTCEncodedImage ()
- (instancetype)initWithNativeEncodedImage:(webrtc::EncodedImage)encodedImage;
- (webrtc::EncodedImage)toCpp;
@end
@interface RTCVideoEncoderSettings ()
- (instancetype)initWithVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec;
- (std::unique_ptr<webrtc::VideoCodec>)toCpp;
@end
@interface RTCCodecSpecificInfoH264 ()
- (webrtc::CodecSpecificInfo)toCpp;
@end
@interface RTCRtpFragmentationHeader ()
- (instancetype)initWithFragmentationHeader:
(const webrtc::RTPFragmentationHeader *__nullable)fragmentationHeader;
- (std::unique_ptr<webrtc::RTPFragmentationHeader>)toCpp;
@end
@interface RTCVideoCodecInfo ()
- (instancetype)initWithVideoCodec:(cricket::VideoCodec)videoCodec;
- (cricket::VideoCodec)toCpp;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,56 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodec.h"
#import "NSString+StdString.h"
#import "RTCVideoCodec+Private.h"
#import "WebRTC/RTCVideoCodecFactory.h"
@implementation RTCVideoCodecInfo
@synthesize payload = _payload;
@synthesize name = _name;
@synthesize parameters = _parameters;
- (instancetype)initWithPayload:(NSInteger)payload
name:(NSString *)name
parameters:(NSDictionary<NSString *, NSString *> *)parameters {
if (self = [super init]) {
_payload = payload;
_name = name;
_parameters = parameters;
}
return self;
}
- (instancetype)initWithVideoCodec:(cricket::VideoCodec)videoCodec {
NSMutableDictionary *params = [NSMutableDictionary dictionary];
for (auto it = videoCodec.params.begin(); it != videoCodec.params.end(); ++it) {
[params setObject:[NSString stringForStdString:it->second]
forKey:[NSString stringForStdString:it->first]];
}
return [self initWithPayload:videoCodec.id
name:[NSString stringForStdString:videoCodec.name]
parameters:params];
}
- (cricket::VideoCodec)toCpp {
cricket::VideoCodec codec([NSString stdStringForString:_name]);
for (NSString *paramKey in _parameters.allKeys) {
codec.SetParam([NSString stdStringForString:paramKey],
[NSString stdStringForString:_parameters[paramKey]]);
}
return codec;
}
@end

View File

@ -0,0 +1,293 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodecH264.h"
#include <vector>
#import "RTCVideoCodec+Private.h"
#import "WebRTC/RTCVideoCodec.h"
#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
#include "webrtc/rtc_base/timeutils.h"
#include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h"
#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/encoder.h"
#include "webrtc/system_wrappers/include/field_trial.h"
const size_t kDefaultPayloadSize = 1440;
const char kHighProfileExperiment[] = "WebRTC-H264HighProfile";
bool IsHighProfileEnabled() {
return webrtc::field_trial::IsEnabled(kHighProfileExperiment);
}
// H264 specific settings.
@implementation RTCCodecSpecificInfoH264
@synthesize packetizationMode = _packetizationMode;
- (webrtc::CodecSpecificInfo)toCpp {
webrtc::CodecSpecificInfo codecSpecificInfo;
codecSpecificInfo.codecType = webrtc::kVideoCodecH264;
codecSpecificInfo.codec_name = "H264";
codecSpecificInfo.codecSpecific.H264.packetization_mode =
(webrtc::H264PacketizationMode)_packetizationMode;
return codecSpecificInfo;
}
@end
namespace {
class H264VideoToolboxEncodeCompleteCallback : public webrtc::EncodedImageCallback {
public:
Result OnEncodedImage(const webrtc::EncodedImage &encoded_image,
const webrtc::CodecSpecificInfo *codec_specific_info,
const webrtc::RTPFragmentationHeader *fragmentation) {
RTCEncodedImage *image = [[RTCEncodedImage alloc] initWithNativeEncodedImage:encoded_image];
RTCCodecSpecificInfoH264 *info = [[RTCCodecSpecificInfoH264 alloc] init];
info.packetizationMode =
(RTCH264PacketizationMode)codec_specific_info->codecSpecific.H264.packetization_mode;
RTCRtpFragmentationHeader *header =
[[RTCRtpFragmentationHeader alloc] initWithFragmentationHeader:fragmentation];
callback(image, info, header);
return Result(Result::OK, 0);
}
RTCVideoEncoderCallback callback;
};
class H264VideoToolboxDecodeCompleteCallback : public webrtc::DecodedImageCallback {
public:
int32_t Decoded(webrtc::VideoFrame &decodedImage) {
rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer =
decodedImage.video_frame_buffer();
id<RTCVideoFrameBuffer> rtcFrameBuffer;
rtc::scoped_refptr<webrtc::ObjCFrameBuffer> objc_frame_buffer(
static_cast<webrtc::ObjCFrameBuffer *>(video_frame_buffer.get()));
rtcFrameBuffer = (id<RTCVideoFrameBuffer>)objc_frame_buffer->wrapped_frame_buffer();
RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc]
initWithBuffer:rtcFrameBuffer
rotation:static_cast<RTCVideoRotation>(decodedImage.rotation())
timeStampNs:decodedImage.timestamp_us() * rtc::kNumNanosecsPerMicrosec];
videoFrame.timeStamp = decodedImage.timestamp();
callback(videoFrame);
return 0;
}
RTCVideoDecoderCallback callback;
};
} // namespace
// Encoder.
@implementation RTCVideoEncoderH264 {
webrtc::H264VideoToolboxEncoder *_videoToolboxEncoder;
H264VideoToolboxEncodeCompleteCallback *_toolboxCallback;
}
- (instancetype)initWithCodecInfo:(RTCVideoCodecInfo *)codecInfo {
if (self = [super init]) {
cricket::VideoCodec codec = [codecInfo toCpp];
_videoToolboxEncoder = new webrtc::H264VideoToolboxEncoder(codec);
}
return self;
}
- (void)setCallback:(RTCVideoEncoderCallback)callback {
if (!_toolboxCallback) _toolboxCallback = new H264VideoToolboxEncodeCompleteCallback();
_toolboxCallback->callback = callback;
_videoToolboxEncoder->RegisterEncodeCompleteCallback(_toolboxCallback);
}
- (void)destroy {
delete _videoToolboxEncoder;
_videoToolboxEncoder = nullptr;
delete _toolboxCallback;
_toolboxCallback = nullptr;
}
-(void)dealloc {
// Make sure C++ objects have been properly cleaned up before this
// is dealloc'd.
RTC_DCHECK(!_videoToolboxEncoder);
RTC_DCHECK(!_toolboxCallback);
}
- (NSInteger)startEncodeWithSettings:(RTCVideoEncoderSettings *)settings
numberOfCores:(int)numberOfCores {
std::unique_ptr<webrtc::VideoCodec> codecSettings = [settings toCpp];
return _videoToolboxEncoder->InitEncode(
codecSettings.release(), numberOfCores, kDefaultPayloadSize);
}
- (NSInteger)releaseEncoder {
return _videoToolboxEncoder->Release();
}
- (NSInteger)encode:(RTCVideoFrame *)frame
codecSpecificInfo:(id<RTCCodecSpecificInfo>)info
frameTypes:(NSArray<NSNumber *> *)frameTypes {
rtc::scoped_refptr<webrtc::VideoFrameBuffer> frameBuffer =
new rtc::RefCountedObject<webrtc::ObjCFrameBuffer>(frame.buffer);
webrtc::VideoFrame videoFrame(frameBuffer,
(webrtc::VideoRotation)frame.rotation,
frame.timeStampNs / rtc::kNumNanosecsPerMicrosec);
videoFrame.set_timestamp(frame.timeStamp);
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
webrtc::CodecSpecificInfo codecSpecificInfo;
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info toCpp];
}
std::vector<webrtc::FrameType> nativeFrameTypes;
for (NSNumber *frameType in frameTypes) {
RTCFrameType rtcFrameType = (RTCFrameType)frameType.unsignedIntegerValue;
nativeFrameTypes.push_back((webrtc::FrameType)rtcFrameType);
}
return _videoToolboxEncoder->Encode(videoFrame, &codecSpecificInfo, &nativeFrameTypes);
}
- (BOOL)setBitrate:(uint32_t)bitrateKbit framerate:(uint32_t)framerate {
return _videoToolboxEncoder->SetRates(bitrateKbit, framerate) == WEBRTC_VIDEO_CODEC_OK;
}
@end
// Decoder.
@implementation RTCVideoDecoderH264 {
webrtc::H264VideoToolboxDecoder *_videoToolboxDecoder;
H264VideoToolboxDecodeCompleteCallback *_toolboxCallback;
}
- (instancetype)init {
if (self = [super init]) {
cricket::VideoCodec codec(cricket::kH264CodecName);
_videoToolboxDecoder = new webrtc::H264VideoToolboxDecoder();
}
return self;
}
- (NSInteger)startDecodeWithSettings:(RTCVideoEncoderSettings *)settings
numberOfCores:(int)numberOfCores {
std::unique_ptr<webrtc::VideoCodec> codecSettings = [settings toCpp];
return _videoToolboxDecoder->InitDecode(codecSettings.release(), numberOfCores);
}
- (void)setCallback:(RTCVideoDecoderCallback)callback {
if (!_toolboxCallback) _toolboxCallback = new H264VideoToolboxDecodeCompleteCallback();
_toolboxCallback->callback = callback;
_videoToolboxDecoder->RegisterDecodeCompleteCallback(_toolboxCallback);
}
- (NSInteger)releaseDecoder {
return _videoToolboxDecoder->Release();
}
- (void)destroy {
delete _videoToolboxDecoder;
_videoToolboxDecoder = nullptr;
delete _toolboxCallback;
_toolboxCallback = nullptr;
}
-(void)dealloc {
// Make sure C++ objects have been properly cleaned up before this
// is dealloc'd.
RTC_DCHECK(!_videoToolboxDecoder);
RTC_DCHECK(!_toolboxCallback);
}
- (NSInteger)decode:(RTCEncodedImage *)encodedImage
missingFrames:(BOOL)missingFrames
fragmentationHeader:(RTCRtpFragmentationHeader *)fragmentationHeader
codecSpecificInfo:(__nullable id<RTCCodecSpecificInfo>)info
renderTimeMs:(int64_t)renderTimeMs {
webrtc::EncodedImage image = [encodedImage toCpp];
// Handle types than can be converted into one of webrtc::CodecSpecificInfo's hard coded cases.
webrtc::CodecSpecificInfo codecSpecificInfo;
if ([info isKindOfClass:[RTCCodecSpecificInfoH264 class]]) {
codecSpecificInfo = [(RTCCodecSpecificInfoH264 *)info toCpp];
}
std::unique_ptr<webrtc::RTPFragmentationHeader> header = [fragmentationHeader toCpp];
return _videoToolboxDecoder->Decode(
image, missingFrames, header.release(), &codecSpecificInfo, renderTimeMs);
}
@end
// Encoder factory.
@implementation RTCVideoEncoderFactoryH264
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
NSMutableArray<RTCVideoCodecInfo *> *codecs = [NSMutableArray array];
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
if (IsHighProfileEnabled()) {
NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
@"profile-level-id" : @"640c1f", // Level 3.1 Constrained High.
@"level-asymmetry-allowed" : @"1",
@"packetization-mode" : @"1",
};
RTCVideoCodecInfo *constrainedHighInfo =
[[RTCVideoCodecInfo alloc] initWithPayload:0
name:codecName
parameters:constrainedHighParams];
[codecs addObject:constrainedHighInfo];
}
NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
@"profile-level-id" : @"42e01f", // Level 3.1 Constrained Baseline.
@"level-asymmetry-allowed" : @"1",
@"packetization-mode" : @"1",
};
RTCVideoCodecInfo *constrainedBaselineInfo =
[[RTCVideoCodecInfo alloc] initWithPayload:0
name:codecName
parameters:constrainedBaselineParams];
[codecs addObject:constrainedBaselineInfo];
return [codecs copy];
}
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
}
@end
// Decoder factory.
@implementation RTCVideoDecoderFactoryH264
- (id<RTCVideoDecoder>)createDecoder:(RTCVideoCodecInfo *)info {
return [[RTCVideoDecoderH264 alloc] init];
}
- (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
NSString *codecName = [NSString stringWithUTF8String:cricket::kH264CodecName];
return @[ [[RTCVideoCodecInfo alloc] initWithPayload:0 name:codecName parameters:@{}] ];
}
@end

View File

@ -0,0 +1,72 @@
/*
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#import "WebRTC/RTCVideoCodec.h"
#import "NSString+StdString.h"
#import "RTCVideoCodec+Private.h"
#import "WebRTC/RTCVideoCodecFactory.h"
@implementation RTCVideoEncoderSettings
@synthesize name = _name;
@synthesize width = _width;
@synthesize height = _height;
@synthesize startBitrate = _startBitrate;
@synthesize maxBitrate = _maxBitrate;
@synthesize minBitrate = _minBitrate;
@synthesize targetBitrate = _targetBitrate;
@synthesize maxFramerate = _maxFramerate;
@synthesize qpMax = _qpMax;
- (instancetype)initWithVideoCodec:(const webrtc::VideoCodec *__nullable)videoCodec {
if (self = [super init]) {
if (videoCodec) {
rtc::Optional<const char *> codecName = CodecTypeToPayloadName(videoCodec->codecType);
if (codecName) {
_name = [NSString stringWithUTF8String:codecName.value()];
}
_width = videoCodec->width;
_height = videoCodec->height;
_startBitrate = videoCodec->startBitrate;
_maxBitrate = videoCodec->maxBitrate;
_minBitrate = videoCodec->minBitrate;
_targetBitrate = videoCodec->targetBitrate;
_maxFramerate = videoCodec->maxFramerate;
_qpMax = videoCodec->qpMax;
}
}
return self;
}
- (std::unique_ptr<webrtc::VideoCodec>)toCpp {
auto codecSettings = std::unique_ptr<webrtc::VideoCodec>(new webrtc::VideoCodec);
rtc::Optional<webrtc::VideoCodecType> codecType =
webrtc::PayloadNameToCodecType([NSString stdStringForString:_name]);
if (codecType) {
codecSettings->codecType = codecType.value();
}
codecSettings->width = _width;
codecSettings->height = _height;
codecSettings->startBitrate = _startBitrate;
codecSettings->maxBitrate = _maxBitrate;
codecSettings->minBitrate = _minBitrate;
codecSettings->targetBitrate = _targetBitrate;
codecSettings->maxFramerate = _maxFramerate;
codecSettings->qpMax = _qpMax;
return codecSettings;
}
@end

View File

@ -17,6 +17,7 @@
}
@synthesize buffer = _buffer;
@synthesize timeStamp;
- (int)width {
return _buffer.width;