| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/common_video/include/video_frame_buffer.h" | 11 #include "webrtc/common_video/include/video_frame_buffer.h" |
| 12 | 12 |
| 13 #include "webrtc/base/checks.h" | 13 #include "webrtc/base/checks.h" |
| 14 #include "webrtc/base/keep_ref_until_done.h" | 14 #include "webrtc/base/keep_ref_until_done.h" |
| 15 #include "libyuv/convert.h" | 15 #include "libyuv/convert.h" |
| 16 | 16 |
| 17 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. | 17 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD. |
| 18 static const int kBufferAlignment = 64; | 18 static const int kBufferAlignment = 64; |
| 19 | 19 |
| 20 namespace webrtc { | 20 namespace webrtc { |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 int I420DataSize(int height, int stride_y, int stride_u, int stride_v) { | 24 int I420DataSize(int height, int stride_y, int stride_u, int stride_v) { |
| 25 return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2); | 25 return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2); |
| 26 } | 26 } |
| 27 | 27 |
| 28 } // namespace | 28 } // namespace |
| 29 | 29 |
| 30 uint8_t* VideoFrameBuffer::MutableData(PlaneType type) { | 30 const uint8_t* VideoFrameBuffer::data(PlaneType type) const { |
| 31 switch (type) { |
| 32 case kYPlane: |
| 33 return DataY(); |
| 34 case kUPlane: |
| 35 return DataU(); |
| 36 case kVPlane: |
| 37 return DataV(); |
| 38 default: |
| 39 RTC_NOTREACHED(); |
| 40 return nullptr; |
| 41 } |
| 42 } |
| 43 |
| 44 const uint8_t* VideoFrameBuffer::DataY() const { |
| 45 return data(kYPlane); |
| 46 } |
| 47 const uint8_t* VideoFrameBuffer::DataU() const { |
| 48 return data(kUPlane); |
| 49 } |
| 50 const uint8_t* VideoFrameBuffer::DataV() const { |
| 51 return data(kVPlane); |
| 52 } |
| 53 |
| 54 int VideoFrameBuffer::stride(PlaneType type) const { |
| 55 switch (type) { |
| 56 case kYPlane: |
| 57 return StrideY(); |
| 58 case kUPlane: |
| 59 return StrideU(); |
| 60 case kVPlane: |
| 61 return StrideV(); |
| 62 default: |
| 63 RTC_NOTREACHED(); |
| 64 return 0; |
| 65 } |
| 66 } |
| 67 |
| 68 int VideoFrameBuffer::StrideY() const { |
| 69 return stride(kYPlane); |
| 70 } |
| 71 int VideoFrameBuffer::StrideU() const { |
| 72 return stride(kUPlane); |
| 73 } |
| 74 int VideoFrameBuffer::StrideV() const { |
| 75 return stride(kVPlane); |
| 76 } |
| 77 |
| 78 uint8_t* VideoFrameBuffer::MutableDataY() { |
| 31 RTC_NOTREACHED(); | 79 RTC_NOTREACHED(); |
| 32 return nullptr; | 80 return nullptr; |
| 33 } | 81 } |
| 82 uint8_t* VideoFrameBuffer::MutableDataU() { |
| 83 RTC_NOTREACHED(); |
| 84 return nullptr; |
| 85 } |
| 86 uint8_t* VideoFrameBuffer::MutableDataV() { |
| 87 RTC_NOTREACHED(); |
| 88 return nullptr; |
| 89 } |
| 90 |
| 91 uint8_t* VideoFrameBuffer::MutableData(PlaneType type) { |
| 92 switch (type) { |
| 93 case kYPlane: |
| 94 return MutableDataY(); |
| 95 case kUPlane: |
| 96 return MutableDataU(); |
| 97 case kVPlane: |
| 98 return MutableDataV(); |
| 99 default: |
| 100 RTC_NOTREACHED(); |
| 101 return nullptr; |
| 102 } |
| 103 } |
| 34 | 104 |
| 35 VideoFrameBuffer::~VideoFrameBuffer() {} | 105 VideoFrameBuffer::~VideoFrameBuffer() {} |
| 36 | 106 |
| 37 I420Buffer::I420Buffer(int width, int height) | 107 I420Buffer::I420Buffer(int width, int height) |
| 38 : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) { | 108 : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) { |
| 39 } | 109 } |
| 40 | 110 |
| 41 I420Buffer::I420Buffer(int width, | 111 I420Buffer::I420Buffer(int width, |
| 42 int height, | 112 int height, |
| 43 int stride_y, | 113 int stride_y, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 67 } | 137 } |
| 68 | 138 |
| 69 int I420Buffer::width() const { | 139 int I420Buffer::width() const { |
| 70 return width_; | 140 return width_; |
| 71 } | 141 } |
| 72 | 142 |
| 73 int I420Buffer::height() const { | 143 int I420Buffer::height() const { |
| 74 return height_; | 144 return height_; |
| 75 } | 145 } |
| 76 | 146 |
| 77 const uint8_t* I420Buffer::data(PlaneType type) const { | 147 const uint8_t* I420Buffer::DataY() const { |
| 78 switch (type) { | 148 return data_.get(); |
| 79 case kYPlane: | 149 } |
| 80 return data_.get(); | 150 const uint8_t* I420Buffer::DataU() const { |
| 81 case kUPlane: | 151 return data_.get() + stride_y_ * height_; |
| 82 return data_.get() + stride_y_ * height_; | 152 } |
| 83 case kVPlane: | 153 const uint8_t* I420Buffer::DataV() const { |
| 84 return data_.get() + stride_y_ * height_ + | 154 return data_.get() + stride_y_ * height_ + stride_u_ * ((height_ + 1) / 2); |
| 85 stride_u_ * ((height_ + 1) / 2); | |
| 86 default: | |
| 87 RTC_NOTREACHED(); | |
| 88 return nullptr; | |
| 89 } | |
| 90 } | 155 } |
| 91 | 156 |
| 92 bool I420Buffer::IsMutable() { | 157 bool I420Buffer::IsMutable() { |
| 93 return HasOneRef(); | 158 return HasOneRef(); |
| 94 } | 159 } |
| 95 | 160 |
| 96 uint8_t* I420Buffer::MutableData(PlaneType type) { | 161 uint8_t* I420Buffer::MutableDataY() { |
| 97 RTC_DCHECK(IsMutable()); | 162 RTC_DCHECK(IsMutable()); |
| 98 return const_cast<uint8_t*>( | 163 return const_cast<uint8_t*>(DataY()); |
| 99 static_cast<const VideoFrameBuffer*>(this)->data(type)); | 164 } |
| 165 uint8_t* I420Buffer::MutableDataU() { |
| 166 RTC_DCHECK(IsMutable()); |
| 167 return const_cast<uint8_t*>(DataU()); |
| 168 } |
| 169 uint8_t* I420Buffer::MutableDataV() { |
| 170 RTC_DCHECK(IsMutable()); |
| 171 return const_cast<uint8_t*>(DataV()); |
| 100 } | 172 } |
| 101 | 173 |
| 102 int I420Buffer::stride(PlaneType type) const { | 174 int I420Buffer::StrideY() const { |
| 103 switch (type) { | 175 return stride_y_; |
| 104 case kYPlane: | 176 } |
| 105 return stride_y_; | 177 int I420Buffer::StrideU() const { |
| 106 case kUPlane: | 178 return stride_u_; |
| 107 return stride_u_; | 179 } |
| 108 case kVPlane: | 180 int I420Buffer::StrideV() const { |
| 109 return stride_v_; | 181 return stride_v_; |
| 110 default: | |
| 111 RTC_NOTREACHED(); | |
| 112 return 0; | |
| 113 } | |
| 114 } | 182 } |
| 115 | 183 |
| 116 void* I420Buffer::native_handle() const { | 184 void* I420Buffer::native_handle() const { |
| 117 return nullptr; | 185 return nullptr; |
| 118 } | 186 } |
| 119 | 187 |
| 120 rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() { | 188 rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() { |
| 121 RTC_NOTREACHED(); | 189 RTC_NOTREACHED(); |
| 122 return nullptr; | 190 return nullptr; |
| 123 } | 191 } |
| 124 | 192 |
| 125 rtc::scoped_refptr<I420Buffer> I420Buffer::Copy( | 193 rtc::scoped_refptr<I420Buffer> I420Buffer::Copy( |
| 126 const rtc::scoped_refptr<VideoFrameBuffer>& buffer) { | 194 const rtc::scoped_refptr<VideoFrameBuffer>& buffer) { |
| 127 int width = buffer->width(); | 195 int width = buffer->width(); |
| 128 int height = buffer->height(); | 196 int height = buffer->height(); |
| 129 rtc::scoped_refptr<I420Buffer> copy = | 197 rtc::scoped_refptr<I420Buffer> copy = |
| 130 new rtc::RefCountedObject<I420Buffer>(width, height); | 198 new rtc::RefCountedObject<I420Buffer>(width, height); |
| 131 RTC_CHECK(libyuv::I420Copy(buffer->data(kYPlane), buffer->stride(kYPlane), | 199 RTC_CHECK(libyuv::I420Copy(buffer->DataY(), buffer->StrideY(), |
| 132 buffer->data(kUPlane), buffer->stride(kUPlane), | 200 buffer->DataU(), buffer->StrideU(), |
| 133 buffer->data(kVPlane), buffer->stride(kVPlane), | 201 buffer->DataV(), buffer->StrideV(), |
| 134 copy->MutableData(kYPlane), copy->stride(kYPlane), | 202 copy->MutableDataY(), copy->StrideY(), |
| 135 copy->MutableData(kUPlane), copy->stride(kUPlane), | 203 copy->MutableDataU(), copy->StrideU(), |
| 136 copy->MutableData(kVPlane), copy->stride(kVPlane), | 204 copy->MutableDataV(), copy->StrideV(), |
| 137 width, height) == 0); | 205 width, height) == 0); |
| 138 | 206 |
| 139 return copy; | 207 return copy; |
| 140 } | 208 } |
| 141 | 209 |
| 142 NativeHandleBuffer::NativeHandleBuffer(void* native_handle, | 210 NativeHandleBuffer::NativeHandleBuffer(void* native_handle, |
| 143 int width, | 211 int width, |
| 144 int height) | 212 int height) |
| 145 : native_handle_(native_handle), width_(width), height_(height) { | 213 : native_handle_(native_handle), width_(width), height_(height) { |
| 146 RTC_DCHECK(native_handle != nullptr); | 214 RTC_DCHECK(native_handle != nullptr); |
| 147 RTC_DCHECK_GT(width, 0); | 215 RTC_DCHECK_GT(width, 0); |
| 148 RTC_DCHECK_GT(height, 0); | 216 RTC_DCHECK_GT(height, 0); |
| 149 } | 217 } |
| 150 | 218 |
| 151 bool NativeHandleBuffer::IsMutable() { | 219 bool NativeHandleBuffer::IsMutable() { |
| 152 return false; | 220 return false; |
| 153 } | 221 } |
| 154 | 222 |
| 155 int NativeHandleBuffer::width() const { | 223 int NativeHandleBuffer::width() const { |
| 156 return width_; | 224 return width_; |
| 157 } | 225 } |
| 158 | 226 |
| 159 int NativeHandleBuffer::height() const { | 227 int NativeHandleBuffer::height() const { |
| 160 return height_; | 228 return height_; |
| 161 } | 229 } |
| 162 | 230 |
| 163 const uint8_t* NativeHandleBuffer::data(PlaneType type) const { | 231 const uint8_t* NativeHandleBuffer::DataY() const { |
| 232 RTC_NOTREACHED(); // Should not be called. |
| 233 return nullptr; |
| 234 } |
| 235 const uint8_t* NativeHandleBuffer::DataU() const { |
| 236 RTC_NOTREACHED(); // Should not be called. |
| 237 return nullptr; |
| 238 } |
| 239 const uint8_t* NativeHandleBuffer::DataV() const { |
| 164 RTC_NOTREACHED(); // Should not be called. | 240 RTC_NOTREACHED(); // Should not be called. |
| 165 return nullptr; | 241 return nullptr; |
| 166 } | 242 } |
| 167 | 243 |
| 168 int NativeHandleBuffer::stride(PlaneType type) const { | 244 int NativeHandleBuffer::StrideY() const { |
| 169 RTC_NOTREACHED(); // Should not be called. | 245 RTC_NOTREACHED(); // Should not be called. |
| 170 return 0; | 246 return 0; |
| 171 } | 247 } |
| 248 int NativeHandleBuffer::StrideU() const { |
| 249 RTC_NOTREACHED(); // Should not be called. |
| 250 return 0; |
| 251 } |
| 252 int NativeHandleBuffer::StrideV() const { |
| 253 RTC_NOTREACHED(); // Should not be called. |
| 254 return 0; |
| 255 } |
| 172 | 256 |
| 173 void* NativeHandleBuffer::native_handle() const { | 257 void* NativeHandleBuffer::native_handle() const { |
| 174 return native_handle_; | 258 return native_handle_; |
| 175 } | 259 } |
| 176 | 260 |
| 177 WrappedI420Buffer::WrappedI420Buffer(int width, | 261 WrappedI420Buffer::WrappedI420Buffer(int width, |
| 178 int height, | 262 int height, |
| 179 const uint8_t* y_plane, | 263 const uint8_t* y_plane, |
| 180 int y_stride, | 264 int y_stride, |
| 181 const uint8_t* u_plane, | 265 const uint8_t* u_plane, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 204 } | 288 } |
| 205 | 289 |
| 206 int WrappedI420Buffer::width() const { | 290 int WrappedI420Buffer::width() const { |
| 207 return width_; | 291 return width_; |
| 208 } | 292 } |
| 209 | 293 |
| 210 int WrappedI420Buffer::height() const { | 294 int WrappedI420Buffer::height() const { |
| 211 return height_; | 295 return height_; |
| 212 } | 296 } |
| 213 | 297 |
| 214 const uint8_t* WrappedI420Buffer::data(PlaneType type) const { | 298 const uint8_t* WrappedI420Buffer::DataY() const { |
| 215 switch (type) { | 299 return y_plane_; |
| 216 case kYPlane: | 300 } |
| 217 return y_plane_; | 301 const uint8_t* WrappedI420Buffer::DataU() const { |
| 218 case kUPlane: | 302 return u_plane_; |
| 219 return u_plane_; | 303 } |
| 220 case kVPlane: | 304 const uint8_t* WrappedI420Buffer::DataV() const { |
| 221 return v_plane_; | 305 return v_plane_; |
| 222 default: | |
| 223 RTC_NOTREACHED(); | |
| 224 return nullptr; | |
| 225 } | |
| 226 } | 306 } |
| 227 | 307 |
| 228 int WrappedI420Buffer::stride(PlaneType type) const { | 308 int WrappedI420Buffer::StrideY() const { |
| 229 switch (type) { | 309 return y_stride_; |
| 230 case kYPlane: | 310 } |
| 231 return y_stride_; | 311 int WrappedI420Buffer::StrideU() const { |
| 232 case kUPlane: | 312 return u_stride_; |
| 233 return u_stride_; | 313 } |
| 234 case kVPlane: | 314 int WrappedI420Buffer::StrideV() const { |
| 235 return v_stride_; | 315 return v_stride_; |
| 236 default: | |
| 237 RTC_NOTREACHED(); | |
| 238 return 0; | |
| 239 } | |
| 240 } | 316 } |
| 241 | 317 |
| 242 void* WrappedI420Buffer::native_handle() const { | 318 void* WrappedI420Buffer::native_handle() const { |
| 243 return nullptr; | 319 return nullptr; |
| 244 } | 320 } |
| 245 | 321 |
| 246 rtc::scoped_refptr<VideoFrameBuffer> WrappedI420Buffer::NativeToI420Buffer() { | 322 rtc::scoped_refptr<VideoFrameBuffer> WrappedI420Buffer::NativeToI420Buffer() { |
| 247 RTC_NOTREACHED(); | 323 RTC_NOTREACHED(); |
| 248 return nullptr; | 324 return nullptr; |
| 249 } | 325 } |
| 250 | 326 |
| 251 rtc::scoped_refptr<VideoFrameBuffer> ShallowCenterCrop( | 327 rtc::scoped_refptr<VideoFrameBuffer> ShallowCenterCrop( |
| 252 const rtc::scoped_refptr<VideoFrameBuffer>& buffer, | 328 const rtc::scoped_refptr<VideoFrameBuffer>& buffer, |
| 253 int cropped_width, | 329 int cropped_width, |
| 254 int cropped_height) { | 330 int cropped_height) { |
| 255 RTC_CHECK(buffer->native_handle() == nullptr); | 331 RTC_CHECK(buffer->native_handle() == nullptr); |
| 256 RTC_CHECK_LE(cropped_width, buffer->width()); | 332 RTC_CHECK_LE(cropped_width, buffer->width()); |
| 257 RTC_CHECK_LE(cropped_height, buffer->height()); | 333 RTC_CHECK_LE(cropped_height, buffer->height()); |
| 258 if (buffer->width() == cropped_width && buffer->height() == cropped_height) | 334 if (buffer->width() == cropped_width && buffer->height() == cropped_height) |
| 259 return buffer; | 335 return buffer; |
| 260 | 336 |
| 261 // Center crop to |cropped_width| x |cropped_height|. | 337 // Center crop to |cropped_width| x |cropped_height|. |
| 262 // Make sure offset is even so that u/v plane becomes aligned. | 338 // Make sure offset is even so that u/v plane becomes aligned. |
| 263 const int uv_offset_x = (buffer->width() - cropped_width) / 4; | 339 const int uv_offset_x = (buffer->width() - cropped_width) / 4; |
| 264 const int uv_offset_y = (buffer->height() - cropped_height) / 4; | 340 const int uv_offset_y = (buffer->height() - cropped_height) / 4; |
| 265 const int offset_x = uv_offset_x * 2; | 341 const int offset_x = uv_offset_x * 2; |
| 266 const int offset_y = uv_offset_y * 2; | 342 const int offset_y = uv_offset_y * 2; |
| 267 | 343 |
| 268 const uint8_t* y_plane = buffer->data(kYPlane) + | 344 const uint8_t* y_plane = buffer->DataY() + |
| 269 buffer->stride(kYPlane) * offset_y + offset_x; | 345 buffer->StrideY() * offset_y + offset_x; |
| 270 const uint8_t* u_plane = buffer->data(kUPlane) + | 346 const uint8_t* u_plane = buffer->DataU() + |
| 271 buffer->stride(kUPlane) * uv_offset_y + uv_offset_x; | 347 buffer->StrideU() * uv_offset_y + uv_offset_x; |
| 272 const uint8_t* v_plane = buffer->data(kVPlane) + | 348 const uint8_t* v_plane = buffer->DataV() + |
| 273 buffer->stride(kVPlane) * uv_offset_y + uv_offset_x; | 349 buffer->StrideV() * uv_offset_y + uv_offset_x; |
| 274 return new rtc::RefCountedObject<WrappedI420Buffer>( | 350 return new rtc::RefCountedObject<WrappedI420Buffer>( |
| 275 cropped_width, cropped_height, | 351 cropped_width, cropped_height, |
| 276 y_plane, buffer->stride(kYPlane), | 352 y_plane, buffer->StrideY(), |
| 277 u_plane, buffer->stride(kUPlane), | 353 u_plane, buffer->StrideU(), |
| 278 v_plane, buffer->stride(kVPlane), | 354 v_plane, buffer->StrideV(), |
| 279 rtc::KeepRefUntilDone(buffer)); | 355 rtc::KeepRefUntilDone(buffer)); |
| 280 } | 356 } |
| 281 | 357 |
| 282 } // namespace webrtc | 358 } // namespace webrtc |
| OLD | NEW |