1*d9f75844SAndroid Build Coastguard Worker/* 2*d9f75844SAndroid Build Coastguard Worker * Copyright 2017 The WebRTC project authors. All Rights Reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker#import "RTCEncodedImage+Private.h" 12*d9f75844SAndroid Build Coastguard Worker 13*d9f75844SAndroid Build Coastguard Worker#import <objc/runtime.h> 14*d9f75844SAndroid Build Coastguard Worker 15*d9f75844SAndroid Build Coastguard Worker#include "rtc_base/numerics/safe_conversions.h" 16*d9f75844SAndroid Build Coastguard Worker 17*d9f75844SAndroid Build Coastguard Workernamespace { 18*d9f75844SAndroid Build Coastguard Worker// An implementation of EncodedImageBufferInterface that doesn't perform any copies. 19*d9f75844SAndroid Build Coastguard Workerclass ObjCEncodedImageBuffer : public webrtc::EncodedImageBufferInterface { 20*d9f75844SAndroid Build Coastguard Worker public: 21*d9f75844SAndroid Build Coastguard Worker static rtc::scoped_refptr<ObjCEncodedImageBuffer> Create(NSData *data) { 22*d9f75844SAndroid Build Coastguard Worker return rtc::make_ref_counted<ObjCEncodedImageBuffer>(data); 23*d9f75844SAndroid Build Coastguard Worker } 24*d9f75844SAndroid Build Coastguard Worker const uint8_t *data() const override { return static_cast<const uint8_t *>(data_.bytes); } 25*d9f75844SAndroid Build Coastguard Worker // TODO(bugs.webrtc.org/9378): delete this non-const data method. 26*d9f75844SAndroid Build Coastguard Worker uint8_t *data() override { 27*d9f75844SAndroid Build Coastguard Worker return const_cast<uint8_t *>(static_cast<const uint8_t *>(data_.bytes)); 28*d9f75844SAndroid Build Coastguard Worker } 29*d9f75844SAndroid Build Coastguard Worker size_t size() const override { return data_.length; } 30*d9f75844SAndroid Build Coastguard Worker 31*d9f75844SAndroid Build Coastguard Worker protected: 32*d9f75844SAndroid Build Coastguard Worker explicit ObjCEncodedImageBuffer(NSData *data) : data_(data) {} 33*d9f75844SAndroid Build Coastguard Worker ~ObjCEncodedImageBuffer() {} 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard Worker NSData *data_; 36*d9f75844SAndroid Build Coastguard Worker}; 37*d9f75844SAndroid Build Coastguard Worker} 38*d9f75844SAndroid Build Coastguard Worker 39*d9f75844SAndroid Build Coastguard Worker// A simple wrapper around webrtc::EncodedImageBufferInterface to make it usable with associated 40*d9f75844SAndroid Build Coastguard Worker// objects. 41*d9f75844SAndroid Build Coastguard Worker@interface RTCWrappedEncodedImageBuffer : NSObject 42*d9f75844SAndroid Build Coastguard Worker@property(nonatomic) rtc::scoped_refptr<webrtc::EncodedImageBufferInterface> buffer; 43*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithEncodedImageBuffer: 44*d9f75844SAndroid Build Coastguard Worker (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer; 45*d9f75844SAndroid Build Coastguard Worker@end 46*d9f75844SAndroid Build Coastguard Worker@implementation RTCWrappedEncodedImageBuffer 47*d9f75844SAndroid Build Coastguard Worker@synthesize buffer = _buffer; 48*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithEncodedImageBuffer: 49*d9f75844SAndroid Build Coastguard Worker (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer { 50*d9f75844SAndroid Build Coastguard Worker self = [super init]; 51*d9f75844SAndroid Build Coastguard Worker if (self) { 52*d9f75844SAndroid Build Coastguard Worker _buffer = buffer; 53*d9f75844SAndroid Build Coastguard Worker } 54*d9f75844SAndroid Build Coastguard Worker return self; 55*d9f75844SAndroid Build Coastguard Worker} 56*d9f75844SAndroid Build Coastguard Worker@end 57*d9f75844SAndroid Build Coastguard Worker 58*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCEncodedImage) 59*d9f75844SAndroid Build Coastguard Worker(Private) 60*d9f75844SAndroid Build Coastguard Worker 61*d9f75844SAndroid Build Coastguard Worker - (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)encodedData { 62*d9f75844SAndroid Build Coastguard Worker RTCWrappedEncodedImageBuffer *wrappedBuffer = 63*d9f75844SAndroid Build Coastguard Worker objc_getAssociatedObject(self, @selector(encodedData)); 64*d9f75844SAndroid Build Coastguard Worker return wrappedBuffer.buffer; 65*d9f75844SAndroid Build Coastguard Worker} 66*d9f75844SAndroid Build Coastguard Worker 67*d9f75844SAndroid Build Coastguard Worker- (void)setEncodedData:(rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer { 68*d9f75844SAndroid Build Coastguard Worker return objc_setAssociatedObject( 69*d9f75844SAndroid Build Coastguard Worker self, 70*d9f75844SAndroid Build Coastguard Worker @selector(encodedData), 71*d9f75844SAndroid Build Coastguard Worker [[RTCWrappedEncodedImageBuffer alloc] initWithEncodedImageBuffer:buffer], 72*d9f75844SAndroid Build Coastguard Worker OBJC_ASSOCIATION_RETAIN_NONATOMIC); 73*d9f75844SAndroid Build Coastguard Worker} 74*d9f75844SAndroid Build Coastguard Worker 75*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithNativeEncodedImage:(const webrtc::EncodedImage &)encodedImage { 76*d9f75844SAndroid Build Coastguard Worker if (self = [super init]) { 77*d9f75844SAndroid Build Coastguard Worker // A reference to the encodedData must be stored so that it's kept alive as long 78*d9f75844SAndroid Build Coastguard Worker // self.buffer references its underlying data. 79*d9f75844SAndroid Build Coastguard Worker self.encodedData = encodedImage.GetEncodedData(); 80*d9f75844SAndroid Build Coastguard Worker // Wrap the buffer in NSData without copying, do not take ownership. 81*d9f75844SAndroid Build Coastguard Worker self.buffer = [NSData dataWithBytesNoCopy:self.encodedData->data() 82*d9f75844SAndroid Build Coastguard Worker length:encodedImage.size() 83*d9f75844SAndroid Build Coastguard Worker freeWhenDone:NO]; 84*d9f75844SAndroid Build Coastguard Worker self.encodedWidth = rtc::dchecked_cast<int32_t>(encodedImage._encodedWidth); 85*d9f75844SAndroid Build Coastguard Worker self.encodedHeight = rtc::dchecked_cast<int32_t>(encodedImage._encodedHeight); 86*d9f75844SAndroid Build Coastguard Worker self.timeStamp = encodedImage.Timestamp(); 87*d9f75844SAndroid Build Coastguard Worker self.captureTimeMs = encodedImage.capture_time_ms_; 88*d9f75844SAndroid Build Coastguard Worker self.ntpTimeMs = encodedImage.ntp_time_ms_; 89*d9f75844SAndroid Build Coastguard Worker self.flags = encodedImage.timing_.flags; 90*d9f75844SAndroid Build Coastguard Worker self.encodeStartMs = encodedImage.timing_.encode_start_ms; 91*d9f75844SAndroid Build Coastguard Worker self.encodeFinishMs = encodedImage.timing_.encode_finish_ms; 92*d9f75844SAndroid Build Coastguard Worker self.frameType = static_cast<RTCFrameType>(encodedImage._frameType); 93*d9f75844SAndroid Build Coastguard Worker self.rotation = static_cast<RTCVideoRotation>(encodedImage.rotation_); 94*d9f75844SAndroid Build Coastguard Worker self.qp = @(encodedImage.qp_); 95*d9f75844SAndroid Build Coastguard Worker self.contentType = (encodedImage.content_type_ == webrtc::VideoContentType::SCREENSHARE) ? 96*d9f75844SAndroid Build Coastguard Worker RTCVideoContentTypeScreenshare : 97*d9f75844SAndroid Build Coastguard Worker RTCVideoContentTypeUnspecified; 98*d9f75844SAndroid Build Coastguard Worker } 99*d9f75844SAndroid Build Coastguard Worker 100*d9f75844SAndroid Build Coastguard Worker return self; 101*d9f75844SAndroid Build Coastguard Worker} 102*d9f75844SAndroid Build Coastguard Worker 103*d9f75844SAndroid Build Coastguard Worker- (webrtc::EncodedImage)nativeEncodedImage { 104*d9f75844SAndroid Build Coastguard Worker // Return the pointer without copying. 105*d9f75844SAndroid Build Coastguard Worker webrtc::EncodedImage encodedImage; 106*d9f75844SAndroid Build Coastguard Worker if (self.encodedData) { 107*d9f75844SAndroid Build Coastguard Worker encodedImage.SetEncodedData(self.encodedData); 108*d9f75844SAndroid Build Coastguard Worker } else if (self.buffer) { 109*d9f75844SAndroid Build Coastguard Worker encodedImage.SetEncodedData(ObjCEncodedImageBuffer::Create(self.buffer)); 110*d9f75844SAndroid Build Coastguard Worker } 111*d9f75844SAndroid Build Coastguard Worker encodedImage.set_size(self.buffer.length); 112*d9f75844SAndroid Build Coastguard Worker encodedImage._encodedWidth = rtc::dchecked_cast<uint32_t>(self.encodedWidth); 113*d9f75844SAndroid Build Coastguard Worker encodedImage._encodedHeight = rtc::dchecked_cast<uint32_t>(self.encodedHeight); 114*d9f75844SAndroid Build Coastguard Worker encodedImage.SetTimestamp(self.timeStamp); 115*d9f75844SAndroid Build Coastguard Worker encodedImage.capture_time_ms_ = self.captureTimeMs; 116*d9f75844SAndroid Build Coastguard Worker encodedImage.ntp_time_ms_ = self.ntpTimeMs; 117*d9f75844SAndroid Build Coastguard Worker encodedImage.timing_.flags = self.flags; 118*d9f75844SAndroid Build Coastguard Worker encodedImage.timing_.encode_start_ms = self.encodeStartMs; 119*d9f75844SAndroid Build Coastguard Worker encodedImage.timing_.encode_finish_ms = self.encodeFinishMs; 120*d9f75844SAndroid Build Coastguard Worker encodedImage._frameType = webrtc::VideoFrameType(self.frameType); 121*d9f75844SAndroid Build Coastguard Worker encodedImage.rotation_ = webrtc::VideoRotation(self.rotation); 122*d9f75844SAndroid Build Coastguard Worker encodedImage.qp_ = self.qp ? self.qp.intValue : -1; 123*d9f75844SAndroid Build Coastguard Worker encodedImage.content_type_ = (self.contentType == RTCVideoContentTypeScreenshare) ? 124*d9f75844SAndroid Build Coastguard Worker webrtc::VideoContentType::SCREENSHARE : 125*d9f75844SAndroid Build Coastguard Worker webrtc::VideoContentType::UNSPECIFIED; 126*d9f75844SAndroid Build Coastguard Worker 127*d9f75844SAndroid Build Coastguard Worker return encodedImage; 128*d9f75844SAndroid Build Coastguard Worker} 129*d9f75844SAndroid Build Coastguard Worker 130*d9f75844SAndroid Build Coastguard Worker@end 131