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:860f729816TBR=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:
@ -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
|
||||
@ -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!");
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -17,6 +17,7 @@
|
||||
}
|
||||
|
||||
@synthesize buffer = _buffer;
|
||||
@synthesize timeStamp;
|
||||
|
||||
- (int)width {
|
||||
return _buffer.width;
|
||||
|
||||
Reference in New Issue
Block a user