diff options
Diffstat (limited to '')
-rw-r--r-- | third_party/libwebrtc/sdk/objc/api/peerconnection/RTCEncodedImage+Private.mm | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCEncodedImage+Private.mm b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCEncodedImage+Private.mm new file mode 100644 index 0000000000..7f8ae739e0 --- /dev/null +++ b/third_party/libwebrtc/sdk/objc/api/peerconnection/RTCEncodedImage+Private.mm @@ -0,0 +1,130 @@ +/* + * 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 "RTCEncodedImage+Private.h" + +#import <objc/runtime.h> + +#include "rtc_base/numerics/safe_conversions.h" + +namespace { +// An implementation of EncodedImageBufferInterface that doesn't perform any copies. +class ObjCEncodedImageBuffer : public webrtc::EncodedImageBufferInterface { + public: + static rtc::scoped_refptr<ObjCEncodedImageBuffer> Create(NSData *data) { + return rtc::make_ref_counted<ObjCEncodedImageBuffer>(data); + } + const uint8_t *data() const override { return static_cast<const uint8_t *>(data_.bytes); } + // TODO(bugs.webrtc.org/9378): delete this non-const data method. + uint8_t *data() override { + return const_cast<uint8_t *>(static_cast<const uint8_t *>(data_.bytes)); + } + size_t size() const override { return data_.length; } + + protected: + explicit ObjCEncodedImageBuffer(NSData *data) : data_(data) {} + ~ObjCEncodedImageBuffer() {} + + NSData *data_; +}; +} + +// A simple wrapper around webrtc::EncodedImageBufferInterface to make it usable with associated +// objects. +@interface RTCWrappedEncodedImageBuffer : NSObject +@property(nonatomic) rtc::scoped_refptr<webrtc::EncodedImageBufferInterface> buffer; +- (instancetype)initWithEncodedImageBuffer: + (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer; +@end +@implementation RTCWrappedEncodedImageBuffer +@synthesize buffer = _buffer; +- (instancetype)initWithEncodedImageBuffer: + (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer { + self = [super init]; + if (self) { + _buffer = buffer; + } + return self; +} +@end + +@implementation RTC_OBJC_TYPE (RTCEncodedImage) +(Private) + + - (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)encodedData { + RTCWrappedEncodedImageBuffer *wrappedBuffer = + objc_getAssociatedObject(self, @selector(encodedData)); + return wrappedBuffer.buffer; +} + +- (void)setEncodedData:(rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer { + return objc_setAssociatedObject( + self, + @selector(encodedData), + [[RTCWrappedEncodedImageBuffer alloc] initWithEncodedImageBuffer:buffer], + OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (instancetype)initWithNativeEncodedImage:(const webrtc::EncodedImage &)encodedImage { + if (self = [super init]) { + // A reference to the encodedData must be stored so that it's kept alive as long + // self.buffer references its underlying data. + self.encodedData = encodedImage.GetEncodedData(); + // Wrap the buffer in NSData without copying, do not take ownership. + self.buffer = [NSData dataWithBytesNoCopy:self.encodedData->data() + length:encodedImage.size() + freeWhenDone:NO]; + self.encodedWidth = rtc::dchecked_cast<int32_t>(encodedImage._encodedWidth); + self.encodedHeight = rtc::dchecked_cast<int32_t>(encodedImage._encodedHeight); + self.timeStamp = encodedImage.Timestamp(); + self.captureTimeMs = encodedImage.capture_time_ms_; + self.ntpTimeMs = encodedImage.ntp_time_ms_; + self.flags = encodedImage.timing_.flags; + self.encodeStartMs = encodedImage.timing_.encode_start_ms; + self.encodeFinishMs = encodedImage.timing_.encode_finish_ms; + self.frameType = static_cast<RTCFrameType>(encodedImage._frameType); + self.rotation = static_cast<RTCVideoRotation>(encodedImage.rotation_); + self.qp = @(encodedImage.qp_); + self.contentType = (encodedImage.content_type_ == webrtc::VideoContentType::SCREENSHARE) ? + RTCVideoContentTypeScreenshare : + RTCVideoContentTypeUnspecified; + } + + return self; +} + +- (webrtc::EncodedImage)nativeEncodedImage { + // Return the pointer without copying. + webrtc::EncodedImage encodedImage; + if (self.encodedData) { + encodedImage.SetEncodedData(self.encodedData); + } else if (self.buffer) { + encodedImage.SetEncodedData(ObjCEncodedImageBuffer::Create(self.buffer)); + } + encodedImage.set_size(self.buffer.length); + encodedImage._encodedWidth = rtc::dchecked_cast<uint32_t>(self.encodedWidth); + encodedImage._encodedHeight = rtc::dchecked_cast<uint32_t>(self.encodedHeight); + encodedImage.SetTimestamp(self.timeStamp); + encodedImage.capture_time_ms_ = self.captureTimeMs; + encodedImage.ntp_time_ms_ = self.ntpTimeMs; + encodedImage.timing_.flags = self.flags; + encodedImage.timing_.encode_start_ms = self.encodeStartMs; + encodedImage.timing_.encode_finish_ms = self.encodeFinishMs; + encodedImage._frameType = webrtc::VideoFrameType(self.frameType); + encodedImage.rotation_ = webrtc::VideoRotation(self.rotation); + encodedImage.qp_ = self.qp ? self.qp.intValue : -1; + encodedImage.content_type_ = (self.contentType == RTCVideoContentTypeScreenshare) ? + webrtc::VideoContentType::SCREENSHARE : + webrtc::VideoContentType::UNSPECIFIED; + + return encodedImage; +} + +@end |