diff --git a/src/modules/video_processing/main/source/frame_preprocessor.cc b/src/modules/video_processing/main/source/frame_preprocessor.cc index 57fcec38c7..57bc84daf9 100644 --- a/src/modules/video_processing/main/source/frame_preprocessor.cc +++ b/src/modules/video_processing/main/source/frame_preprocessor.cc @@ -139,41 +139,43 @@ VPMFramePreprocessor::DecimatedHeight() const WebRtc_Word32 VPMFramePreprocessor::PreprocessFrame(const VideoFrame* frame, VideoFrame** processedFrame) { - if (frame == NULL) - { - return VPM_PARAMETER_ERROR; - } - else if (frame->Height() == 0 || frame->Width() == 0) + if (frame == NULL || frame->Height() == 0 || frame->Width() == 0) { return VPM_PARAMETER_ERROR; } + _vd->UpdateIncomingFrameRate(); if (_vd->DropFrame()) { WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, _id, "Drop frame due to frame rate"); - return 1;// drop 1 frame + return 1; // drop 1 frame } - //Resizing incoming frame. - // Note that we must make a copy of it. We are not allowed to resample the input frame. - WebRtc_Word32 ret = _spatialResampler->ResampleFrame(*frame, _resampledFrame); - if (ret != VPM_OK) - { + // Resizing incoming frame if needed. + // Note that we must make a copy of it. + // We are not allowed to resample the input frame. + *processedFrame = NULL; + if (_spatialResampler->ApplyResample(frame->Width(), frame->Height())) { + WebRtc_Word32 ret = _spatialResampler->ResampleFrame(*frame, _resampledFrame); + if (ret != VPM_OK) return ret; + *processedFrame = &_resampledFrame; } - *processedFrame = &_resampledFrame; - - // Perform content analysis on the resampled frame + // Perform content analysis on the frame to be encoded if (_enableCA) { - _contentMetrics = _ca->ComputeContentMetrics(&_resampledFrame); - //Update native values: + if (*processedFrame == NULL) { + _contentMetrics = _ca->ComputeContentMetrics(frame); + } else { + _contentMetrics = _ca->ComputeContentMetrics(&_resampledFrame); + } + // Update native values: _contentMetrics->nativeHeight = frame->Height(); _contentMetrics->nativeWidth = frame->Width(); - - _contentMetrics->nativeFrameRate = _maxFrameRate; // max value as set by user + // Max value as set by user + _contentMetrics->nativeFrameRate = _maxFrameRate; } return VPM_OK; } diff --git a/src/modules/video_processing/main/source/spatial_resampler.cc b/src/modules/video_processing/main/source/spatial_resampler.cc index c98c1dd407..e42471d452 100644 --- a/src/modules/video_processing/main/source/spatial_resampler.cc +++ b/src/modules/video_processing/main/source/spatial_resampler.cc @@ -371,5 +371,16 @@ VPMSimpleSpatialResampler::TargetWidth() return _targetWidth; } +bool +VPMSimpleSpatialResampler::ApplyResample(WebRtc_UWord32 width, + WebRtc_UWord32 height) +{ + if ((width == _targetWidth && height == _targetHeight) || + _resamplingMode == kNoRescaling) + return false; + else + return true; +} + } //namespace diff --git a/src/modules/video_processing/main/source/spatial_resampler.h b/src/modules/video_processing/main/source/spatial_resampler.h index aa9cd36ef4..48914716b2 100644 --- a/src/modules/video_processing/main/source/spatial_resampler.h +++ b/src/modules/video_processing/main/source/spatial_resampler.h @@ -39,6 +39,7 @@ public: virtual WebRtc_UWord32 TargetWidth() = 0; virtual WebRtc_UWord32 TargetHeight() = 0; virtual WebRtc_Word32 Release() = 0; + virtual bool ApplyResample(WebRtc_UWord32 width, WebRtc_UWord32 height) = 0; }; class VPMSimpleSpatialResampler : public VPMSpatialResampler @@ -55,6 +56,7 @@ public: virtual WebRtc_UWord32 TargetWidth(); virtual WebRtc_UWord32 TargetHeight(); virtual WebRtc_Word32 Release(); + virtual bool ApplyResample(WebRtc_UWord32 width, WebRtc_UWord32 height); private: WebRtc_Word32 UpsampleFrame(const VideoFrame& inFrame, VideoFrame& outFrame); diff --git a/src/modules/video_processing/main/source/video_processing_impl.h b/src/modules/video_processing/main/source/video_processing_impl.h index 6b8994236b..813f2a7507 100644 --- a/src/modules/video_processing/main/source/video_processing_impl.h +++ b/src/modules/video_processing/main/source/video_processing_impl.h @@ -11,6 +11,7 @@ /* * video_processing_impl.h */ + #ifndef WEBRTC_MODULE_VIDEO_PROCESSING_IMPL_H #define WEBRTC_MODULE_VIDEO_PROCESSING_IMPL_H @@ -33,8 +34,8 @@ public: virtual ~VideoProcessingModuleImpl(); virtual WebRtc_Word32 Version(WebRtc_Word8* version, - WebRtc_UWord32& remainingBufferInBytes, - WebRtc_UWord32& position) const; + WebRtc_UWord32& remainingBufferInBytes, + WebRtc_UWord32& position) const; WebRtc_Word32 Id() const; @@ -49,21 +50,21 @@ public: FrameStats& stats); virtual WebRtc_Word32 Deflickering(VideoFrame& frame, - FrameStats& stats); + FrameStats& stats); virtual WebRtc_Word32 Denoising(WebRtc_UWord8* frame, - WebRtc_UWord32 width, - WebRtc_UWord32 height); + WebRtc_UWord32 width, + WebRtc_UWord32 height); virtual WebRtc_Word32 Denoising(VideoFrame& frame); virtual WebRtc_Word32 BrightnessDetection(const WebRtc_UWord8* frame, - WebRtc_UWord32 width, - WebRtc_UWord32 height, - const FrameStats& stats); + WebRtc_UWord32 width, + WebRtc_UWord32 height, + const FrameStats& stats); virtual WebRtc_Word32 BrightnessDetection(const VideoFrame& frame, - const FrameStats& stats); + const FrameStats& stats); //Frame pre-processor functions @@ -80,20 +81,26 @@ public: virtual WebRtc_Word32 SetMaxFrameRate(WebRtc_UWord32 maxFrameRate); // Set Target Resolution: frame rate and dimension - virtual WebRtc_Word32 SetTargetResolution(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 frameRate); + virtual WebRtc_Word32 SetTargetResolution(WebRtc_UWord32 width, + WebRtc_UWord32 height, + WebRtc_UWord32 frameRate); // Get decimated values: frame rate/dimension virtual WebRtc_UWord32 DecimatedFrameRate(); virtual WebRtc_UWord32 DecimatedWidth() const; virtual WebRtc_UWord32 DecimatedHeight() const; - // Preprocess: - virtual WebRtc_Word32 PreprocessFrame(const VideoFrame* frame, VideoFrame** processedFrame); + // Pre-process: + // Pre-process incoming frame: Sample when needed and compute content metrics + // when enable. + // If no resampling takes place - processedFrame is set to NULL. + virtual WebRtc_Word32 PreprocessFrame(const VideoFrame* frame, + VideoFrame** processedFrame); virtual VideoContentMetrics* ContentMetrics() const; private: - WebRtc_Word32 _id; - CriticalSectionWrapper& _mutex; + WebRtc_Word32 _id; + CriticalSectionWrapper& _mutex; VPMDeflickering _deflickering; VPMDenoising _denoising; diff --git a/src/video_engine/main/source/vie_encoder.cc b/src/video_engine/main/source/vie_encoder.cc index 4ce754f61d..6c97691f6a 100644 --- a/src/video_engine/main/source/vie_encoder.cc +++ b/src/video_engine/main/source/vie_encoder.cc @@ -585,6 +585,11 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, VideoContentMetrics* contentMetrics = NULL; contentMetrics = _vpm.ContentMetrics(); + // frame was not sampled => use original + if (decimatedFrame == NULL) { + decimatedFrame = &videoFrame; + } + if (_vcm.AddVideoFrame (*decimatedFrame, contentMetrics, &codecSpecificInfo) != VCM_OK) { @@ -609,6 +614,10 @@ void ViEEncoder::DeliverFrame(int id, webrtc::VideoFrame& videoFrame, "%s: Error preprocessing frame %u", __FUNCTION__, videoFrame.TimeStamp()); return; } + // frame was not sampled => use original + if (decimatedFrame == NULL) { + decimatedFrame = &videoFrame; + } if (_vcm.AddVideoFrame(*decimatedFrame) != VCM_OK) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,