| Index: webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
|
| diff --git a/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm b/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
|
| index ddeedb5ab6ffe19aedcc48627b571bd59880cc7d..fd608fe59072b813f7a0d8579ac79989dc0c2120 100644
|
| --- a/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
|
| +++ b/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
|
| @@ -22,10 +22,13 @@
|
| #import "WebRTC/UIDevice+RTCDevice.h"
|
| #endif
|
|
|
| +#include "libyuv/rotate.h"
|
| +
|
| #include "webrtc/base/bind.h"
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/base/thread.h"
|
| #include "webrtc/common_video/include/corevideo_frame_buffer.h"
|
| +#include "webrtc/common_video/rotation.h"
|
|
|
| struct AVCaptureSessionPresetResolution {
|
| NSString *sessionPreset;
|
| @@ -98,7 +101,7 @@ static NSString *GetSessionPresetForVideoFormat(
|
| AVCaptureVideoDataOutput *_videoDataOutput;
|
| // The cricket::VideoCapturer that owns this class. Should never be NULL.
|
| webrtc::AVFoundationVideoCapturer *_capturer;
|
| - BOOL _orientationHasChanged;
|
| + webrtc::VideoRotation _rotation;
|
| BOOL _hasRetriedOnFatalError;
|
| BOOL _isRunning;
|
| BOOL _hasStarted;
|
| @@ -228,7 +231,14 @@ static NSString *GetSessionPresetForVideoFormat(
|
| self.hasStarted = YES;
|
| [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
|
| block:^{
|
| - _orientationHasChanged = NO;
|
| +#if TARGET_OS_IPHONE
|
| + // Default to portrait orientation on iPhone. This will be reset in
|
| + // updateOrientation unless orientation is unknown/faceup/facedown.
|
| + _rotation = webrtc::kVideoRotation_90;
|
| +#else
|
| + // No rotation on Mac.
|
| + _rotation = webrtc::kVideoRotation_0;
|
| +#endif
|
| [self updateOrientation];
|
| #if TARGET_OS_IPHONE
|
| [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
|
| @@ -263,7 +273,6 @@ static NSString *GetSessionPresetForVideoFormat(
|
| - (void)deviceOrientationDidChange:(NSNotification *)notification {
|
| [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
|
| block:^{
|
| - _orientationHasChanged = YES;
|
| [self updateOrientation];
|
| }];
|
| }
|
| @@ -278,7 +287,7 @@ static NSString *GetSessionPresetForVideoFormat(
|
| if (!self.hasStarted) {
|
| return;
|
| }
|
| - _capturer->CaptureSampleBuffer(sampleBuffer);
|
| + _capturer->CaptureSampleBuffer(sampleBuffer, _rotation);
|
| }
|
|
|
| - (void)captureOutput:(AVCaptureOutput *)captureOutput
|
| @@ -510,36 +519,26 @@ static NSString *GetSessionPresetForVideoFormat(
|
|
|
| // Called from capture session queue.
|
| - (void)updateOrientation {
|
| - AVCaptureConnection *connection =
|
| - [_videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
|
| - if (!connection.supportsVideoOrientation) {
|
| - // TODO(tkchin): set rotation bit on frames.
|
| - return;
|
| - }
|
| #if TARGET_OS_IPHONE
|
| - AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationPortrait;
|
| switch ([UIDevice currentDevice].orientation) {
|
| case UIDeviceOrientationPortrait:
|
| - orientation = AVCaptureVideoOrientationPortrait;
|
| + _rotation = webrtc::kVideoRotation_90;
|
| break;
|
| case UIDeviceOrientationPortraitUpsideDown:
|
| - orientation = AVCaptureVideoOrientationPortraitUpsideDown;
|
| + _rotation = webrtc::kVideoRotation_270;
|
| break;
|
| case UIDeviceOrientationLandscapeLeft:
|
| - orientation = AVCaptureVideoOrientationLandscapeRight;
|
| + _rotation = webrtc::kVideoRotation_180;
|
| break;
|
| case UIDeviceOrientationLandscapeRight:
|
| - orientation = AVCaptureVideoOrientationLandscapeLeft;
|
| + _rotation = webrtc::kVideoRotation_0;
|
| break;
|
| case UIDeviceOrientationFaceUp:
|
| case UIDeviceOrientationFaceDown:
|
| case UIDeviceOrientationUnknown:
|
| - if (!_orientationHasChanged) {
|
| - connection.videoOrientation = orientation;
|
| - }
|
| - return;
|
| + // Ignore.
|
| + break;
|
| }
|
| - connection.videoOrientation = orientation;
|
| #endif
|
| }
|
|
|
| @@ -578,9 +577,12 @@ enum AVFoundationVideoCapturerMessageType : uint32_t {
|
| };
|
|
|
| struct AVFoundationFrame {
|
| - AVFoundationFrame(CVImageBufferRef buffer, int64_t time)
|
| - : image_buffer(buffer), capture_time(time) {}
|
| + AVFoundationFrame(CVImageBufferRef buffer,
|
| + webrtc::VideoRotation rotation,
|
| + int64_t time)
|
| + : image_buffer(buffer), rotation(rotation), capture_time(time) {}
|
| CVImageBufferRef image_buffer;
|
| + webrtc::VideoRotation rotation;
|
| int64_t capture_time;
|
| };
|
|
|
| @@ -688,14 +690,14 @@ bool AVFoundationVideoCapturer::GetUseBackCamera() const {
|
| }
|
|
|
| void AVFoundationVideoCapturer::CaptureSampleBuffer(
|
| - CMSampleBufferRef sampleBuffer) {
|
| - if (CMSampleBufferGetNumSamples(sampleBuffer) != 1 ||
|
| - !CMSampleBufferIsValid(sampleBuffer) ||
|
| - !CMSampleBufferDataIsReady(sampleBuffer)) {
|
| + CMSampleBufferRef sample_buffer, webrtc::VideoRotation rotation) {
|
| + if (CMSampleBufferGetNumSamples(sample_buffer) != 1 ||
|
| + !CMSampleBufferIsValid(sample_buffer) ||
|
| + !CMSampleBufferDataIsReady(sample_buffer)) {
|
| return;
|
| }
|
|
|
| - CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
| + CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(sample_buffer);
|
| if (image_buffer == NULL) {
|
| return;
|
| }
|
| @@ -703,7 +705,7 @@ void AVFoundationVideoCapturer::CaptureSampleBuffer(
|
| // Retain the buffer and post it to the webrtc thread. It will be released
|
| // after it has successfully been signaled.
|
| CVBufferRetain(image_buffer);
|
| - AVFoundationFrame frame(image_buffer, rtc::TimeNanos());
|
| + AVFoundationFrame frame(image_buffer, rotation, rtc::TimeNanos());
|
| _startThread->Post(RTC_FROM_HERE, this, kMessageTypeFrame,
|
| new rtc::TypedMessageData<AVFoundationFrame>(frame));
|
| }
|
| @@ -714,7 +716,7 @@ void AVFoundationVideoCapturer::OnMessage(rtc::Message *msg) {
|
| rtc::TypedMessageData<AVFoundationFrame>* data =
|
| static_cast<rtc::TypedMessageData<AVFoundationFrame>*>(msg->pdata);
|
| const AVFoundationFrame& frame = data->data();
|
| - OnFrameMessage(frame.image_buffer, frame.capture_time);
|
| + OnFrameMessage(frame.image_buffer, frame.rotation, frame.capture_time);
|
| delete data;
|
| break;
|
| }
|
| @@ -722,6 +724,7 @@ void AVFoundationVideoCapturer::OnMessage(rtc::Message *msg) {
|
| }
|
|
|
| void AVFoundationVideoCapturer::OnFrameMessage(CVImageBufferRef image_buffer,
|
| + webrtc::VideoRotation rotation,
|
| int64_t capture_time_ns) {
|
| RTC_DCHECK(_startThread->IsCurrent());
|
|
|
| @@ -749,16 +752,33 @@ void AVFoundationVideoCapturer::OnFrameMessage(CVImageBufferRef image_buffer,
|
| }
|
|
|
| if (adapted_width != captured_width || crop_width != captured_width ||
|
| - adapted_height != captured_height || crop_height != captured_height) {
|
| + adapted_height != captured_height || crop_height != captured_height ||
|
| + (apply_rotation() && rotation != webrtc::kVideoRotation_0)) {
|
| // TODO(magjed): Avoid converting to I420.
|
| rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer(
|
| _buffer_pool.CreateBuffer(adapted_width, adapted_height));
|
| scaled_buffer->CropAndScaleFrom(buffer->NativeToI420Buffer(), crop_x,
|
| crop_y, crop_width, crop_height);
|
| - buffer = scaled_buffer;
|
| + if (!apply_rotation() || rotation == webrtc::kVideoRotation_0) {
|
| + buffer = scaled_buffer;
|
| + } else {
|
| + // Applying rotation is only supported for legacy reasons and performance
|
| + // is not critical here.
|
| + buffer = (rotation == webrtc::kVideoRotation_180)
|
| + ? I420Buffer::Create(adapted_width, adapted_height)
|
| + : I420Buffer::Create(adapted_height, adapted_width);
|
| + libyuv::I420Rotate(scaled_buffer->DataY(), scaled_buffer->StrideY(),
|
| + scaled_buffer->DataU(), scaled_buffer->StrideU(),
|
| + scaled_buffer->DataV(), scaled_buffer->StrideV(),
|
| + buffer->MutableDataY(), buffer->StrideY(),
|
| + buffer->MutableDataU(), buffer->StrideU(),
|
| + buffer->MutableDataV(), buffer->StrideV(),
|
| + crop_width, crop_height,
|
| + static_cast<libyuv::RotationMode>(rotation));
|
| + }
|
| }
|
|
|
| - OnFrame(cricket::WebRtcVideoFrame(buffer, webrtc::kVideoRotation_0,
|
| + OnFrame(cricket::WebRtcVideoFrame(buffer, rotation,
|
| translated_camera_time_us, 0),
|
| captured_width, captured_height);
|
|
|
|
|