Index: webrtc/api/java/jni/androidvideocapturer_jni.cc |
diff --git a/webrtc/api/java/jni/androidvideocapturer_jni.cc b/webrtc/api/java/jni/androidvideocapturer_jni.cc |
index 615fcb32d80c30895e4958215e96be5ef5ed9dda..3743adfed37e50e27faf2cf2f1e107fed92c4297 100644 |
--- a/webrtc/api/java/jni/androidvideocapturer_jni.cc |
+++ b/webrtc/api/java/jni/androidvideocapturer_jni.cc |
@@ -169,21 +169,62 @@ void AndroidVideoCapturerJni::OnMemoryBufferFrame(void* video_frame, |
int height, |
int rotation, |
int64_t timestamp_ns) { |
- const uint8_t* y_plane = static_cast<uint8_t*>(video_frame); |
- const uint8_t* vu_plane = y_plane + width * height; |
+ RTC_DCHECK(rotation == 0 || rotation == 90 || rotation == 180 || |
+ rotation == 270); |
+ rtc::CritScope cs(&capturer_lock_); |
+ |
+ int adapted_width; |
+ int adapted_height; |
+ int crop_width; |
+ int crop_height; |
+ int crop_x; |
+ int crop_y; |
+ |
+ if (!capturer_->AdaptFrame(width, height, &adapted_width, &adapted_height, |
+ &crop_width, &crop_height, &crop_x, &crop_y)) { |
+ return; |
+ } |
+ |
+ int rotated_width = crop_width; |
+ int rotated_height = crop_height; |
+ |
+ if (capturer_->apply_rotation() && (rotation == 90 || rotation == 270)) { |
+ std::swap(adapted_width, adapted_height); |
+ std::swap(rotated_width, rotated_height); |
+ } |
rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = |
- buffer_pool_.CreateBuffer(width, height); |
- libyuv::NV21ToI420( |
- y_plane, width, |
- vu_plane, width, |
+ buffer_pool_.CreateBuffer(rotated_width, rotated_height); |
+ |
+ const uint8_t* y_plane = static_cast<const uint8_t*>(video_frame); |
+ const uint8_t* uv_plane = y_plane + width * height; |
+ |
+ // Can only crop at even pixels. |
+ crop_x &= ~1; |
magjed_webrtc
2016/05/18 15:45:30
The same is true for crop_y.
nisse-webrtc
2016/05/18 16:34:17
Done.
|
+ |
+ libyuv::NV12ToI420Rotate( |
+ y_plane + width * crop_y + crop_x, width, |
+ uv_plane + width * crop_y + crop_x, width, |
magjed_webrtc
2016/05/18 15:45:30
crop_y is not used correctly, it should be roughly
nisse-webrtc
2016/05/18 16:34:17
If crop_y is forced to be even (fixed above), then
|
buffer->MutableData(webrtc::kYPlane), buffer->stride(webrtc::kYPlane), |
- buffer->MutableData(webrtc::kUPlane), buffer->stride(webrtc::kUPlane), |
+ // Swap U and V, since we have NV21, not NV12. |
buffer->MutableData(webrtc::kVPlane), buffer->stride(webrtc::kVPlane), |
- width, height); |
- AsyncCapturerInvoke("OnIncomingFrame", |
- &webrtc::AndroidVideoCapturer::OnIncomingFrame, |
- buffer, rotation, timestamp_ns); |
+ buffer->MutableData(webrtc::kUPlane), buffer->stride(webrtc::kUPlane), |
+ crop_width, crop_height, static_cast<libyuv::RotationMode>( |
+ capturer_->apply_rotation() ? rotation : 0)); |
+ |
+ if (adapted_width != rotated_width || adapted_height != rotated_height) { |
+ // TODO(nisse): Use buffer_pool_ here? |
magjed_webrtc
2016/05/18 15:45:30
Yes, use a buffer pool here.
nisse-webrtc
2016/05/18 16:34:17
Two buffer pools it is, then. But it would be nice
|
+ buffer = webrtc::I420Buffer::CropAndScale(buffer, 0, 0, |
+ rotated_width, rotated_height, |
+ adapted_width, adapted_height); |
+ } |
+ // TODO(nisse): Use microsecond time instead. |
+ capturer_->OnFrame(cricket::WebRtcVideoFrame( |
+ buffer, timestamp_ns, |
+ capturer_->apply_rotation() |
+ ? webrtc::kVideoRotation_0 |
+ : static_cast<webrtc::VideoRotation>(rotation)), |
+ width, height); |
} |
void AndroidVideoCapturerJni::OnTextureFrame(int width, |
@@ -191,12 +232,47 @@ void AndroidVideoCapturerJni::OnTextureFrame(int width, |
int rotation, |
int64_t timestamp_ns, |
const NativeHandleImpl& handle) { |
- rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( |
- surface_texture_helper_->CreateTextureFrame(width, height, handle)); |
+ RTC_DCHECK(rotation == 0 || rotation == 90 || rotation == 180 || |
+ rotation == 270); |
+ rtc::CritScope cs(&capturer_lock_); |
- AsyncCapturerInvoke("OnIncomingFrame", |
- &webrtc::AndroidVideoCapturer::OnIncomingFrame, |
- buffer, rotation, timestamp_ns); |
+ int adapted_width; |
+ int adapted_height; |
+ int crop_width; |
+ int crop_height; |
+ int crop_x; |
+ int crop_y; |
+ |
+ if (!capturer_->AdaptFrame(width, height, &adapted_width, &adapted_height, |
+ &crop_width, &crop_height, &crop_x, &crop_y)) { |
+ return; |
+ } |
+ |
+ Matrix matrix = handle.sampling_matrix; |
+ |
+ matrix.Crop(crop_width / static_cast<float>(width), |
+ crop_height / static_cast<float>(height), |
+ crop_x / static_cast<float>(width), |
+ crop_y / static_cast<float>(height)); |
+ |
+ if (capturer_->apply_rotation()) { |
+ if (rotation == webrtc::kVideoRotation_90 || |
+ rotation == webrtc::kVideoRotation_270) { |
+ std::swap(adapted_width, adapted_height); |
+ } |
+ matrix.Rotate(static_cast<webrtc::VideoRotation>(rotation)); |
+ } |
+ |
+ // TODO(nisse): Use microsecond time instead. |
+ capturer_->OnFrame( |
+ cricket::WebRtcVideoFrame( |
+ surface_texture_helper_->CreateTextureFrame( |
+ adapted_width, adapted_height, |
+ NativeHandleImpl(handle.oes_texture_id, matrix)), |
+ timestamp_ns, capturer_->apply_rotation() |
+ ? webrtc::kVideoRotation_0 |
+ : static_cast<webrtc::VideoRotation>(rotation)), |
+ width, height); |
} |
void AndroidVideoCapturerJni::OnOutputFormatRequest(int width, |