1/* 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 "RTCNativeI420Buffer+Private.h" 12 13#include "api/video/i420_buffer.h" 14 15#if !defined(NDEBUG) && defined(WEBRTC_IOS) 16#import <UIKit/UIKit.h> 17#include "third_party/libyuv/include/libyuv.h" 18#endif 19 20@implementation RTC_OBJC_TYPE (RTCI420Buffer) 21 22- (instancetype)initWithWidth:(int)width height:(int)height { 23 if (self = [super init]) { 24 _i420Buffer = webrtc::I420Buffer::Create(width, height); 25 } 26 27 return self; 28} 29 30- (instancetype)initWithWidth:(int)width 31 height:(int)height 32 dataY:(const uint8_t *)dataY 33 dataU:(const uint8_t *)dataU 34 dataV:(const uint8_t *)dataV { 35 if (self = [super init]) { 36 _i420Buffer = webrtc::I420Buffer::Copy( 37 width, height, dataY, width, dataU, (width + 1) / 2, dataV, (width + 1) / 2); 38 } 39 return self; 40} 41 42- (instancetype)initWithWidth:(int)width 43 height:(int)height 44 strideY:(int)strideY 45 strideU:(int)strideU 46 strideV:(int)strideV { 47 if (self = [super init]) { 48 _i420Buffer = webrtc::I420Buffer::Create(width, height, strideY, strideU, strideV); 49 } 50 51 return self; 52} 53 54- (instancetype)initWithFrameBuffer:(rtc::scoped_refptr<webrtc::I420BufferInterface>)i420Buffer { 55 if (self = [super init]) { 56 _i420Buffer = i420Buffer; 57 } 58 59 return self; 60} 61 62- (int)width { 63 return _i420Buffer->width(); 64} 65 66- (int)height { 67 return _i420Buffer->height(); 68} 69 70- (int)strideY { 71 return _i420Buffer->StrideY(); 72} 73 74- (int)strideU { 75 return _i420Buffer->StrideU(); 76} 77 78- (int)strideV { 79 return _i420Buffer->StrideV(); 80} 81 82- (int)chromaWidth { 83 return _i420Buffer->ChromaWidth(); 84} 85 86- (int)chromaHeight { 87 return _i420Buffer->ChromaHeight(); 88} 89 90- (const uint8_t *)dataY { 91 return _i420Buffer->DataY(); 92} 93 94- (const uint8_t *)dataU { 95 return _i420Buffer->DataU(); 96} 97 98- (const uint8_t *)dataV { 99 return _i420Buffer->DataV(); 100} 101 102- (id<RTC_OBJC_TYPE(RTCVideoFrameBuffer)>)cropAndScaleWith:(int)offsetX 103 offsetY:(int)offsetY 104 cropWidth:(int)cropWidth 105 cropHeight:(int)cropHeight 106 scaleWidth:(int)scaleWidth 107 scaleHeight:(int)scaleHeight { 108 rtc::scoped_refptr<webrtc::VideoFrameBuffer> scaled_buffer = 109 _i420Buffer->CropAndScale(offsetX, offsetY, cropWidth, cropHeight, scaleWidth, scaleHeight); 110 RTC_DCHECK_EQ(scaled_buffer->type(), webrtc::VideoFrameBuffer::Type::kI420); 111 // Calling ToI420() doesn't do any conversions. 112 rtc::scoped_refptr<webrtc::I420BufferInterface> buffer = scaled_buffer->ToI420(); 113 RTC_OBJC_TYPE(RTCI420Buffer) *result = 114 [[RTC_OBJC_TYPE(RTCI420Buffer) alloc] initWithFrameBuffer:buffer]; 115 return result; 116} 117 118- (id<RTC_OBJC_TYPE(RTCI420Buffer)>)toI420 { 119 return self; 120} 121 122#pragma mark - Private 123 124- (rtc::scoped_refptr<webrtc::I420BufferInterface>)nativeI420Buffer { 125 return _i420Buffer; 126} 127 128#pragma mark - Debugging 129 130#if !defined(NDEBUG) && defined(WEBRTC_IOS) 131- (id)debugQuickLookObject { 132 UIGraphicsBeginImageContext(CGSizeMake(_i420Buffer->width(), _i420Buffer->height())); 133 CGContextRef c = UIGraphicsGetCurrentContext(); 134 uint8_t *ctxData = (uint8_t *)CGBitmapContextGetData(c); 135 136 libyuv::I420ToARGB(_i420Buffer->DataY(), 137 _i420Buffer->StrideY(), 138 _i420Buffer->DataU(), 139 _i420Buffer->StrideU(), 140 _i420Buffer->DataV(), 141 _i420Buffer->StrideV(), 142 ctxData, 143 CGBitmapContextGetBytesPerRow(c), 144 CGBitmapContextGetWidth(c), 145 CGBitmapContextGetHeight(c)); 146 147 UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 148 UIGraphicsEndImageContext(); 149 150 return image; 151} 152#endif 153 154@end 155