1/* 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "sdk/objc/native/src/objc_video_track_source.h" 12 13#import "base/RTCVideoFrame.h" 14#import "base/RTCVideoFrameBuffer.h" 15#import "components/video_frame_buffer/RTCCVPixelBuffer.h" 16 17#include "api/video/i420_buffer.h" 18#include "sdk/objc/native/src/objc_frame_buffer.h" 19 20@interface RTCObjCVideoSourceAdapter () 21@property(nonatomic) webrtc::ObjCVideoTrackSource *objCVideoTrackSource; 22@end 23 24@implementation RTCObjCVideoSourceAdapter 25 26@synthesize objCVideoTrackSource = _objCVideoTrackSource; 27 28- (void)capturer:(RTC_OBJC_TYPE(RTCVideoCapturer) *)capturer 29 didCaptureVideoFrame:(RTC_OBJC_TYPE(RTCVideoFrame) *)frame { 30 _objCVideoTrackSource->OnCapturedFrame(frame); 31} 32 33@end 34 35namespace webrtc { 36 37ObjCVideoTrackSource::ObjCVideoTrackSource() 38 : AdaptedVideoTrackSource(/* required resolution alignment */ 2) {} 39 40ObjCVideoTrackSource::ObjCVideoTrackSource(RTCObjCVideoSourceAdapter *adapter) : adapter_(adapter) { 41 adapter_.objCVideoTrackSource = this; 42} 43 44bool ObjCVideoTrackSource::is_screencast() const { 45 return false; 46} 47 48absl::optional<bool> ObjCVideoTrackSource::needs_denoising() const { 49 return false; 50} 51 52MediaSourceInterface::SourceState ObjCVideoTrackSource::state() const { 53 return SourceState::kLive; 54} 55 56bool ObjCVideoTrackSource::remote() const { 57 return false; 58} 59 60void ObjCVideoTrackSource::OnOutputFormatRequest(int width, int height, int fps) { 61 cricket::VideoFormat format(width, height, cricket::VideoFormat::FpsToInterval(fps), 0); 62 video_adapter()->OnOutputFormatRequest(format); 63} 64 65void ObjCVideoTrackSource::OnCapturedFrame(RTC_OBJC_TYPE(RTCVideoFrame) * frame) { 66 const int64_t timestamp_us = frame.timeStampNs / rtc::kNumNanosecsPerMicrosec; 67 const int64_t translated_timestamp_us = 68 timestamp_aligner_.TranslateTimestamp(timestamp_us, rtc::TimeMicros()); 69 70 int adapted_width; 71 int adapted_height; 72 int crop_width; 73 int crop_height; 74 int crop_x; 75 int crop_y; 76 if (!AdaptFrame(frame.width, 77 frame.height, 78 timestamp_us, 79 &adapted_width, 80 &adapted_height, 81 &crop_width, 82 &crop_height, 83 &crop_x, 84 &crop_y)) { 85 return; 86 } 87 88 rtc::scoped_refptr<VideoFrameBuffer> buffer; 89 if (adapted_width == frame.width && adapted_height == frame.height) { 90 // No adaption - optimized path. 91 buffer = new rtc::RefCountedObject<ObjCFrameBuffer>(frame.buffer); 92 } else if ([frame.buffer isKindOfClass:[RTC_OBJC_TYPE(RTCCVPixelBuffer) class]]) { 93 // Adapted CVPixelBuffer frame. 94 RTC_OBJC_TYPE(RTCCVPixelBuffer) *rtcPixelBuffer = 95 (RTC_OBJC_TYPE(RTCCVPixelBuffer) *)frame.buffer; 96 buffer = new rtc::RefCountedObject<ObjCFrameBuffer>([[RTC_OBJC_TYPE(RTCCVPixelBuffer) alloc] 97 initWithPixelBuffer:rtcPixelBuffer.pixelBuffer 98 adaptedWidth:adapted_width 99 adaptedHeight:adapted_height 100 cropWidth:crop_width 101 cropHeight:crop_height 102 cropX:crop_x + rtcPixelBuffer.cropX 103 cropY:crop_y + rtcPixelBuffer.cropY]); 104 } else { 105 // Adapted I420 frame. 106 // TODO(magjed): Optimize this I420 path. 107 rtc::scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(adapted_width, adapted_height); 108 buffer = new rtc::RefCountedObject<ObjCFrameBuffer>(frame.buffer); 109 i420_buffer->CropAndScaleFrom(*buffer->ToI420(), crop_x, crop_y, crop_width, crop_height); 110 buffer = i420_buffer; 111 } 112 113 // Applying rotation is only supported for legacy reasons and performance is 114 // not critical here. 115 VideoRotation rotation = static_cast<VideoRotation>(frame.rotation); 116 if (apply_rotation() && rotation != kVideoRotation_0) { 117 buffer = I420Buffer::Rotate(*buffer->ToI420(), rotation); 118 rotation = kVideoRotation_0; 119 } 120 121 OnFrame(VideoFrame::Builder() 122 .set_video_frame_buffer(buffer) 123 .set_rotation(rotation) 124 .set_timestamp_us(translated_timestamp_us) 125 .build()); 126} 127 128} // namespace webrtc 129