blob: 7f8ae739e06f628544a6eca8527a4513c14850f3 [file] [log] [blame]
Anders Carlsson7bca8ca2018-08-30 09:30:29 +02001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#import "RTCEncodedImage+Private.h"
12
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020013#import <objc/runtime.h>
14
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020015#include "rtc_base/numerics/safe_conversions.h"
Kári Tristan Helgasonecbdbf62020-02-20 07:34:45 -080016
17namespace {
18// An implementation of EncodedImageBufferInterface that doesn't perform any copies.
19class ObjCEncodedImageBuffer : public webrtc::EncodedImageBufferInterface {
20 public:
21 static rtc::scoped_refptr<ObjCEncodedImageBuffer> Create(NSData *data) {
Niels Möllerac0d1832022-01-17 15:26:54 +010022 return rtc::make_ref_counted<ObjCEncodedImageBuffer>(data);
Kári Tristan Helgasonecbdbf62020-02-20 07:34:45 -080023 }
24 const uint8_t *data() const override { return static_cast<const uint8_t *>(data_.bytes); }
25 // TODO(bugs.webrtc.org/9378): delete this non-const data method.
26 uint8_t *data() override {
27 return const_cast<uint8_t *>(static_cast<const uint8_t *>(data_.bytes));
28 }
29 size_t size() const override { return data_.length; }
30
31 protected:
32 explicit ObjCEncodedImageBuffer(NSData *data) : data_(data) {}
33 ~ObjCEncodedImageBuffer() {}
34
35 NSData *data_;
36};
37}
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020038
Niels Möller4d504c72019-06-18 15:56:56 +020039// A simple wrapper around webrtc::EncodedImageBufferInterface to make it usable with associated
40// objects.
41@interface RTCWrappedEncodedImageBuffer : NSObject
42@property(nonatomic) rtc::scoped_refptr<webrtc::EncodedImageBufferInterface> buffer;
43- (instancetype)initWithEncodedImageBuffer:
44 (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer;
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020045@end
Niels Möller4d504c72019-06-18 15:56:56 +020046@implementation RTCWrappedEncodedImageBuffer
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020047@synthesize buffer = _buffer;
Niels Möller4d504c72019-06-18 15:56:56 +020048- (instancetype)initWithEncodedImageBuffer:
49 (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer {
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020050 self = [super init];
51 if (self) {
52 _buffer = buffer;
53 }
54 return self;
55}
56@end
57
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020058@implementation RTC_OBJC_TYPE (RTCEncodedImage)
59(Private)
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020060
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020061 - (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)encodedData {
Niels Möller4d504c72019-06-18 15:56:56 +020062 RTCWrappedEncodedImageBuffer *wrappedBuffer =
63 objc_getAssociatedObject(self, @selector(encodedData));
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020064 return wrappedBuffer.buffer;
65}
66
Niels Möller4d504c72019-06-18 15:56:56 +020067- (void)setEncodedData:(rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer {
68 return objc_setAssociatedObject(
69 self,
70 @selector(encodedData),
71 [[RTCWrappedEncodedImageBuffer alloc] initWithEncodedImageBuffer:buffer],
72 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
Kári Tristan Helgason03e85d22019-04-25 08:57:41 +020073}
74
Dillon Cower5963fdd2019-02-07 16:17:43 -080075- (instancetype)initWithNativeEncodedImage:(const webrtc::EncodedImage &)encodedImage {
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020076 if (self = [super init]) {
Kári Tristan Helgasonecbdbf62020-02-20 07:34:45 -080077 // A reference to the encodedData must be stored so that it's kept alive as long
78 // self.buffer references its underlying data.
79 self.encodedData = encodedImage.GetEncodedData();
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020080 // Wrap the buffer in NSData without copying, do not take ownership.
Kári Tristan Helgasonecbdbf62020-02-20 07:34:45 -080081 self.buffer = [NSData dataWithBytesNoCopy:self.encodedData->data()
Kári Tristan Helgasonba9e1b82020-03-16 16:49:11 +010082 length:encodedImage.size()
Niels Möller77536a22019-01-15 08:50:01 +010083 freeWhenDone:NO];
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020084 self.encodedWidth = rtc::dchecked_cast<int32_t>(encodedImage._encodedWidth);
85 self.encodedHeight = rtc::dchecked_cast<int32_t>(encodedImage._encodedHeight);
86 self.timeStamp = encodedImage.Timestamp();
87 self.captureTimeMs = encodedImage.capture_time_ms_;
88 self.ntpTimeMs = encodedImage.ntp_time_ms_;
89 self.flags = encodedImage.timing_.flags;
90 self.encodeStartMs = encodedImage.timing_.encode_start_ms;
91 self.encodeFinishMs = encodedImage.timing_.encode_finish_ms;
92 self.frameType = static_cast<RTCFrameType>(encodedImage._frameType);
93 self.rotation = static_cast<RTCVideoRotation>(encodedImage.rotation_);
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020094 self.qp = @(encodedImage.qp_);
95 self.contentType = (encodedImage.content_type_ == webrtc::VideoContentType::SCREENSHARE) ?
96 RTCVideoContentTypeScreenshare :
97 RTCVideoContentTypeUnspecified;
98 }
99
100 return self;
101}
102
103- (webrtc::EncodedImage)nativeEncodedImage {
104 // Return the pointer without copying.
Kári Tristan Helgasonecbdbf62020-02-20 07:34:45 -0800105 webrtc::EncodedImage encodedImage;
106 if (self.encodedData) {
107 encodedImage.SetEncodedData(self.encodedData);
108 } else if (self.buffer) {
109 encodedImage.SetEncodedData(ObjCEncodedImageBuffer::Create(self.buffer));
110 }
111 encodedImage.set_size(self.buffer.length);
Anders Carlsson7bca8ca2018-08-30 09:30:29 +0200112 encodedImage._encodedWidth = rtc::dchecked_cast<uint32_t>(self.encodedWidth);
113 encodedImage._encodedHeight = rtc::dchecked_cast<uint32_t>(self.encodedHeight);
114 encodedImage.SetTimestamp(self.timeStamp);
115 encodedImage.capture_time_ms_ = self.captureTimeMs;
116 encodedImage.ntp_time_ms_ = self.ntpTimeMs;
117 encodedImage.timing_.flags = self.flags;
118 encodedImage.timing_.encode_start_ms = self.encodeStartMs;
119 encodedImage.timing_.encode_finish_ms = self.encodeFinishMs;
Niels Möller87e2d782019-03-07 10:18:23 +0100120 encodedImage._frameType = webrtc::VideoFrameType(self.frameType);
Anders Carlsson7bca8ca2018-08-30 09:30:29 +0200121 encodedImage.rotation_ = webrtc::VideoRotation(self.rotation);
Anders Carlsson7bca8ca2018-08-30 09:30:29 +0200122 encodedImage.qp_ = self.qp ? self.qp.intValue : -1;
123 encodedImage.content_type_ = (self.contentType == RTCVideoContentTypeScreenshare) ?
124 webrtc::VideoContentType::SCREENSHARE :
125 webrtc::VideoContentType::UNSPECIFIED;
126
127 return encodedImage;
128}
129
130@end