OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |