OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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/api/androidvideotracksource.h" | 11 #include "webrtc/api/androidvideotracksource.h" |
12 | 12 |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
| 15 #include "third_party/libyuv/include/libyuv/rotate.h" |
| 16 |
15 namespace webrtc { | 17 namespace webrtc { |
16 | 18 |
17 AndroidVideoTrackSource::AndroidVideoTrackSource(rtc::Thread* signaling_thread, | 19 AndroidVideoTrackSource::AndroidVideoTrackSource(rtc::Thread* signaling_thread, |
18 JNIEnv* jni, | 20 JNIEnv* jni, |
19 jobject j_egl_context, | 21 jobject j_egl_context, |
20 bool is_screencast) | 22 bool is_screencast) |
21 : signaling_thread_(signaling_thread), | 23 : signaling_thread_(signaling_thread), |
22 surface_texture_helper_(webrtc_jni::SurfaceTextureHelper::create( | 24 surface_texture_helper_(webrtc_jni::SurfaceTextureHelper::create( |
23 jni, | 25 jni, |
24 "Camera SurfaceTextureHelper", | 26 "Camera SurfaceTextureHelper", |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 int crop_x; | 101 int crop_x; |
100 int crop_y; | 102 int crop_y; |
101 int64_t translated_camera_time_us; | 103 int64_t translated_camera_time_us; |
102 | 104 |
103 if (!AdaptFrame(width, height, timestamp_ns / rtc::kNumNanosecsPerMicrosec, | 105 if (!AdaptFrame(width, height, timestamp_ns / rtc::kNumNanosecsPerMicrosec, |
104 &adapted_width, &adapted_height, &crop_width, &crop_height, | 106 &adapted_width, &adapted_height, &crop_width, &crop_height, |
105 &crop_x, &crop_y, &translated_camera_time_us)) { | 107 &crop_x, &crop_y, &translated_camera_time_us)) { |
106 return; | 108 return; |
107 } | 109 } |
108 | 110 |
109 int rotated_width = crop_width; | |
110 int rotated_height = crop_height; | |
111 | |
112 rtc::CritScope lock(&apply_rotation_crit_); | |
113 if (apply_rotation_ && (rotation == 90 || rotation == 270)) { | |
114 std::swap(adapted_width, adapted_height); | |
115 std::swap(rotated_width, rotated_height); | |
116 } | |
117 | |
118 rtc::scoped_refptr<webrtc::I420Buffer> buffer = | |
119 pre_scale_pool_.CreateBuffer(rotated_width, rotated_height); | |
120 | |
121 const uint8_t* y_plane = static_cast<const uint8_t*>(frame_data); | 111 const uint8_t* y_plane = static_cast<const uint8_t*>(frame_data); |
122 const uint8_t* uv_plane = y_plane + width * height; | 112 const uint8_t* uv_plane = y_plane + width * height; |
123 int uv_width = (width + 1) / 2; | 113 const int uv_width = (width + 1) / 2; |
124 | 114 |
125 RTC_CHECK_GE(length, width * height + 2 * uv_width * ((height + 1) / 2)); | 115 RTC_CHECK_GE(length, width * height + 2 * uv_width * ((height + 1) / 2)); |
126 | 116 |
127 // Can only crop at even pixels. | 117 // Can only crop at even pixels. |
128 crop_x &= ~1; | 118 crop_x &= ~1; |
129 crop_y &= ~1; | 119 crop_y &= ~1; |
| 120 // Crop just by modifying pointers. |
| 121 y_plane += width * crop_y + crop_x; |
| 122 uv_plane += uv_width * crop_y + crop_x; |
130 | 123 |
131 libyuv::NV12ToI420Rotate( | 124 rtc::scoped_refptr<webrtc::I420Buffer> buffer = |
132 y_plane + width * crop_y + crop_x, width, | 125 buffer_pool_.CreateBuffer(adapted_width, adapted_height); |
133 uv_plane + uv_width * crop_y + crop_x, width, buffer->MutableDataY(), | 126 |
134 buffer->StrideY(), | 127 nv12toi420_scaler_.NV12ToI420Scale( |
| 128 y_plane, width, |
| 129 uv_plane, uv_width * 2, |
| 130 crop_width, crop_height, |
| 131 buffer->MutableDataY(), buffer->StrideY(), |
135 // Swap U and V, since we have NV21, not NV12. | 132 // Swap U and V, since we have NV21, not NV12. |
136 buffer->MutableDataV(), buffer->StrideV(), buffer->MutableDataU(), | 133 buffer->MutableDataV(), buffer->StrideV(), |
137 buffer->StrideU(), crop_width, crop_height, | 134 buffer->MutableDataU(), buffer->StrideU(), |
138 static_cast<libyuv::RotationMode>(apply_rotation_ ? rotation : 0)); | 135 buffer->width(), buffer->height()); |
139 | 136 |
140 if (adapted_width != buffer->width() || adapted_height != buffer->height()) { | 137 // Applying rotation is only supported for legacy reasons, and the performance |
141 rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer( | 138 // for this path is not critical. |
142 post_scale_pool_.CreateBuffer(adapted_width, adapted_height)); | 139 rtc::CritScope lock(&apply_rotation_crit_); |
143 scaled_buffer->ScaleFrom(buffer); | 140 if (apply_rotation_ && rotation != 0) { |
144 buffer = scaled_buffer; | 141 rtc::scoped_refptr<I420Buffer> rotated_buffer = |
| 142 rotation == 180 ? I420Buffer::Create(buffer->width(), buffer->height()) |
| 143 : I420Buffer::Create(buffer->height(), buffer->width()); |
| 144 |
| 145 libyuv::I420Rotate( |
| 146 buffer->DataY(), buffer->StrideY(), |
| 147 buffer->DataU(), buffer->StrideU(), |
| 148 buffer->DataV(), buffer->StrideV(), |
| 149 rotated_buffer->MutableDataY(), rotated_buffer->StrideY(), |
| 150 rotated_buffer->MutableDataU(), rotated_buffer->StrideU(), |
| 151 rotated_buffer->MutableDataV(), rotated_buffer->StrideV(), |
| 152 buffer->width(), buffer->height(), |
| 153 static_cast<libyuv::RotationMode>(rotation)); |
| 154 |
| 155 buffer = rotated_buffer; |
145 } | 156 } |
146 | 157 |
147 OnFrame(cricket::WebRtcVideoFrame( | 158 OnFrame(cricket::WebRtcVideoFrame( |
148 buffer, | 159 buffer, |
149 apply_rotation_ ? webrtc::kVideoRotation_0 | 160 apply_rotation_ ? webrtc::kVideoRotation_0 |
150 : static_cast<webrtc::VideoRotation>(rotation), | 161 : static_cast<webrtc::VideoRotation>(rotation), |
151 translated_camera_time_us, 0), | 162 translated_camera_time_us, 0), |
152 width, height); | 163 width, height); |
153 } | 164 } |
154 | 165 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 // VideoAdapter dropped the frame. | 261 // VideoAdapter dropped the frame. |
251 return false; | 262 return false; |
252 } | 263 } |
253 *crop_x = (width - *crop_width) / 2; | 264 *crop_x = (width - *crop_width) / 2; |
254 *crop_y = (height - *crop_height) / 2; | 265 *crop_y = (height - *crop_height) / 2; |
255 | 266 |
256 return true; | 267 return true; |
257 } | 268 } |
258 | 269 |
259 } // namespace webrtc | 270 } // namespace webrtc |
OLD | NEW |