Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm

Issue 2349223002: Replace SessionPresets with AVCaptureDeviceFormats (Closed)
Patch Set: Remove unused method Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright 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
(...skipping 12 matching lines...) Expand all
23 #endif 23 #endif
24 24
25 #include "libyuv/rotate.h" 25 #include "libyuv/rotate.h"
26 26
27 #include "webrtc/base/bind.h" 27 #include "webrtc/base/bind.h"
28 #include "webrtc/base/checks.h" 28 #include "webrtc/base/checks.h"
29 #include "webrtc/base/thread.h" 29 #include "webrtc/base/thread.h"
30 #include "webrtc/common_video/include/corevideo_frame_buffer.h" 30 #include "webrtc/common_video/include/corevideo_frame_buffer.h"
31 #include "webrtc/common_video/rotation.h" 31 #include "webrtc/common_video/rotation.h"
32 32
33 struct AVCaptureSessionPresetResolution { 33 // Maping from cricket::VideoFormat to AVCaptureDeviceFormat.
kthelgason 2016/09/20 07:00:30 nit: mapping
34 NSString *sessionPreset; 34 static AVCaptureDeviceFormat *GetDeviceFormatForVideoFormat(const AVCaptureDevic e *device,
35 int width; 35 const cricket::Video Format& videoFormat) {
36 int height;
37 };
38 36
39 #if TARGET_OS_IPHONE 37 AVCaptureDeviceFormat *desiredDeviceFormat = nil;
40 static const AVCaptureSessionPresetResolution kAvailablePresets[] = { 38 for (AVCaptureDeviceFormat *deviceFormat in [device formats]) {
41 { AVCaptureSessionPreset352x288, 352, 288}, 39 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions([deviceF ormat formatDescription]);
42 { AVCaptureSessionPreset640x480, 640, 480}, 40 FourCharCode code = CMFormatDescriptionGetMediaSubType([deviceFormat formatD escription]);
43 { AVCaptureSessionPreset1280x720, 1280, 720},
44 { AVCaptureSessionPreset1920x1080, 1920, 1080},
45 };
46 #else // macOS
47 static const AVCaptureSessionPresetResolution kAvailablePresets[] = {
48 { AVCaptureSessionPreset320x240, 320, 240},
49 { AVCaptureSessionPreset352x288, 352, 288},
50 { AVCaptureSessionPreset640x480, 640, 480},
51 { AVCaptureSessionPreset960x540, 960, 540},
52 { AVCaptureSessionPreset1280x720, 1280, 720},
53 };
54 #endif
55 41
56 // Mapping from cricket::VideoFormat to AVCaptureSession presets. 42 if (code != kCVPixelFormatType_420YpCbCr8BiPlanarFullRange &&
57 static NSString *GetSessionPresetForVideoFormat( 43 code !=kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) {
58 const cricket::VideoFormat& format) { 44 continue;
59 for (const auto preset : kAvailablePresets) { 45 }
60 // Check both orientations 46
61 if ((format.width == preset.width && format.height == preset.height) || 47 if (videoFormat.width == dimension.width && videoFormat.height == dimension. height) {
magjed_webrtc 2016/09/20 08:42:18 Shouldn't we also look at fps? Maybe it would be b
daniela-webrtc 2016/09/26 11:03:15 Acknowledged.
62 (format.width == preset.height && format.height == preset.width)) { 48 if (code == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
63 return preset.sessionPreset; 49 //this is the preferred format so no need to wait for better option
50 return deviceFormat;
51 } else {
52 //this is good candidate, but let's wait for something better
53 desiredDeviceFormat = deviceFormat;
54 }
64 } 55 }
65 } 56 }
66 // If no matching preset is found, use a default one. 57 return desiredDeviceFormat;
67 return AVCaptureSessionPreset640x480; 58 }
59
60 // Mapping from AVCaptureDeviceFormat to cricket::VideoFormat for given input de vice.
61 static std::vector<cricket::VideoFormat> GetSupportedVideoFormatsForDevice(AVCap tureDevice *device) {
62 std::vector<cricket::VideoFormat> supportedFormats;
63
64 for (AVCaptureDeviceFormat *deviceFormat in [device formats]) {
65 FourCharCode code = CMFormatDescriptionGetMediaSubType([deviceFormat formatD escription]);
66
67 if (code != kCVPixelFormatType_420YpCbCr8BiPlanarFullRange &&
68 code !=kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) {
kthelgason 2016/09/20 07:00:30 nit: missing space
daniela-webrtc 2016/09/23 08:49:17 Acknowledged.
69 continue;
70 }
71
72 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions([deviceF ormat formatDescription]);
73
74 for (AVFrameRateRange* frameRate in [deviceFormat videoSupportedFrameRateRan ges]) {
75 Float64 fps = frameRate.maxFrameRate;
kthelgason 2016/09/20 07:00:30 is there a need to introduce this variable?
daniela-webrtc 2016/09/26 11:03:15 Acknowledged.
76 int64_t interval = cricket::VideoFormat::FpsToInterval(fps);
77 cricket::VideoFormat format = cricket::VideoFormat(dimension.width,
78 dimension.height,
79 interval,
80 cricket::FOURCC_NV12);
81
82 std::vector<cricket::VideoFormat>::iterator iterator = std::find(supported Formats.begin(),
kthelgason 2016/09/20 07:00:30 I'd go for auto here, this type is very unwieldy.
daniela-webrtc 2016/09/23 08:49:17 This will no longer be needed once I implement the
83 supported Formats.end(),
84 format);
85 if (iterator != supportedFormats.end()) {
86 continue;
87 } else {
88 supportedFormats.push_back(format);
89 }
90 }
kthelgason 2016/09/20 07:00:30 We might be better off just using a std::set for s
magjed_webrtc 2016/09/20 08:42:18 +1 Go with a std::set, it should simplify the code
daniela-webrtc 2016/09/23 08:49:17 Acknowledged.
91 }
92 return supportedFormats;
68 } 93 }
69 94
70 // This class used to capture frames using AVFoundation APIs on iOS. It is meant 95 // This class used to capture frames using AVFoundation APIs on iOS. It is meant
71 // to be owned by an instance of AVFoundationVideoCapturer. The reason for this 96 // to be owned by an instance of AVFoundationVideoCapturer. The reason for this
72 // because other webrtc objects own cricket::VideoCapturer, which is not 97 // because other webrtc objects own cricket::VideoCapturer, which is not
73 // ref counted. To prevent bad behavior we do not expose this class directly. 98 // ref counted. To prevent bad behavior we do not expose this class directly.
74 @interface RTCAVFoundationVideoCapturerInternal : NSObject 99 @interface RTCAVFoundationVideoCapturerInternal : NSObject
75 <AVCaptureVideoDataOutputSampleBufferDelegate> 100 <AVCaptureVideoDataOutputSampleBufferDelegate>
76 101
77 @property(nonatomic, readonly) AVCaptureSession *captureSession; 102 @property(nonatomic, readonly) AVCaptureSession *captureSession;
78 @property(nonatomic, readonly) dispatch_queue_t frameQueue; 103 @property(nonatomic, readonly) dispatch_queue_t frameQueue;
79 @property(nonatomic, readonly) BOOL canUseBackCamera; 104 @property(nonatomic, readonly) BOOL canUseBackCamera;
80 @property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO. 105 @property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
81 @property(nonatomic, assign) BOOL isRunning; // Whether the capture session is running. 106 @property(nonatomic, assign) BOOL isRunning; // Whether the capture session is running.
82 @property(atomic, assign) BOOL hasStarted; // Whether we have an unmatched star t. 107 @property(atomic, assign) BOOL hasStarted; // Whether we have an unmatched star t.
83 108
84 // We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it 109 // We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
85 // when we receive frames. This is safe because this object should be owned by 110 // when we receive frames. This is safe because this object should be owned by
86 // it. 111 // it.
87 - (instancetype)initWithCapturer:(webrtc::AVFoundationVideoCapturer *)capturer; 112 - (instancetype)initWithCapturer:(webrtc::AVFoundationVideoCapturer *)capturer;
88 - (AVCaptureDevice *)getActiveCaptureDevice; 113 - (AVCaptureDevice *)getActiveCaptureDevice;
89 114
115 - (nullable AVCaptureDevice *)frontCaptureDevice;
116 - (nullable AVCaptureDevice *)backCaptureDevice;
117
90 // Starts and stops the capture session asynchronously. We cannot do this 118 // Starts and stops the capture session asynchronously. We cannot do this
91 // synchronously without blocking a WebRTC thread. 119 // synchronously without blocking a WebRTC thread.
92 - (void)start; 120 - (void)start;
93 - (void)stop; 121 - (void)stop;
94 122
95 @end 123 @end
96 124
97 @implementation RTCAVFoundationVideoCapturerInternal { 125 @implementation RTCAVFoundationVideoCapturerInternal {
98 // Keep pointers to inputs for convenience. 126 // Keep pointers to inputs for convenience.
99 AVCaptureDeviceInput *_frontCameraInput; 127 AVCaptureDeviceInput *_frontCameraInput;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 196 }
169 197
170 - (AVCaptureSession *)captureSession { 198 - (AVCaptureSession *)captureSession {
171 return _captureSession; 199 return _captureSession;
172 } 200 }
173 201
174 - (AVCaptureDevice *)getActiveCaptureDevice { 202 - (AVCaptureDevice *)getActiveCaptureDevice {
175 return self.useBackCamera ? _backCameraInput.device : _frontCameraInput.device ; 203 return self.useBackCamera ? _backCameraInput.device : _frontCameraInput.device ;
176 } 204 }
177 205
206 - (AVCaptureDevice *)frontCaptureDevice {
207 return _frontCameraInput.device;
208 }
209
210 - (AVCaptureDevice *)backCaptureDevice {
211 return _backCameraInput.device;
212 }
213
214
178 - (dispatch_queue_t)frameQueue { 215 - (dispatch_queue_t)frameQueue {
179 if (!_frameQueue) { 216 if (!_frameQueue) {
180 _frameQueue = 217 _frameQueue =
181 dispatch_queue_create("org.webrtc.avfoundationvideocapturer.video", 218 dispatch_queue_create("org.webrtc.avfoundationvideocapturer.video",
182 DISPATCH_QUEUE_SERIAL); 219 DISPATCH_QUEUE_SERIAL);
183 dispatch_set_target_queue( 220 dispatch_set_target_queue(
184 _frameQueue, 221 _frameQueue,
185 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)); 222 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
186 } 223 }
187 return _frameQueue; 224 return _frameQueue;
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 627
591 @end 628 @end
592 629
593 namespace webrtc { 630 namespace webrtc {
594 631
595 enum AVFoundationVideoCapturerMessageType : uint32_t { 632 enum AVFoundationVideoCapturerMessageType : uint32_t {
596 kMessageTypeFrame, 633 kMessageTypeFrame,
597 }; 634 };
598 635
599 AVFoundationVideoCapturer::AVFoundationVideoCapturer() : _capturer(nil) { 636 AVFoundationVideoCapturer::AVFoundationVideoCapturer() : _capturer(nil) {
600 // Set our supported formats. This matches kAvailablePresets. 637 _capturer = [[RTCAVFoundationVideoCapturerInternal alloc] initWithCapturer:thi s];
601 _capturer =
602 [[RTCAVFoundationVideoCapturerInternal alloc] initWithCapturer:this];
603 638
604 std::vector<cricket::VideoFormat> supported_formats; 639 std::vector<cricket::VideoFormat> frontCameraSupportedVideoFormats =
605 int framerate = 30; 640 GetSupportedVideoFormatsForDevice([_capturer frontCaptureDevice]);
641 std::vector<cricket::VideoFormat> backCameraSupportedVideoFormats =
kthelgason 2016/09/20 07:00:30 I would use auto for all these types, I try to use
magjed_webrtc 2016/09/20 08:42:18 See https://google.github.io/styleguide/cppguide.h
642 GetSupportedVideoFormatsForDevice([_capturer backCaptureDevice]);
606 643
607 #if TARGET_OS_IPHONE 644 std::sort(frontCameraSupportedVideoFormats.begin(), frontCameraSupportedVideoF ormats.end());
608 if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) { 645 std::sort(backCameraSupportedVideoFormats.begin(), backCameraSupportedVideoFor mats.end());
609 set_enable_video_adapter(false);
610 framerate = 15;
611 }
612 #endif
613 646
614 for (const auto preset : kAvailablePresets) { 647 std::vector<cricket::VideoFormat> intersectionVideoFormats;
615 if ([_capturer.captureSession canSetSessionPreset:preset.sessionPreset]) { 648 std::set_intersection(frontCameraSupportedVideoFormats.begin(),
616 const auto format = cricket::VideoFormat( 649 frontCameraSupportedVideoFormats.end(),
617 preset.width, 650 backCameraSupportedVideoFormats.begin(),
618 preset.height, 651 backCameraSupportedVideoFormats.end(),
619 cricket::VideoFormat::FpsToInterval(framerate), 652 std::back_inserter(intersectionVideoFormats));
620 cricket::FOURCC_NV12);
621 supported_formats.push_back(format);
622 }
623 }
624 653
625 SetSupportedFormats(supported_formats); 654 SetSupportedFormats(intersectionVideoFormats);
626 } 655 }
627 656
628 AVFoundationVideoCapturer::~AVFoundationVideoCapturer() { 657 AVFoundationVideoCapturer::~AVFoundationVideoCapturer() {
629 _capturer = nil; 658 _capturer = nil;
630 } 659 }
631 660
632 cricket::CaptureState AVFoundationVideoCapturer::Start( 661 cricket::CaptureState AVFoundationVideoCapturer::Start(
633 const cricket::VideoFormat& format) { 662 const cricket::VideoFormat& format) {
634 if (!_capturer) { 663 if (!_capturer) {
635 LOG(LS_ERROR) << "Failed to create AVFoundation capturer."; 664 LOG(LS_ERROR) << "Failed to create AVFoundation capturer.";
636 return cricket::CaptureState::CS_FAILED; 665 return cricket::CaptureState::CS_FAILED;
637 } 666 }
638 if (_capturer.isRunning) { 667 if (_capturer.isRunning) {
639 LOG(LS_ERROR) << "The capturer is already running."; 668 LOG(LS_ERROR) << "The capturer is already running.";
640 return cricket::CaptureState::CS_FAILED; 669 return cricket::CaptureState::CS_FAILED;
641 } 670 }
642 671
643 NSString *desiredPreset = GetSessionPresetForVideoFormat(format); 672 AVCaptureDeviceFormat *deviceFormat =
644 RTC_DCHECK(desiredPreset); 673 GetDeviceFormatForVideoFormat([_capturer getActiveCaptureDevice], format);
magjed_webrtc 2016/09/20 08:42:18 You need to indent the new line with 4 spaces. htt
daniela-webrtc 2016/09/26 11:03:15 Acknowledged.
674 AVCaptureDevice *device = [_capturer getActiveCaptureDevice];
675 AVCaptureSession *session = [_capturer captureSession];
676 NSError *error = nil;
645 677
646 [_capturer.captureSession beginConfiguration]; 678 [session beginConfiguration]; // the session to which the receiver's AVCapture DeviceInput is added.
kthelgason 2016/09/20 07:00:30 Is this necessary when only re-configuring the dev
daniela-webrtc 2016/09/23 08:49:17 Yes. Because this essentially causes the session t
647 if (![_capturer.captureSession canSetSessionPreset:desiredPreset]) { 679 if ([device lockForConfiguration:&error]) {
648 LOG(LS_ERROR) << "Unsupported video format."; 680 @try {
649 [_capturer.captureSession commitConfiguration]; 681 [device setActiveFormat:deviceFormat];
650 return cricket::CaptureState::CS_FAILED; 682 } @catch (NSException *exception) {
683 LOG(LS_ERROR) << [NSString stringWithFormat:
684 @"Exception occured while setting active format!\n User info:%@", exception.userInfo];
685 return cricket::CaptureState::CS_FAILED;
686 }
687
688 [device unlockForConfiguration];
651 } 689 }
652 _capturer.captureSession.sessionPreset = desiredPreset; 690
653 [_capturer.captureSession commitConfiguration]; 691 [session commitConfiguration];
654 692
655 SetCaptureFormat(&format); 693 SetCaptureFormat(&format);
656 // This isn't super accurate because it takes a while for the AVCaptureSession 694 // This isn't super accurate because it takes a while for the AVCaptureSession
657 // to spin up, and this call returns async. 695 // to spin up, and this call returns async.
658 // TODO(tkchin): make this better. 696 // TODO(tkchin): make this better.
659 [_capturer start]; 697 [_capturer start];
660 SetCaptureState(cricket::CaptureState::CS_RUNNING); 698 SetCaptureState(cricket::CaptureState::CS_RUNNING);
661 699
662 // Adjust the framerate for all capture devices. 700 // Adjust the framerate for all capture devices.
663 const auto fps = cricket::VideoFormat::IntervalToFps(format.interval); 701 const auto fps = cricket::VideoFormat::IntervalToFps(format.interval);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 buffer = rotated_buffer; 794 buffer = rotated_buffer;
757 } 795 }
758 } 796 }
759 797
760 OnFrame(cricket::WebRtcVideoFrame(buffer, rotation, 798 OnFrame(cricket::WebRtcVideoFrame(buffer, rotation,
761 translated_camera_time_us, 0), 799 translated_camera_time_us, 0),
762 captured_width, captured_height); 800 captured_width, captured_height);
763 } 801 }
764 802
765 } // namespace webrtc 803 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698