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

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

Issue 2137503003: AVFoundation Video Capturer: Remove thread jump when delivering frames (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Add thread comment in TimestampAligner 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 | « webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.h ('k') | 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 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 } 589 }
590 590
591 @end 591 @end
592 592
593 namespace webrtc { 593 namespace webrtc {
594 594
595 enum AVFoundationVideoCapturerMessageType : uint32_t { 595 enum AVFoundationVideoCapturerMessageType : uint32_t {
596 kMessageTypeFrame, 596 kMessageTypeFrame,
597 }; 597 };
598 598
599 struct AVFoundationFrame { 599 AVFoundationVideoCapturer::AVFoundationVideoCapturer() : _capturer(nil) {
600 AVFoundationFrame(CVImageBufferRef buffer,
601 webrtc::VideoRotation rotation,
602 int64_t time)
603 : image_buffer(buffer), rotation(rotation), capture_time(time) {}
604 CVImageBufferRef image_buffer;
605 webrtc::VideoRotation rotation;
606 int64_t capture_time;
607 };
608
609 AVFoundationVideoCapturer::AVFoundationVideoCapturer()
610 : _capturer(nil), _startThread(nullptr) {
611 // Set our supported formats. This matches kAvailablePresets. 600 // Set our supported formats. This matches kAvailablePresets.
612 _capturer = 601 _capturer =
613 [[RTCAVFoundationVideoCapturerInternal alloc] initWithCapturer:this]; 602 [[RTCAVFoundationVideoCapturerInternal alloc] initWithCapturer:this];
614 603
615 std::vector<cricket::VideoFormat> supported_formats; 604 std::vector<cricket::VideoFormat> supported_formats;
616 int framerate = 30; 605 int framerate = 30;
617 606
618 #if TARGET_OS_IPHONE 607 #if TARGET_OS_IPHONE
619 if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) { 608 if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) {
620 set_enable_video_adapter(false); 609 set_enable_video_adapter(false);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 645
657 [_capturer.captureSession beginConfiguration]; 646 [_capturer.captureSession beginConfiguration];
658 if (![_capturer.captureSession canSetSessionPreset:desiredPreset]) { 647 if (![_capturer.captureSession canSetSessionPreset:desiredPreset]) {
659 LOG(LS_ERROR) << "Unsupported video format."; 648 LOG(LS_ERROR) << "Unsupported video format.";
660 [_capturer.captureSession commitConfiguration]; 649 [_capturer.captureSession commitConfiguration];
661 return cricket::CaptureState::CS_FAILED; 650 return cricket::CaptureState::CS_FAILED;
662 } 651 }
663 _capturer.captureSession.sessionPreset = desiredPreset; 652 _capturer.captureSession.sessionPreset = desiredPreset;
664 [_capturer.captureSession commitConfiguration]; 653 [_capturer.captureSession commitConfiguration];
665 654
666 // Keep track of which thread capture started on. This is the thread that
667 // frames need to be sent to.
668 RTC_DCHECK(!_startThread);
669 _startThread = rtc::Thread::Current();
670
671 SetCaptureFormat(&format); 655 SetCaptureFormat(&format);
672 // This isn't super accurate because it takes a while for the AVCaptureSession 656 // This isn't super accurate because it takes a while for the AVCaptureSession
673 // to spin up, and this call returns async. 657 // to spin up, and this call returns async.
674 // TODO(tkchin): make this better. 658 // TODO(tkchin): make this better.
675 [_capturer start]; 659 [_capturer start];
676 SetCaptureState(cricket::CaptureState::CS_RUNNING); 660 SetCaptureState(cricket::CaptureState::CS_RUNNING);
677 661
678 // Adjust the framerate for all capture devices. 662 // Adjust the framerate for all capture devices.
679 const auto fps = cricket::VideoFormat::IntervalToFps(format.interval); 663 const auto fps = cricket::VideoFormat::IntervalToFps(format.interval);
680 AVCaptureDevice *activeDevice = [_capturer getActiveCaptureDevice]; 664 AVCaptureDevice *activeDevice = [_capturer getActiveCaptureDevice];
681 [_capturer setMinFrameDuration:CMTimeMake(1, fps)forDevice:activeDevice]; 665 [_capturer setMinFrameDuration:CMTimeMake(1, fps)forDevice:activeDevice];
682 666
683 return cricket::CaptureState::CS_STARTING; 667 return cricket::CaptureState::CS_STARTING;
684 } 668 }
685 669
686 void AVFoundationVideoCapturer::Stop() { 670 void AVFoundationVideoCapturer::Stop() {
687 [_capturer stop]; 671 [_capturer stop];
688 SetCaptureFormat(NULL); 672 SetCaptureFormat(NULL);
689 _startThread = nullptr;
690 } 673 }
691 674
692 bool AVFoundationVideoCapturer::IsRunning() { 675 bool AVFoundationVideoCapturer::IsRunning() {
693 return _capturer.isRunning; 676 return _capturer.isRunning;
694 } 677 }
695 678
696 AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() { 679 AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() {
697 return _capturer.captureSession; 680 return _capturer.captureSession;
698 } 681 }
699 682
(...skipping 15 matching lines...) Expand all
715 !CMSampleBufferIsValid(sample_buffer) || 698 !CMSampleBufferIsValid(sample_buffer) ||
716 !CMSampleBufferDataIsReady(sample_buffer)) { 699 !CMSampleBufferDataIsReady(sample_buffer)) {
717 return; 700 return;
718 } 701 }
719 702
720 CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(sample_buffer); 703 CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(sample_buffer);
721 if (image_buffer == NULL) { 704 if (image_buffer == NULL) {
722 return; 705 return;
723 } 706 }
724 707
725 // Retain the buffer and post it to the webrtc thread. It will be released
726 // after it has successfully been signaled.
727 CVBufferRetain(image_buffer);
728 AVFoundationFrame frame(image_buffer, rotation, rtc::TimeNanos());
729 _startThread->Post(RTC_FROM_HERE, this, kMessageTypeFrame,
730 new rtc::TypedMessageData<AVFoundationFrame>(frame));
731 }
732
733 void AVFoundationVideoCapturer::OnMessage(rtc::Message *msg) {
734 switch (msg->message_id) {
735 case kMessageTypeFrame: {
736 rtc::TypedMessageData<AVFoundationFrame>* data =
737 static_cast<rtc::TypedMessageData<AVFoundationFrame>*>(msg->pdata);
738 const AVFoundationFrame& frame = data->data();
739 OnFrameMessage(frame.image_buffer, frame.rotation, frame.capture_time);
740 delete data;
741 break;
742 }
743 }
744 }
745
746 void AVFoundationVideoCapturer::OnFrameMessage(CVImageBufferRef image_buffer,
747 webrtc::VideoRotation rotation,
748 int64_t capture_time_ns) {
749 RTC_DCHECK(_startThread->IsCurrent());
750
751 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer = 708 rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer =
752 new rtc::RefCountedObject<webrtc::CoreVideoFrameBuffer>(image_buffer); 709 new rtc::RefCountedObject<webrtc::CoreVideoFrameBuffer>(image_buffer);
753 710
754 const int captured_width = buffer->width(); 711 const int captured_width = buffer->width();
755 const int captured_height = buffer->height(); 712 const int captured_height = buffer->height();
756 713
757 int adapted_width; 714 int adapted_width;
758 int adapted_height; 715 int adapted_height;
759 int crop_width; 716 int crop_width;
760 int crop_height; 717 int crop_height;
761 int crop_x; 718 int crop_x;
762 int crop_y; 719 int crop_y;
763 int64_t translated_camera_time_us; 720 int64_t translated_camera_time_us;
764 721
765 if (!AdaptFrame(captured_width, captured_height, 722 if (!AdaptFrame(captured_width, captured_height,
766 capture_time_ns / rtc::kNumNanosecsPerMicrosec, 723 rtc::TimeNanos() / rtc::kNumNanosecsPerMicrosec,
767 rtc::TimeMicros(), &adapted_width, &adapted_height, 724 rtc::TimeMicros(), &adapted_width, &adapted_height,
768 &crop_width, &crop_height, &crop_x, &crop_y, 725 &crop_width, &crop_height, &crop_x, &crop_y,
769 &translated_camera_time_us)) { 726 &translated_camera_time_us)) {
770 CVBufferRelease(image_buffer);
771 return; 727 return;
772 } 728 }
773 729
774 if (adapted_width != captured_width || crop_width != captured_width || 730 if (adapted_width != captured_width || crop_width != captured_width ||
775 adapted_height != captured_height || crop_height != captured_height || 731 adapted_height != captured_height || crop_height != captured_height ||
776 (apply_rotation() && rotation != webrtc::kVideoRotation_0)) { 732 (apply_rotation() && rotation != webrtc::kVideoRotation_0)) {
777 // TODO(magjed): Avoid converting to I420. 733 // TODO(magjed): Avoid converting to I420.
778 rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer( 734 rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer(
779 _buffer_pool.CreateBuffer(adapted_width, adapted_height)); 735 _buffer_pool.CreateBuffer(adapted_width, adapted_height));
780 scaled_buffer->CropAndScaleFrom(buffer->NativeToI420Buffer(), crop_x, 736 scaled_buffer->CropAndScaleFrom(buffer->NativeToI420Buffer(), crop_x,
(...skipping 13 matching lines...) Expand all
794 buffer->MutableDataU(), buffer->StrideU(), 750 buffer->MutableDataU(), buffer->StrideU(),
795 buffer->MutableDataV(), buffer->StrideV(), 751 buffer->MutableDataV(), buffer->StrideV(),
796 crop_width, crop_height, 752 crop_width, crop_height,
797 static_cast<libyuv::RotationMode>(rotation)); 753 static_cast<libyuv::RotationMode>(rotation));
798 } 754 }
799 } 755 }
800 756
801 OnFrame(cricket::WebRtcVideoFrame(buffer, rotation, 757 OnFrame(cricket::WebRtcVideoFrame(buffer, rotation,
802 translated_camera_time_us, 0), 758 translated_camera_time_us, 0),
803 captured_width, captured_height); 759 captured_width, captured_height);
804
805 CVBufferRelease(image_buffer);
806 } 760 }
807 761
808 } // namespace webrtc 762 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698