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