blob: 98b86c54c0709c763fd7c2eaaaf13addcfc1db1b [file] [log] [blame]
Anders Carlssonfe9d8172018-04-03 11:40:39 +02001/*
2 * Copyright 2018 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
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020011#include "sdk/objc/unittests/frame_buffer_helpers.h"
Anders Carlssonfe9d8172018-04-03 11:40:39 +020012
13#include "third_party/libyuv/include/libyuv.h"
14
15void DrawGradientInRGBPixelBuffer(CVPixelBufferRef pixelBuffer) {
16 CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
17 void* baseAddr = CVPixelBufferGetBaseAddress(pixelBuffer);
18 size_t width = CVPixelBufferGetWidth(pixelBuffer);
19 size_t height = CVPixelBufferGetHeight(pixelBuffer);
20 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
Anders Carlsson498644e2018-04-05 13:07:39 +020021 int byteOrder = CVPixelBufferGetPixelFormatType(pixelBuffer) == kCVPixelFormatType_32ARGB ?
22 kCGBitmapByteOrder32Little :
23 0;
Anders Carlssonfe9d8172018-04-03 11:40:39 +020024 CGContextRef cgContext = CGBitmapContextCreate(baseAddr,
25 width,
26 height,
27 8,
28 CVPixelBufferGetBytesPerRow(pixelBuffer),
29 colorSpace,
Anders Carlsson498644e2018-04-05 13:07:39 +020030 byteOrder | kCGImageAlphaNoneSkipLast);
Anders Carlssonfe9d8172018-04-03 11:40:39 +020031
32 // Create a gradient
33 CGFloat colors[] = {
34 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,
35 };
36 CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, NULL, 4);
37
38 CGContextDrawLinearGradient(
39 cgContext, gradient, CGPointMake(0, 0), CGPointMake(width, height), 0);
40 CGGradientRelease(gradient);
41
42 CGImageRef cgImage = CGBitmapContextCreateImage(cgContext);
43 CGContextRelease(cgContext);
44 CGImageRelease(cgImage);
45 CGColorSpaceRelease(colorSpace);
46
47 CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
48}
49
50rtc::scoped_refptr<webrtc::I420Buffer> CreateI420Gradient(int width, int height) {
51 rtc::scoped_refptr<webrtc::I420Buffer> buffer(webrtc::I420Buffer::Create(width, height));
52 // Initialize with gradient, Y = 128(x/w + y/h), U = 256 x/w, V = 256 y/h
53 for (int x = 0; x < width; x++) {
54 for (int y = 0; y < height; y++) {
55 buffer->MutableDataY()[x + y * width] = 128 * (x * height + y * width) / (width * height);
56 }
57 }
58 int chroma_width = buffer->ChromaWidth();
59 int chroma_height = buffer->ChromaHeight();
60 for (int x = 0; x < chroma_width; x++) {
61 for (int y = 0; y < chroma_height; y++) {
62 buffer->MutableDataU()[x + y * chroma_width] = 255 * x / (chroma_width - 1);
63 buffer->MutableDataV()[x + y * chroma_width] = 255 * y / (chroma_height - 1);
64 }
65 }
66 return buffer;
67}
68
69void CopyI420BufferToCVPixelBuffer(rtc::scoped_refptr<webrtc::I420Buffer> i420Buffer,
70 CVPixelBufferRef pixelBuffer) {
71 CVPixelBufferLockBaseAddress(pixelBuffer, 0);
72
73 const OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);
74 if (pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ||
75 pixelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
76 // NV12
77 uint8_t* dstY = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0));
78 const int dstYStride = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
79 uint8_t* dstUV = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1));
80 const int dstUVStride = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
81
82 libyuv::I420ToNV12(i420Buffer->DataY(),
83 i420Buffer->StrideY(),
84 i420Buffer->DataU(),
85 i420Buffer->StrideU(),
86 i420Buffer->DataV(),
87 i420Buffer->StrideV(),
88 dstY,
89 dstYStride,
90 dstUV,
91 dstUVStride,
92 i420Buffer->width(),
93 i420Buffer->height());
94 } else {
95 uint8_t* dst = static_cast<uint8_t*>(CVPixelBufferGetBaseAddress(pixelBuffer));
96 const int bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
97
98 if (pixelFormat == kCVPixelFormatType_32BGRA) {
99 // Corresponds to libyuv::FOURCC_ARGB
100 libyuv::I420ToARGB(i420Buffer->DataY(),
101 i420Buffer->StrideY(),
102 i420Buffer->DataU(),
103 i420Buffer->StrideU(),
104 i420Buffer->DataV(),
105 i420Buffer->StrideV(),
106 dst,
107 bytesPerRow,
108 i420Buffer->width(),
109 i420Buffer->height());
110 } else if (pixelFormat == kCVPixelFormatType_32ARGB) {
111 // Corresponds to libyuv::FOURCC_BGRA
112 libyuv::I420ToBGRA(i420Buffer->DataY(),
113 i420Buffer->StrideY(),
114 i420Buffer->DataU(),
115 i420Buffer->StrideU(),
116 i420Buffer->DataV(),
117 i420Buffer->StrideV(),
118 dst,
119 bytesPerRow,
120 i420Buffer->width(),
121 i420Buffer->height());
122 }
123 }
124
125 CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
126}