OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2016 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 #include "webrtc/sdk/objc/Framework/Classes/Video/corevideo_frame_buffer.h" | |
12 | |
13 #include "libyuv/convert.h" | |
14 #include "webrtc/api/video/i420_buffer.h" | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/logging.h" | |
17 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | |
18 | |
19 namespace webrtc { | |
20 | |
21 CoreVideoFrameBuffer::CoreVideoFrameBuffer(CVPixelBufferRef pixel_buffer, | |
22 int adapted_width, | |
23 int adapted_height, | |
24 int crop_width, | |
25 int crop_height, | |
26 int crop_x, | |
27 int crop_y) | |
28 : NativeHandleBuffer(pixel_buffer, adapted_width, adapted_height), | |
29 pixel_buffer_(pixel_buffer), | |
30 buffer_width_(CVPixelBufferGetWidth(pixel_buffer)), | |
31 buffer_height_(CVPixelBufferGetHeight(pixel_buffer)), | |
32 crop_width_(crop_width), crop_height_(crop_height), | |
33 // Can only crop at even pixels. | |
34 crop_x_(crop_x & ~1), crop_y_(crop_y & ~1) { | |
35 CVBufferRetain(pixel_buffer_); | |
36 } | |
37 | |
38 CoreVideoFrameBuffer::CoreVideoFrameBuffer(CVPixelBufferRef pixel_buffer) | |
39 : NativeHandleBuffer(pixel_buffer, | |
40 CVPixelBufferGetWidth(pixel_buffer), | |
41 CVPixelBufferGetHeight(pixel_buffer)), | |
42 pixel_buffer_(pixel_buffer), | |
43 buffer_width_(width_), buffer_height_(height_), | |
44 crop_width_(width_), crop_height_(height_), | |
45 crop_x_(0), crop_y_(0) { | |
46 CVBufferRetain(pixel_buffer_); | |
47 } | |
48 | |
49 CoreVideoFrameBuffer::~CoreVideoFrameBuffer() { | |
50 CVBufferRelease(pixel_buffer_); | |
51 } | |
52 | |
53 rtc::scoped_refptr<VideoFrameBuffer> | |
54 CoreVideoFrameBuffer::NativeToI420Buffer() { | |
55 const OSType pixel_format = CVPixelBufferGetPixelFormatType(pixel_buffer_); | |
56 RTC_DCHECK(pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange || | |
57 pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange); | |
58 | |
59 CVPixelBufferLockBaseAddress(pixel_buffer_, kCVPixelBufferLock_ReadOnly); | |
60 const uint8_t* src_y = static_cast<const uint8_t*>( | |
61 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer_, 0)); | |
62 const int src_y_stride = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer_, 0); | |
63 const uint8_t* src_uv = static_cast<const uint8_t*>( | |
64 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer_, 1)); | |
65 const int src_uv_stride = | |
66 CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer_, 1); | |
67 | |
68 // Crop just by modifying pointers. | |
69 src_y += src_y_stride * crop_y_ + crop_x_; | |
70 src_uv += src_uv_stride * (crop_y_ / 2) + crop_x_; | |
71 | |
72 // TODO(magjed): Use a frame buffer pool. | |
73 NV12ToI420Scaler nv12_to_i420_scaler; | |
74 rtc::scoped_refptr<I420Buffer> buffer = | |
75 new rtc::RefCountedObject<I420Buffer>(width_, height_); | |
76 nv12_to_i420_scaler.NV12ToI420Scale( | |
77 src_y, src_y_stride, | |
78 src_uv, src_uv_stride, | |
79 crop_width_, crop_height_, | |
80 buffer->MutableDataY(), buffer->StrideY(), | |
81 buffer->MutableDataU(), buffer->StrideU(), | |
82 buffer->MutableDataV(), buffer->StrideV(), | |
83 buffer->width(), buffer->height()); | |
84 | |
85 CVPixelBufferUnlockBaseAddress(pixel_buffer_, kCVPixelBufferLock_ReadOnly); | |
86 | |
87 return buffer; | |
88 } | |
89 | |
90 bool CoreVideoFrameBuffer::RequiresCropping() const { | |
91 return crop_width_ != buffer_width_ || crop_height_ != buffer_height_; | |
92 } | |
93 | |
94 bool CoreVideoFrameBuffer::CropAndScaleTo( | |
95 std::vector<uint8_t>* tmp_buffer, | |
96 CVPixelBufferRef output_pixel_buffer) const { | |
97 // Prepare output pointers. | |
98 RTC_DCHECK_EQ(CVPixelBufferGetPixelFormatType(output_pixel_buffer), | |
99 kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); | |
100 CVReturn cv_ret = CVPixelBufferLockBaseAddress(output_pixel_buffer, 0); | |
101 if (cv_ret != kCVReturnSuccess) { | |
102 LOG(LS_ERROR) << "Failed to lock base address: " << cv_ret; | |
103 return false; | |
104 } | |
105 const int dst_width = CVPixelBufferGetWidth(output_pixel_buffer); | |
106 const int dst_height = CVPixelBufferGetHeight(output_pixel_buffer); | |
107 uint8_t* dst_y = reinterpret_cast<uint8_t*>( | |
108 CVPixelBufferGetBaseAddressOfPlane(output_pixel_buffer, 0)); | |
109 const int dst_y_stride = | |
110 CVPixelBufferGetBytesPerRowOfPlane(output_pixel_buffer, 0); | |
111 uint8_t* dst_uv = reinterpret_cast<uint8_t*>( | |
112 CVPixelBufferGetBaseAddressOfPlane(output_pixel_buffer, 1)); | |
113 const int dst_uv_stride = | |
114 CVPixelBufferGetBytesPerRowOfPlane(output_pixel_buffer, 1); | |
115 | |
116 // Prepare source pointers. | |
117 const OSType src_pixel_format = | |
118 CVPixelBufferGetPixelFormatType(pixel_buffer_); | |
119 RTC_DCHECK( | |
120 src_pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange || | |
121 src_pixel_format == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange); | |
122 CVPixelBufferLockBaseAddress(pixel_buffer_, kCVPixelBufferLock_ReadOnly); | |
123 const uint8_t* src_y = static_cast<const uint8_t*>( | |
124 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer_, 0)); | |
125 const int src_y_stride = CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer_, 0); | |
126 const uint8_t* src_uv = static_cast<const uint8_t*>( | |
127 CVPixelBufferGetBaseAddressOfPlane(pixel_buffer_, 1)); | |
128 const int src_uv_stride = | |
129 CVPixelBufferGetBytesPerRowOfPlane(pixel_buffer_, 1); | |
130 | |
131 // Crop just by modifying pointers. | |
132 src_y += src_y_stride * crop_y_ + crop_x_; | |
133 src_uv += src_uv_stride * (crop_y_ / 2) + crop_x_; | |
134 | |
135 NV12Scale(tmp_buffer, | |
136 src_y, src_y_stride, | |
137 src_uv, src_uv_stride, | |
138 crop_width_, crop_height_, | |
139 dst_y, dst_y_stride, | |
140 dst_uv, dst_uv_stride, | |
141 dst_width, dst_height); | |
142 | |
143 CVPixelBufferUnlockBaseAddress(pixel_buffer_, kCVPixelBufferLock_ReadOnly); | |
144 CVPixelBufferUnlockBaseAddress(output_pixel_buffer, 0); | |
145 | |
146 return true; | |
147 } | |
148 | |
149 } // namespace webrtc | |
OLD | NEW |