| 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 |