/* * 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 #include "rtc_base/numerics/safe_conversions.h" // A simple wrapper around webrtc::EncodedImageBufferInterface to make it usable with associated // objects. @interface RTCWrappedEncodedImageBuffer : NSObject @property(nonatomic) rtc::scoped_refptr buffer; - (instancetype)initWithEncodedImageBuffer: (rtc::scoped_refptr)buffer; @end @implementation RTCWrappedEncodedImageBuffer @synthesize buffer = _buffer; - (instancetype)initWithEncodedImageBuffer: (rtc::scoped_refptr)buffer { self = [super init]; if (self) { _buffer = buffer; } return self; } @end @implementation RTCEncodedImage (Private) - (rtc::scoped_refptr)encodedData { RTCWrappedEncodedImageBuffer *wrappedBuffer = objc_getAssociatedObject(self, @selector(encodedData)); return wrappedBuffer.buffer; } - (void)setEncodedData:(rtc::scoped_refptr)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]) { // Wrap the buffer in NSData without copying, do not take ownership. self.buffer = [NSData dataWithBytesNoCopy:encodedImage.mutable_data() length:encodedImage.size() freeWhenDone:NO]; self.encodedWidth = rtc::dchecked_cast(encodedImage._encodedWidth); self.encodedHeight = rtc::dchecked_cast(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(encodedImage._frameType); self.rotation = static_cast(encodedImage.rotation_); self.completeFrame = encodedImage._completeFrame; 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( (uint8_t *)self.buffer.bytes, (size_t)self.buffer.length, (size_t)self.buffer.length); encodedImage._encodedWidth = rtc::dchecked_cast(self.encodedWidth); encodedImage._encodedHeight = rtc::dchecked_cast(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._completeFrame = self.completeFrame; encodedImage.qp_ = self.qp ? self.qp.intValue : -1; encodedImage.content_type_ = (self.contentType == RTCVideoContentTypeScreenshare) ? webrtc::VideoContentType::SCREENSHARE : webrtc::VideoContentType::UNSPECIFIED; return encodedImage; } @end