Initial VideoProcessing refactoring.
This CL is the first in a series of CLs to refactor VideoProcessing(Module) to follow Google C++ style guide and make the code more readable. This CL removed inheritance from Module, renames variables and makes VideoProcessingImpl::PreprocessFrame return a frame pointer if there is a frame to send, nullptr otherwise. The affected CLs also passes git cl lint. BUG=webrtc:5259 Review URL: https://codereview.webrtc.org/1482913003 Cr-Commit-Position: refs/heads/master@{#10907}
This commit is contained in:
@ -13,8 +13,6 @@ build_video_processing_sse2 = current_cpu == "x86" || current_cpu == "x64"
|
||||
|
||||
source_set("video_processing") {
|
||||
sources = [
|
||||
"brighten.cc",
|
||||
"brighten.h",
|
||||
"brightness_detection.cc",
|
||||
"brightness_detection.h",
|
||||
"content_analysis.cc",
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/video_processing/brighten.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace webrtc {
|
||||
namespace VideoProcessing {
|
||||
|
||||
int32_t Brighten(VideoFrame* frame, int delta) {
|
||||
assert(frame);
|
||||
if (frame->IsZeroSize()) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
}
|
||||
if (frame->width() <= 0 || frame->height() <= 0) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
int num_pixels = frame->width() * frame->height();
|
||||
|
||||
int look_up[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int val = i + delta;
|
||||
look_up[i] = ((((val < 0) ? 0 : val) > 255) ? 255 : val);
|
||||
}
|
||||
|
||||
uint8_t* temp_ptr = frame->buffer(kYPlane);
|
||||
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
*temp_ptr = static_cast<uint8_t>(look_up[*temp_ptr]);
|
||||
temp_ptr++;
|
||||
}
|
||||
return VPM_OK;
|
||||
}
|
||||
|
||||
} // namespace VideoProcessing
|
||||
} // namespace webrtc
|
||||
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_BRIGHTEN_H_
|
||||
#define WEBRTC_MODULES_VIDEO_PROCESSING_BRIGHTEN_H_
|
||||
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace VideoProcessing {
|
||||
|
||||
int32_t Brighten(VideoFrame* frame, int delta);
|
||||
|
||||
} // namespace VideoProcessing
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_BRIGHTEN_H_
|
||||
@ -8,11 +8,12 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
#include "webrtc/modules/video_processing/brightness_detection.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
VPMBrightnessDetection::VPMBrightnessDetection() {
|
||||
@ -28,14 +29,14 @@ void VPMBrightnessDetection::Reset() {
|
||||
|
||||
int32_t VPMBrightnessDetection::ProcessFrame(
|
||||
const VideoFrame& frame,
|
||||
const VideoProcessingModule::FrameStats& stats) {
|
||||
const VideoProcessing::FrameStats& stats) {
|
||||
if (frame.IsZeroSize()) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
}
|
||||
int width = frame.width();
|
||||
int height = frame.height();
|
||||
|
||||
if (!VideoProcessingModule::ValidFrameStats(stats)) {
|
||||
if (!VideoProcessing::ValidFrameStats(stats)) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
}
|
||||
|
||||
@ -62,9 +63,9 @@ int32_t VPMBrightnessDetection::ProcessFrame(
|
||||
// Standard deviation of Y
|
||||
const uint8_t* buffer = frame.buffer(kYPlane);
|
||||
float std_y = 0;
|
||||
for (int h = 0; h < height; h += (1 << stats.subSamplHeight)) {
|
||||
for (int h = 0; h < height; h += (1 << stats.sub_sampling_factor)) {
|
||||
int row = h*width;
|
||||
for (int w = 0; w < width; w += (1 << stats.subSamplWidth)) {
|
||||
for (int w = 0; w < width; w += (1 << stats.sub_sampling_factor)) {
|
||||
std_y += (buffer[w + row] - stats.mean) * (buffer[w + row] -
|
||||
stats.mean);
|
||||
}
|
||||
@ -122,11 +123,11 @@ int32_t VPMBrightnessDetection::ProcessFrame(
|
||||
}
|
||||
|
||||
if (frame_cnt_dark_ > frame_cnt_alarm) {
|
||||
return VideoProcessingModule::kDarkWarning;
|
||||
return VideoProcessing::kDarkWarning;
|
||||
} else if (frame_cnt_bright_ > frame_cnt_alarm) {
|
||||
return VideoProcessingModule::kBrightWarning;
|
||||
return VideoProcessing::kBrightWarning;
|
||||
} else {
|
||||
return VideoProcessingModule::kNoWarning;
|
||||
return VideoProcessing::kNoWarning;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ class VPMBrightnessDetection {
|
||||
|
||||
void Reset();
|
||||
int32_t ProcessFrame(const VideoFrame& frame,
|
||||
const VideoProcessingModule::FrameStats& stats);
|
||||
const VideoProcessing::FrameStats& stats);
|
||||
|
||||
private:
|
||||
uint32_t frame_cnt_bright_;
|
||||
@ -32,4 +32,4 @@ class VPMBrightnessDetection {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_BRIGHTNESS_DETECTION_H_
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_BRIGHTNESS_DETECTION_H_
|
||||
|
||||
@ -41,7 +41,7 @@ enum { kLog2OfDownsamplingFactor = 3 };
|
||||
// Resolution reduced to avoid overflow when multiplying with the
|
||||
// (potentially) large number of pixels.
|
||||
const uint16_t VPMDeflickering::prob_uw16_[kNumProbs] = {102, 205, 410, 614,
|
||||
819, 1024, 1229, 1434, 1638, 1843, 1946, 1987}; // <Q11>
|
||||
819, 1024, 1229, 1434, 1638, 1843, 1946, 1987}; // <Q11>
|
||||
|
||||
// To generate in Matlab:
|
||||
// >> numQuants = 14; maxOnlyLength = 5;
|
||||
@ -49,7 +49,7 @@ const uint16_t VPMDeflickering::prob_uw16_[kNumProbs] = {102, 205, 410, 614,
|
||||
// [linspace(0.5, 1.0, numQuants - maxOnlyLength)]);
|
||||
// >> fprintf('%d, %d,\n ', weightUW16);
|
||||
const uint16_t VPMDeflickering::weight_uw16_[kNumQuants - kMaxOnlyLength] =
|
||||
{16384, 18432, 20480, 22528, 24576, 26624, 28672, 30720, 32768}; // <Q15>
|
||||
{16384, 18432, 20480, 22528, 24576, 26624, 28672, 30720, 32768}; // <Q15>
|
||||
|
||||
VPMDeflickering::VPMDeflickering() {
|
||||
Reset();
|
||||
@ -82,7 +82,7 @@ void VPMDeflickering::Reset() {
|
||||
|
||||
int32_t VPMDeflickering::ProcessFrame(
|
||||
VideoFrame* frame,
|
||||
VideoProcessingModule::FrameStats* stats) {
|
||||
VideoProcessing::FrameStats* stats) {
|
||||
assert(frame);
|
||||
uint32_t frame_memory;
|
||||
uint8_t quant_uw8[kNumQuants];
|
||||
@ -107,7 +107,7 @@ int32_t VPMDeflickering::ProcessFrame(
|
||||
return VPM_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if (!VideoProcessingModule::ValidFrameStats(*stats)) {
|
||||
if (!VideoProcessing::ValidFrameStats(*stats)) {
|
||||
return VPM_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
@ -209,7 +209,7 @@ int32_t VPMDeflickering::ProcessFrame(
|
||||
|
||||
if (tmp_uw16 > 0) {
|
||||
increment_uw16 = static_cast<uint16_t>(WebRtcSpl_DivU32U16(tmp_uw32,
|
||||
tmp_uw16)); // <Q7>
|
||||
tmp_uw16)); // <Q7>
|
||||
} else {
|
||||
// The value is irrelevant; the loop below will only iterate once.
|
||||
increment_uw16 = 0;
|
||||
@ -230,7 +230,7 @@ int32_t VPMDeflickering::ProcessFrame(
|
||||
}
|
||||
|
||||
// Frame was altered, so reset stats.
|
||||
VideoProcessingModule::ClearFrameStats(stats);
|
||||
VideoProcessing::ClearFrameStats(stats);
|
||||
|
||||
return VPM_OK;
|
||||
}
|
||||
@ -248,7 +248,7 @@ int32_t VPMDeflickering::ProcessFrame(
|
||||
-1: Error
|
||||
*/
|
||||
int32_t VPMDeflickering::PreDetection(const uint32_t timestamp,
|
||||
const VideoProcessingModule::FrameStats& stats) {
|
||||
const VideoProcessing::FrameStats& stats) {
|
||||
int32_t mean_val; // Mean value of frame (Q4)
|
||||
uint32_t frame_rate = 0;
|
||||
int32_t meanBufferLength; // Temp variable.
|
||||
@ -371,7 +371,7 @@ int32_t VPMDeflickering::DetectFlicker() {
|
||||
int32_t freqAlias = freqEst;
|
||||
if (freqEst > kMinFrequencyToDetect) {
|
||||
uint8_t aliasState = 1;
|
||||
while(freqState == 0) {
|
||||
while (freqState == 0) {
|
||||
/* Increase frequency */
|
||||
freqAlias += (aliasState * frame_rate_);
|
||||
freqAlias += ((freqEst << 1) * (1 - (aliasState << 1)));
|
||||
|
||||
@ -24,12 +24,11 @@ class VPMDeflickering {
|
||||
~VPMDeflickering();
|
||||
|
||||
void Reset();
|
||||
int32_t ProcessFrame(VideoFrame* frame,
|
||||
VideoProcessingModule::FrameStats* stats);
|
||||
int32_t ProcessFrame(VideoFrame* frame, VideoProcessing::FrameStats* stats);
|
||||
|
||||
private:
|
||||
int32_t PreDetection(uint32_t timestamp,
|
||||
const VideoProcessingModule::FrameStats& stats);
|
||||
const VideoProcessing::FrameStats& stats);
|
||||
|
||||
int32_t DetectFlicker();
|
||||
|
||||
@ -53,4 +52,4 @@ class VPMDeflickering {
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_DEFLICKERING_H_
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_DEFLICKERING_H_
|
||||
|
||||
@ -10,30 +10,24 @@
|
||||
|
||||
#include "webrtc/modules/video_processing/frame_preprocessor.h"
|
||||
|
||||
#include "webrtc/modules/video_processing/video_denoiser.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
VPMFramePreprocessor::VPMFramePreprocessor()
|
||||
: content_metrics_(nullptr),
|
||||
resampled_frame_(),
|
||||
enable_ca_(false),
|
||||
enable_denoising_(false),
|
||||
frame_cnt_(0) {
|
||||
spatial_resampler_ = new VPMSimpleSpatialResampler();
|
||||
ca_ = new VPMContentAnalysis(true);
|
||||
vd_ = new VPMVideoDecimator();
|
||||
if (enable_denoising_) {
|
||||
denoiser_ = new VideoDenoiser();
|
||||
} else {
|
||||
denoiser_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VPMFramePreprocessor::~VPMFramePreprocessor() {
|
||||
Reset();
|
||||
delete ca_;
|
||||
delete vd_;
|
||||
if (enable_denoising_)
|
||||
delete denoiser_;
|
||||
delete spatial_resampler_;
|
||||
}
|
||||
|
||||
@ -61,7 +55,7 @@ void VPMFramePreprocessor::SetInputFrameResampleMode(
|
||||
|
||||
int32_t VPMFramePreprocessor::SetTargetResolution(
|
||||
uint32_t width, uint32_t height, uint32_t frame_rate) {
|
||||
if ( (width == 0) || (height == 0) || (frame_rate == 0)) {
|
||||
if ((width == 0) || (height == 0) || (frame_rate == 0)) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
}
|
||||
int32_t ret_val = 0;
|
||||
@ -86,70 +80,62 @@ void VPMFramePreprocessor::UpdateIncomingframe_rate() {
|
||||
vd_->UpdateIncomingframe_rate();
|
||||
}
|
||||
|
||||
uint32_t VPMFramePreprocessor::Decimatedframe_rate() {
|
||||
return vd_->Decimatedframe_rate();
|
||||
uint32_t VPMFramePreprocessor::GetDecimatedFrameRate() {
|
||||
return vd_->GetDecimatedFrameRate();
|
||||
}
|
||||
|
||||
|
||||
uint32_t VPMFramePreprocessor::DecimatedWidth() const {
|
||||
uint32_t VPMFramePreprocessor::GetDecimatedWidth() const {
|
||||
return spatial_resampler_->TargetWidth();
|
||||
}
|
||||
|
||||
|
||||
uint32_t VPMFramePreprocessor::DecimatedHeight() const {
|
||||
uint32_t VPMFramePreprocessor::GetDecimatedHeight() const {
|
||||
return spatial_resampler_->TargetHeight();
|
||||
}
|
||||
|
||||
int32_t VPMFramePreprocessor::PreprocessFrame(const VideoFrame& frame,
|
||||
VideoFrame** processed_frame) {
|
||||
void VPMFramePreprocessor::EnableDenosing(bool enable) {
|
||||
denoiser_.reset(new VideoDenoiser());
|
||||
}
|
||||
|
||||
const VideoFrame* VPMFramePreprocessor::PreprocessFrame(
|
||||
const VideoFrame& frame) {
|
||||
if (frame.IsZeroSize()) {
|
||||
return VPM_PARAMETER_ERROR;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vd_->UpdateIncomingframe_rate();
|
||||
|
||||
if (vd_->DropFrame()) {
|
||||
return 1; // drop 1 frame
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Resizing incoming frame if needed. Otherwise, remains nullptr.
|
||||
// We are not allowed to resample the input frame (must make a copy of it).
|
||||
*processed_frame = nullptr;
|
||||
if (denoiser_ != nullptr) {
|
||||
denoiser_->DenoiseFrame(frame, &denoised_frame_);
|
||||
*processed_frame = &denoised_frame_;
|
||||
const VideoFrame* current_frame = &frame;
|
||||
if (denoiser_) {
|
||||
denoiser_->DenoiseFrame(*current_frame, &denoised_frame_);
|
||||
current_frame = &denoised_frame_;
|
||||
}
|
||||
|
||||
if (spatial_resampler_->ApplyResample(frame.width(), frame.height())) {
|
||||
int32_t ret;
|
||||
if (enable_denoising_) {
|
||||
ret = spatial_resampler_->ResampleFrame(denoised_frame_,
|
||||
&resampled_frame_);
|
||||
} else {
|
||||
ret = spatial_resampler_->ResampleFrame(frame, &resampled_frame_);
|
||||
if (spatial_resampler_->ApplyResample(current_frame->width(),
|
||||
current_frame->height())) {
|
||||
if (spatial_resampler_->ResampleFrame(*current_frame, &resampled_frame_) !=
|
||||
VPM_OK) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ret != VPM_OK) return ret;
|
||||
*processed_frame = &resampled_frame_;
|
||||
current_frame = &resampled_frame_;
|
||||
}
|
||||
|
||||
// Perform content analysis on the frame to be encoded.
|
||||
if (enable_ca_) {
|
||||
if (enable_ca_ && frame_cnt_ % kSkipFrameCA == 0) {
|
||||
// Compute new metrics every |kSkipFramesCA| frames, starting with
|
||||
// the first frame.
|
||||
if (frame_cnt_ % kSkipFrameCA == 0) {
|
||||
if (*processed_frame == nullptr) {
|
||||
content_metrics_ = ca_->ComputeContentMetrics(frame);
|
||||
} else {
|
||||
content_metrics_ = ca_->ComputeContentMetrics(**processed_frame);
|
||||
}
|
||||
}
|
||||
content_metrics_ = ca_->ComputeContentMetrics(*current_frame);
|
||||
}
|
||||
++frame_cnt_;
|
||||
return VPM_OK;
|
||||
return current_frame;
|
||||
}
|
||||
|
||||
VideoContentMetrics* VPMFramePreprocessor::ContentMetrics() const {
|
||||
VideoContentMetrics* VPMFramePreprocessor::GetContentMetrics() const {
|
||||
return content_metrics_;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
@ -8,22 +8,23 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
/*
|
||||
* frame_preprocessor.h
|
||||
*/
|
||||
#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_
|
||||
#define WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_
|
||||
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
#include "webrtc/modules/video_processing/content_analysis.h"
|
||||
#include "webrtc/modules/video_processing/spatial_resampler.h"
|
||||
#include "webrtc/modules/video_processing/video_decimator.h"
|
||||
#include "webrtc/modules/video_processing/video_denoiser.h"
|
||||
#include "webrtc/typedefs.h"
|
||||
#include "webrtc/video_frame.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoDenoiser;
|
||||
|
||||
// All pointers/members in this class are assumed to be protected by the class
|
||||
// owner.
|
||||
class VPMFramePreprocessor {
|
||||
public:
|
||||
VPMFramePreprocessor();
|
||||
@ -52,14 +53,14 @@ class VPMFramePreprocessor {
|
||||
int32_t updateIncomingFrameSize(uint32_t width, uint32_t height);
|
||||
|
||||
// Set decimated values: frame rate/dimension.
|
||||
uint32_t Decimatedframe_rate();
|
||||
uint32_t DecimatedWidth() const;
|
||||
uint32_t DecimatedHeight() const;
|
||||
uint32_t GetDecimatedFrameRate();
|
||||
uint32_t GetDecimatedWidth() const;
|
||||
uint32_t GetDecimatedHeight() const;
|
||||
|
||||
// Preprocess output:
|
||||
int32_t PreprocessFrame(const VideoFrame& frame,
|
||||
VideoFrame** processed_frame);
|
||||
VideoContentMetrics* ContentMetrics() const;
|
||||
void EnableDenosing(bool enable);
|
||||
const VideoFrame* PreprocessFrame(const VideoFrame& frame);
|
||||
VideoContentMetrics* GetContentMetrics() const;
|
||||
|
||||
private:
|
||||
// The content does not change so much every frame, so to reduce complexity
|
||||
@ -72,13 +73,11 @@ class VPMFramePreprocessor {
|
||||
VPMSpatialResampler* spatial_resampler_;
|
||||
VPMContentAnalysis* ca_;
|
||||
VPMVideoDecimator* vd_;
|
||||
VideoDenoiser* denoiser_;
|
||||
rtc::scoped_ptr<VideoDenoiser> denoiser_;
|
||||
bool enable_ca_;
|
||||
bool enable_denoising_;
|
||||
int frame_cnt_;
|
||||
|
||||
uint32_t frame_cnt_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_FRAME_PREPROCESSOR_H_
|
||||
|
||||
@ -18,250 +18,93 @@
|
||||
#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_H_
|
||||
#define WEBRTC_MODULES_VIDEO_PROCESSING_INCLUDE_VIDEO_PROCESSING_H_
|
||||
|
||||
#include "webrtc/modules/include/module.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/video_processing/include/video_processing_defines.h"
|
||||
#include "webrtc/video_frame.h"
|
||||
|
||||
/**
|
||||
The module is largely intended to process video streams, except functionality
|
||||
provided by static functions which operate independent of previous frames. It
|
||||
is recommended, but not required that a unique instance be used for each
|
||||
concurrently processed stream. Similarly, it is recommended to call Reset()
|
||||
before switching to a new stream, but this is not absolutely required.
|
||||
|
||||
The module provides basic thread safety by permitting only a single function
|
||||
to execute concurrently.
|
||||
*/
|
||||
// The module is largely intended to process video streams, except functionality
|
||||
// provided by static functions which operate independent of previous frames. It
|
||||
// is recommended, but not required that a unique instance be used for each
|
||||
// concurrently processed stream. Similarly, it is recommended to call Reset()
|
||||
// before switching to a new stream, but this is not absolutely required.
|
||||
//
|
||||
// The module provides basic thread safety by permitting only a single function
|
||||
// to execute concurrently.
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoProcessingModule : public Module {
|
||||
class VideoProcessing {
|
||||
public:
|
||||
/**
|
||||
Structure to hold frame statistics. Populate it with GetFrameStats().
|
||||
*/
|
||||
struct FrameStats {
|
||||
FrameStats() :
|
||||
mean(0),
|
||||
sum(0),
|
||||
num_pixels(0),
|
||||
subSamplWidth(0),
|
||||
subSamplHeight(0) {
|
||||
memset(hist, 0, sizeof(hist));
|
||||
}
|
||||
|
||||
uint32_t hist[256]; // FRame histogram.
|
||||
uint32_t mean; // Frame Mean value.
|
||||
uint32_t sum; // Sum of frame.
|
||||
uint32_t num_pixels; // Number of pixels.
|
||||
uint8_t subSamplWidth; // Subsampling rate of width in powers of 2.
|
||||
uint8_t subSamplHeight; // Subsampling rate of height in powers of 2.
|
||||
};
|
||||
|
||||
/**
|
||||
Specifies the warning types returned by BrightnessDetection().
|
||||
*/
|
||||
enum BrightnessWarning {
|
||||
kNoWarning, // Frame has acceptable brightness.
|
||||
kDarkWarning, // Frame is too dark.
|
||||
kBrightWarning // Frame is too bright.
|
||||
uint32_t hist[256]; // Frame histogram.
|
||||
uint32_t mean;
|
||||
uint32_t sum;
|
||||
uint32_t num_pixels;
|
||||
uint32_t sub_sampling_factor; // Sub-sampling factor, in powers of 2.
|
||||
};
|
||||
|
||||
/*
|
||||
Creates a VPM object.
|
||||
enum BrightnessWarning {
|
||||
kNoWarning,
|
||||
kDarkWarning,
|
||||
kBrightWarning
|
||||
};
|
||||
|
||||
\param[in] id
|
||||
Unique identifier of this object.
|
||||
static VideoProcessing* Create();
|
||||
virtual ~VideoProcessing() {}
|
||||
|
||||
\return Pointer to a VPM object.
|
||||
*/
|
||||
static VideoProcessingModule* Create();
|
||||
// Retrieves statistics for the input frame. This function must be used to
|
||||
// prepare a FrameStats struct for use in certain VPM functions.
|
||||
static void GetFrameStats(const VideoFrame& frame, FrameStats* stats);
|
||||
|
||||
/**
|
||||
Destroys a VPM object.
|
||||
|
||||
\param[in] module
|
||||
Pointer to the VPM object to destroy.
|
||||
*/
|
||||
static void Destroy(VideoProcessingModule* module);
|
||||
|
||||
/**
|
||||
Not supported.
|
||||
*/
|
||||
int64_t TimeUntilNextProcess() override { return -1; }
|
||||
|
||||
/**
|
||||
Not supported.
|
||||
*/
|
||||
int32_t Process() override { return -1; }
|
||||
|
||||
/**
|
||||
Resets all processing components to their initial states. This should be
|
||||
called whenever a new video stream is started.
|
||||
*/
|
||||
virtual void Reset() = 0;
|
||||
|
||||
/**
|
||||
Retrieves statistics for the input frame. This function must be used to
|
||||
prepare a FrameStats struct for use in certain VPM functions.
|
||||
|
||||
\param[out] stats
|
||||
The frame statistics will be stored here on return.
|
||||
|
||||
\param[in] frame
|
||||
Reference to the video frame.
|
||||
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int32_t GetFrameStats(FrameStats* stats, const VideoFrame& frame);
|
||||
|
||||
/**
|
||||
Checks the validity of a FrameStats struct. Currently, valid implies only
|
||||
that is had changed from its initialized state.
|
||||
|
||||
\param[in] stats
|
||||
Frame statistics.
|
||||
|
||||
\return True on valid stats, false on invalid stats.
|
||||
*/
|
||||
// Checks the validity of a FrameStats struct. Currently, valid implies only
|
||||
// that is had changed from its initialized state.
|
||||
static bool ValidFrameStats(const FrameStats& stats);
|
||||
|
||||
/**
|
||||
Returns a FrameStats struct to its intialized state.
|
||||
|
||||
\param[in,out] stats
|
||||
Frame statistics.
|
||||
*/
|
||||
static void ClearFrameStats(FrameStats* stats);
|
||||
|
||||
/**
|
||||
Increases/decreases the luminance value.
|
||||
// Increases/decreases the luminance value. 'delta' can be in the range {}
|
||||
static void Brighten(int delta, VideoFrame* frame);
|
||||
|
||||
\param[in,out] frame
|
||||
Pointer to the video frame.
|
||||
|
||||
\param[in] delta
|
||||
The amount to change the chrominance value of every single pixel.
|
||||
Can be < 0 also.
|
||||
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int32_t Brighten(VideoFrame* frame, int delta);
|
||||
|
||||
/**
|
||||
Detects and removes camera flicker from a video stream. Every frame from
|
||||
the stream must be passed in. A frame will only be altered if flicker has
|
||||
been detected. Has a fixed-point implementation.
|
||||
|
||||
\param[in,out] frame
|
||||
Pointer to the video frame.
|
||||
|
||||
\param[in,out] stats
|
||||
Frame statistics provided by GetFrameStats(). On return the stats will
|
||||
be reset to zero if the frame was altered. Call GetFrameStats() again
|
||||
if the statistics for the altered frame are required.
|
||||
|
||||
\return 0 on success, -1 on failure.
|
||||
*/
|
||||
// Detects and removes camera flicker from a video stream. Every frame from
|
||||
// the stream must be passed in. A frame will only be altered if flicker has
|
||||
// been detected. Has a fixed-point implementation.
|
||||
// Frame statistics provided by GetFrameStats(). On return the stats will
|
||||
// be reset to zero if the frame was altered. Call GetFrameStats() again
|
||||
// if the statistics for the altered frame are required.
|
||||
virtual int32_t Deflickering(VideoFrame* frame, FrameStats* stats) = 0;
|
||||
|
||||
/**
|
||||
Detects if a video frame is excessively bright or dark. Returns a
|
||||
warning if this is the case. Multiple frames should be passed in before
|
||||
expecting a warning. Has a floating-point implementation.
|
||||
|
||||
\param[in] frame
|
||||
Pointer to the video frame.
|
||||
|
||||
\param[in] stats
|
||||
Frame statistics provided by GetFrameStats().
|
||||
|
||||
\return A member of BrightnessWarning on success, -1 on error
|
||||
*/
|
||||
// Detects if a video frame is excessively bright or dark. Returns a
|
||||
// warning if this is the case. Multiple frames should be passed in before
|
||||
// expecting a warning. Has a floating-point implementation.
|
||||
virtual int32_t BrightnessDetection(const VideoFrame& frame,
|
||||
const FrameStats& stats) = 0;
|
||||
|
||||
/**
|
||||
The following functions refer to the pre-processor unit within VPM. The
|
||||
pre-processor perfoms spatial/temporal decimation and content analysis on
|
||||
the frames prior to encoding.
|
||||
*/
|
||||
// The following functions refer to the pre-processor unit within VPM. The
|
||||
// pre-processor perfoms spatial/temporal decimation and content analysis on
|
||||
// the frames prior to encoding.
|
||||
|
||||
/**
|
||||
Enable/disable temporal decimation
|
||||
|
||||
\param[in] enable when true, temporal decimation is enabled
|
||||
*/
|
||||
// Enable/disable temporal decimation
|
||||
virtual void EnableTemporalDecimation(bool enable) = 0;
|
||||
|
||||
/**
|
||||
Set target resolution
|
||||
|
||||
\param[in] width
|
||||
Target width
|
||||
|
||||
\param[in] height
|
||||
Target height
|
||||
|
||||
\param[in] frame_rate
|
||||
Target frame_rate
|
||||
|
||||
\return VPM_OK on success, a negative value on error (see error codes)
|
||||
|
||||
*/
|
||||
virtual int32_t SetTargetResolution(uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t frame_rate) = 0;
|
||||
|
||||
virtual void SetTargetFramerate(int frame_rate) {}
|
||||
virtual void SetTargetFramerate(int frame_rate) = 0;
|
||||
|
||||
/**
|
||||
Get decimated(target) frame rate
|
||||
*/
|
||||
virtual uint32_t Decimatedframe_rate() = 0;
|
||||
virtual uint32_t GetDecimatedFrameRate() = 0;
|
||||
virtual uint32_t GetDecimatedWidth() const = 0;
|
||||
virtual uint32_t GetDecimatedHeight() const = 0;
|
||||
|
||||
/**
|
||||
Get decimated(target) frame width
|
||||
*/
|
||||
virtual uint32_t DecimatedWidth() const = 0;
|
||||
// Set the spatial resampling settings of the VPM according to
|
||||
// VideoFrameResampling.
|
||||
virtual void SetInputFrameResampleMode(
|
||||
VideoFrameResampling resampling_mode) = 0;
|
||||
|
||||
/**
|
||||
Get decimated(target) frame height
|
||||
*/
|
||||
virtual uint32_t DecimatedHeight() const = 0 ;
|
||||
virtual void EnableDenosing(bool enable) = 0;
|
||||
virtual const VideoFrame* PreprocessFrame(const VideoFrame& frame) = 0;
|
||||
|
||||
/**
|
||||
Set the spatial resampling settings of the VPM: The resampler may either be
|
||||
disabled or one of the following:
|
||||
scaling to a close to target dimension followed by crop/pad
|
||||
|
||||
\param[in] resampling_mode
|
||||
Set resampling mode (a member of VideoFrameResampling)
|
||||
*/
|
||||
virtual void SetInputFrameResampleMode(VideoFrameResampling
|
||||
resampling_mode) = 0;
|
||||
|
||||
/**
|
||||
Get Processed (decimated) frame
|
||||
|
||||
\param[in] frame pointer to the video frame.
|
||||
\param[in] processed_frame pointer (double) to the processed frame. If no
|
||||
processing is required, processed_frame will be NULL.
|
||||
|
||||
\return VPM_OK on success, a negative value on error (see error codes)
|
||||
*/
|
||||
virtual int32_t PreprocessFrame(const VideoFrame& frame,
|
||||
VideoFrame** processed_frame) = 0;
|
||||
|
||||
/**
|
||||
Return content metrics for the last processed frame
|
||||
*/
|
||||
virtual VideoContentMetrics* ContentMetrics() const = 0 ;
|
||||
|
||||
/**
|
||||
Enable content analysis
|
||||
*/
|
||||
virtual VideoContentMetrics* GetContentMetrics() const = 0;
|
||||
virtual void EnableContentAnalysis(bool enable) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -13,26 +13,24 @@
|
||||
#include "webrtc/modules/video_processing/test/video_processing_unittest.h"
|
||||
#include "webrtc/test/testsupport/gtest_disable.h"
|
||||
|
||||
using namespace webrtc;
|
||||
namespace webrtc {
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(BrightnessDetection))
|
||||
{
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(BrightnessDetection)) {
|
||||
uint32_t frameNum = 0;
|
||||
int32_t brightnessWarning = 0;
|
||||
uint32_t warningCount = 0;
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
|
||||
frame_length_)
|
||||
{
|
||||
frame_length_) {
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_,
|
||||
height_, 0, kVideoRotation_0, &video_frame_));
|
||||
frameNum++;
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
ASSERT_GE(brightnessWarning = vpm_->BrightnessDetection(video_frame_,
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_GE(brightnessWarning = vp_->BrightnessDetection(video_frame_,
|
||||
stats), 0);
|
||||
if (brightnessWarning != VideoProcessingModule::kNoWarning)
|
||||
{
|
||||
if (brightnessWarning != VideoProcessing::kNoWarning) {
|
||||
warningCount++;
|
||||
}
|
||||
}
|
||||
@ -49,31 +47,28 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(BrightnessDetection))
|
||||
warningCount = 0;
|
||||
while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
|
||||
frame_length_ &&
|
||||
frameNum < 300)
|
||||
{
|
||||
frameNum < 300) {
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_,
|
||||
height_, 0, kVideoRotation_0, &video_frame_));
|
||||
frameNum++;
|
||||
|
||||
uint8_t* frame = video_frame_.buffer(kYPlane);
|
||||
uint32_t yTmp = 0;
|
||||
for (int yIdx = 0; yIdx < width_ * height_; yIdx++)
|
||||
{
|
||||
for (int yIdx = 0; yIdx < width_ * height_; yIdx++) {
|
||||
yTmp = frame[yIdx] << 1;
|
||||
if (yTmp > 255)
|
||||
{
|
||||
if (yTmp > 255) {
|
||||
yTmp = 255;
|
||||
}
|
||||
frame[yIdx] = static_cast<uint8_t>(yTmp);
|
||||
}
|
||||
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
ASSERT_GE(brightnessWarning = vpm_->BrightnessDetection(video_frame_,
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_GE(brightnessWarning = vp_->BrightnessDetection(video_frame_,
|
||||
stats), 0);
|
||||
EXPECT_NE(VideoProcessingModule::kDarkWarning, brightnessWarning);
|
||||
if (brightnessWarning == VideoProcessingModule::kBrightWarning)
|
||||
{
|
||||
EXPECT_NE(VideoProcessing::kDarkWarning, brightnessWarning);
|
||||
if (brightnessWarning == VideoProcessing::kBrightWarning) {
|
||||
warningCount++;
|
||||
}
|
||||
}
|
||||
@ -88,27 +83,25 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(BrightnessDetection))
|
||||
frameNum = 0;
|
||||
warningCount = 0;
|
||||
while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
|
||||
frame_length_ && frameNum < 300)
|
||||
{
|
||||
frame_length_ && frameNum < 300) {
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_,
|
||||
height_, 0, kVideoRotation_0, &video_frame_));
|
||||
frameNum++;
|
||||
|
||||
uint8_t* y_plane = video_frame_.buffer(kYPlane);
|
||||
int32_t yTmp = 0;
|
||||
for (int yIdx = 0; yIdx < width_ * height_; yIdx++)
|
||||
{
|
||||
for (int yIdx = 0; yIdx < width_ * height_; yIdx++) {
|
||||
yTmp = y_plane[yIdx] >> 1;
|
||||
y_plane[yIdx] = static_cast<uint8_t>(yTmp);
|
||||
}
|
||||
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
ASSERT_GE(brightnessWarning = vpm_->BrightnessDetection(video_frame_,
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_GE(brightnessWarning = vp_->BrightnessDetection(video_frame_,
|
||||
stats), 0);
|
||||
EXPECT_NE(VideoProcessingModule::kBrightWarning, brightnessWarning);
|
||||
if (brightnessWarning == VideoProcessingModule::kDarkWarning)
|
||||
{
|
||||
EXPECT_NE(VideoProcessing::kBrightWarning, brightnessWarning);
|
||||
if (brightnessWarning == VideoProcessing::kDarkWarning) {
|
||||
warningCount++;
|
||||
}
|
||||
}
|
||||
@ -119,3 +112,4 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(BrightnessDetection))
|
||||
printf("Dark foreman: %.1f %%\n\n", warningProportion);
|
||||
EXPECT_GT(warningProportion, 90);
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -16,13 +16,14 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(ContentAnalysis)) {
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(ContentAnalysis)) {
|
||||
VPMContentAnalysis ca__c(false);
|
||||
VPMContentAnalysis ca__sse(true);
|
||||
VideoContentMetrics *_cM_c, *_cM_SSE;
|
||||
VideoContentMetrics* _cM_c;
|
||||
VideoContentMetrics* _cM_SSE;
|
||||
|
||||
ca__c.Initialize(width_,height_);
|
||||
ca__sse.Initialize(width_,height_);
|
||||
ca__c.Initialize(width_, height_);
|
||||
ca__sse.Initialize(width_, height_);
|
||||
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
while (fread(video_buffer.get(), 1, frame_length_, source_file_)
|
||||
|
||||
@ -20,8 +20,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Deflickering))
|
||||
{
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(Deflickering)) {
|
||||
enum { NumRuns = 30 };
|
||||
uint32_t frameNum = 0;
|
||||
const uint32_t frame_rate = 15;
|
||||
@ -45,8 +44,7 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Deflickering))
|
||||
|
||||
printf("\nRun time [us / frame]:\n");
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
for (uint32_t run_idx = 0; run_idx < NumRuns; run_idx++)
|
||||
{
|
||||
for (uint32_t run_idx = 0; run_idx < NumRuns; run_idx++) {
|
||||
TickTime t0;
|
||||
TickTime t1;
|
||||
TickInterval acc_ticks;
|
||||
@ -54,8 +52,7 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Deflickering))
|
||||
|
||||
frameNum = 0;
|
||||
while (fread(video_buffer.get(), 1, frame_length_, source_file_) ==
|
||||
frame_length_)
|
||||
{
|
||||
frame_length_) {
|
||||
frameNum++;
|
||||
EXPECT_EQ(
|
||||
0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_,
|
||||
@ -63,14 +60,14 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Deflickering))
|
||||
video_frame_.set_timestamp(timeStamp);
|
||||
|
||||
t0 = TickTime::Now();
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
ASSERT_EQ(0, vpm_->Deflickering(&video_frame_, &stats));
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_EQ(0, vp_->Deflickering(&video_frame_, &stats));
|
||||
t1 = TickTime::Now();
|
||||
acc_ticks += (t1 - t0);
|
||||
|
||||
if (run_idx == 0)
|
||||
{
|
||||
if (run_idx == 0) {
|
||||
if (PrintVideoFrame(video_frame_, deflickerFile) < 0) {
|
||||
return;
|
||||
}
|
||||
@ -80,8 +77,7 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Deflickering))
|
||||
ASSERT_NE(0, feof(source_file_)) << "Error reading source file";
|
||||
|
||||
printf("%u\n", static_cast<int>(acc_ticks.Microseconds() / frameNum));
|
||||
if (acc_ticks.Microseconds() < min_runtime || run_idx == 0)
|
||||
{
|
||||
if (acc_ticks.Microseconds() < min_runtime || run_idx == 0) {
|
||||
min_runtime = acc_ticks.Microseconds();
|
||||
}
|
||||
avg_runtime += acc_ticks.Microseconds();
|
||||
|
||||
@ -10,9 +10,10 @@
|
||||
|
||||
#include "webrtc/modules/video_processing/test/video_processing_unittest.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/system_wrappers/include/tick_util.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
@ -30,8 +31,8 @@ DEFINE_bool(gen_files, false, "Output files for visual inspection.");
|
||||
static void PreprocessFrameAndVerify(const VideoFrame& source,
|
||||
int target_width,
|
||||
int target_height,
|
||||
VideoProcessingModule* vpm,
|
||||
VideoFrame** out_frame);
|
||||
VideoProcessing* vpm,
|
||||
const VideoFrame* out_frame);
|
||||
static void CropFrame(const uint8_t* source_data,
|
||||
int source_width,
|
||||
int source_height,
|
||||
@ -49,14 +50,14 @@ static void TestSize(const VideoFrame& source_frame,
|
||||
int target_width,
|
||||
int target_height,
|
||||
double expected_psnr,
|
||||
VideoProcessingModule* vpm);
|
||||
VideoProcessing* vpm);
|
||||
static bool CompareFrames(const webrtc::VideoFrame& frame1,
|
||||
const webrtc::VideoFrame& frame2);
|
||||
static void WriteProcessedFrameForVisualInspection(const VideoFrame& source,
|
||||
const VideoFrame& processed);
|
||||
|
||||
VideoProcessingModuleTest::VideoProcessingModuleTest()
|
||||
: vpm_(NULL),
|
||||
VideoProcessingTest::VideoProcessingTest()
|
||||
: vp_(NULL),
|
||||
source_file_(NULL),
|
||||
width_(352),
|
||||
half_width_((width_ + 1) / 2),
|
||||
@ -65,9 +66,9 @@ VideoProcessingModuleTest::VideoProcessingModuleTest()
|
||||
size_uv_(half_width_ * ((height_ + 1) / 2)),
|
||||
frame_length_(CalcBufferSize(kI420, width_, height_)) {}
|
||||
|
||||
void VideoProcessingModuleTest::SetUp() {
|
||||
vpm_ = VideoProcessingModule::Create();
|
||||
ASSERT_TRUE(vpm_ != NULL);
|
||||
void VideoProcessingTest::SetUp() {
|
||||
vp_ = VideoProcessing::Create();
|
||||
ASSERT_TRUE(vp_ != NULL);
|
||||
|
||||
ASSERT_EQ(0, video_frame_.CreateEmptyFrame(width_, height_, width_,
|
||||
half_width_, half_width_));
|
||||
@ -77,125 +78,126 @@ void VideoProcessingModuleTest::SetUp() {
|
||||
memset(video_frame_.buffer(kVPlane), 0, video_frame_.allocated_size(kVPlane));
|
||||
const std::string video_file =
|
||||
webrtc::test::ResourcePath("foreman_cif", "yuv");
|
||||
source_file_ = fopen(video_file.c_str(),"rb");
|
||||
source_file_ = fopen(video_file.c_str(), "rb");
|
||||
ASSERT_TRUE(source_file_ != NULL) <<
|
||||
"Cannot read source file: " + video_file + "\n";
|
||||
}
|
||||
|
||||
void VideoProcessingModuleTest::TearDown() {
|
||||
void VideoProcessingTest::TearDown() {
|
||||
if (source_file_ != NULL) {
|
||||
ASSERT_EQ(0, fclose(source_file_));
|
||||
}
|
||||
source_file_ = NULL;
|
||||
|
||||
if (vpm_ != NULL) {
|
||||
VideoProcessingModule::Destroy(vpm_);
|
||||
}
|
||||
vpm_ = NULL;
|
||||
delete vp_;
|
||||
vp_ = NULL;
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(HandleNullBuffer)) {
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(HandleNullBuffer)) {
|
||||
// TODO(mikhal/stefan): Do we need this one?
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
VideoProcessing::FrameStats stats;
|
||||
// Video frame with unallocated buffer.
|
||||
VideoFrame videoFrame;
|
||||
|
||||
EXPECT_EQ(-3, vpm_->GetFrameStats(&stats, videoFrame));
|
||||
vp_->GetFrameStats(videoFrame, &stats);
|
||||
EXPECT_EQ(stats.num_pixels, 0u);
|
||||
|
||||
EXPECT_EQ(-1, vpm_->Deflickering(&videoFrame, &stats));
|
||||
EXPECT_EQ(-1, vp_->Deflickering(&videoFrame, &stats));
|
||||
|
||||
EXPECT_EQ(-3, vpm_->BrightnessDetection(videoFrame, stats));
|
||||
EXPECT_EQ(-3, vp_->BrightnessDetection(videoFrame, stats));
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(HandleBadStats)) {
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(HandleBadStats)) {
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->ClearFrameStats(&stats);
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
ASSERT_EQ(frame_length_, fread(video_buffer.get(), 1, frame_length_,
|
||||
source_file_));
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
|
||||
0, kVideoRotation_0, &video_frame_));
|
||||
|
||||
EXPECT_EQ(-1, vpm_->Deflickering(&video_frame_, &stats));
|
||||
EXPECT_EQ(-1, vp_->Deflickering(&video_frame_, &stats));
|
||||
|
||||
EXPECT_EQ(-3, vpm_->BrightnessDetection(video_frame_, stats));
|
||||
EXPECT_EQ(-3, vp_->BrightnessDetection(video_frame_, stats));
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(IdenticalResultsAfterReset)) {
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(IdenticalResultsAfterReset)) {
|
||||
VideoFrame video_frame2;
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
VideoProcessing::FrameStats stats;
|
||||
// Only testing non-static functions here.
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
ASSERT_EQ(frame_length_, fread(video_buffer.get(), 1, frame_length_,
|
||||
source_file_));
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
|
||||
0, kVideoRotation_0, &video_frame_));
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_EQ(0, video_frame2.CopyFrame(video_frame_));
|
||||
ASSERT_EQ(0, vpm_->Deflickering(&video_frame_, &stats));
|
||||
vpm_->Reset();
|
||||
ASSERT_EQ(0, vp_->Deflickering(&video_frame_, &stats));
|
||||
|
||||
// Retrieve frame stats again in case Deflickering() has zeroed them.
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame2));
|
||||
ASSERT_EQ(0, vpm_->Deflickering(&video_frame2, &stats));
|
||||
vp_->GetFrameStats(video_frame2, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
ASSERT_EQ(0, vp_->Deflickering(&video_frame2, &stats));
|
||||
EXPECT_TRUE(CompareFrames(video_frame_, video_frame2));
|
||||
|
||||
ASSERT_EQ(frame_length_, fread(video_buffer.get(), 1, frame_length_,
|
||||
source_file_));
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
|
||||
0, kVideoRotation_0, &video_frame_));
|
||||
ASSERT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
video_frame2.CopyFrame(video_frame_);
|
||||
ASSERT_EQ(0, vpm_->BrightnessDetection(video_frame_, stats));
|
||||
vpm_->Reset();
|
||||
ASSERT_EQ(0, vpm_->BrightnessDetection(video_frame2, stats));
|
||||
ASSERT_EQ(0, vp_->BrightnessDetection(video_frame_, stats));
|
||||
|
||||
ASSERT_EQ(0, vp_->BrightnessDetection(video_frame2, stats));
|
||||
EXPECT_TRUE(CompareFrames(video_frame_, video_frame2));
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(FrameStats)) {
|
||||
VideoProcessingModule::FrameStats stats;
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(FrameStats)) {
|
||||
VideoProcessing::FrameStats stats;
|
||||
vp_->ClearFrameStats(&stats);
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
ASSERT_EQ(frame_length_, fread(video_buffer.get(), 1, frame_length_,
|
||||
source_file_));
|
||||
EXPECT_EQ(0, ConvertToI420(kI420, video_buffer.get(), 0, 0, width_, height_,
|
||||
0, kVideoRotation_0, &video_frame_));
|
||||
|
||||
EXPECT_FALSE(vpm_->ValidFrameStats(stats));
|
||||
EXPECT_EQ(0, vpm_->GetFrameStats(&stats, video_frame_));
|
||||
EXPECT_TRUE(vpm_->ValidFrameStats(stats));
|
||||
EXPECT_FALSE(vp_->ValidFrameStats(stats));
|
||||
vp_->GetFrameStats(video_frame_, &stats);
|
||||
EXPECT_GT(stats.num_pixels, 0u);
|
||||
EXPECT_TRUE(vp_->ValidFrameStats(stats));
|
||||
|
||||
printf("\nFrameStats\n");
|
||||
printf("mean: %u\nnum_pixels: %u\nsubSamplWidth: "
|
||||
"%u\nsumSamplHeight: %u\nsum: %u\n\n",
|
||||
printf("mean: %u\nnum_pixels: %u\nsubSamplFactor: %u\nsum: %u\n\n",
|
||||
static_cast<unsigned int>(stats.mean),
|
||||
static_cast<unsigned int>(stats.num_pixels),
|
||||
static_cast<unsigned int>(stats.subSamplHeight),
|
||||
static_cast<unsigned int>(stats.subSamplWidth),
|
||||
static_cast<unsigned int>(stats.sub_sampling_factor),
|
||||
static_cast<unsigned int>(stats.sum));
|
||||
|
||||
vpm_->ClearFrameStats(&stats);
|
||||
EXPECT_FALSE(vpm_->ValidFrameStats(stats));
|
||||
vp_->ClearFrameStats(&stats);
|
||||
EXPECT_FALSE(vp_->ValidFrameStats(stats));
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(PreprocessorLogic)) {
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(PreprocessorLogic)) {
|
||||
// Disable temporal sampling (frame dropping).
|
||||
vpm_->EnableTemporalDecimation(false);
|
||||
vp_->EnableTemporalDecimation(false);
|
||||
int resolution = 100;
|
||||
EXPECT_EQ(VPM_OK, vpm_->SetTargetResolution(resolution, resolution, 15));
|
||||
EXPECT_EQ(VPM_OK, vpm_->SetTargetResolution(resolution, resolution, 30));
|
||||
EXPECT_EQ(VPM_OK, vp_->SetTargetResolution(resolution, resolution, 15));
|
||||
EXPECT_EQ(VPM_OK, vp_->SetTargetResolution(resolution, resolution, 30));
|
||||
// Disable spatial sampling.
|
||||
vpm_->SetInputFrameResampleMode(kNoRescaling);
|
||||
EXPECT_EQ(VPM_OK, vpm_->SetTargetResolution(resolution, resolution, 30));
|
||||
vp_->SetInputFrameResampleMode(kNoRescaling);
|
||||
EXPECT_EQ(VPM_OK, vp_->SetTargetResolution(resolution, resolution, 30));
|
||||
VideoFrame* out_frame = NULL;
|
||||
// Set rescaling => output frame != NULL.
|
||||
vpm_->SetInputFrameResampleMode(kFastRescaling);
|
||||
PreprocessFrameAndVerify(video_frame_, resolution, resolution, vpm_,
|
||||
&out_frame);
|
||||
vp_->SetInputFrameResampleMode(kFastRescaling);
|
||||
PreprocessFrameAndVerify(video_frame_, resolution, resolution, vp_,
|
||||
out_frame);
|
||||
// No rescaling=> output frame = NULL.
|
||||
vpm_->SetInputFrameResampleMode(kNoRescaling);
|
||||
EXPECT_EQ(VPM_OK, vpm_->PreprocessFrame(video_frame_, &out_frame));
|
||||
EXPECT_TRUE(out_frame == NULL);
|
||||
vp_->SetInputFrameResampleMode(kNoRescaling);
|
||||
EXPECT_TRUE(vp_->PreprocessFrame(video_frame_) != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Resampler)) {
|
||||
TEST_F(VideoProcessingTest, DISABLED_ON_IOS(Resampler)) {
|
||||
enum { NumRuns = 1 };
|
||||
|
||||
int64_t min_runtime = 0;
|
||||
@ -206,9 +208,9 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Resampler)) {
|
||||
"Cannot read input file \n";
|
||||
|
||||
// CA not needed here
|
||||
vpm_->EnableContentAnalysis(false);
|
||||
vp_->EnableContentAnalysis(false);
|
||||
// no temporal decimation
|
||||
vpm_->EnableTemporalDecimation(false);
|
||||
vp_->EnableTemporalDecimation(false);
|
||||
|
||||
// Reading test frame
|
||||
rtc::scoped_ptr<uint8_t[]> video_buffer(new uint8_t[frame_length_]);
|
||||
@ -231,43 +233,43 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Resampler)) {
|
||||
|
||||
// Test scaling to different sizes: source is of |width|/|height| = 352/288.
|
||||
// Pure scaling:
|
||||
TestSize(video_frame_, video_frame_, width_ / 4, height_ / 4, 25.2, vpm_);
|
||||
TestSize(video_frame_, video_frame_, width_ / 2, height_ / 2, 28.1, vpm_);
|
||||
TestSize(video_frame_, video_frame_, width_ / 4, height_ / 4, 25.2, vp_);
|
||||
TestSize(video_frame_, video_frame_, width_ / 2, height_ / 2, 28.1, vp_);
|
||||
// No resampling:
|
||||
TestSize(video_frame_, video_frame_, width_, height_, -1, vpm_);
|
||||
TestSize(video_frame_, video_frame_, 2 * width_, 2 * height_, 32.2, vpm_);
|
||||
TestSize(video_frame_, video_frame_, width_, height_, -1, vp_);
|
||||
TestSize(video_frame_, video_frame_, 2 * width_, 2 * height_, 32.2, vp_);
|
||||
|
||||
// Scaling and cropping. The cropped source frame is the largest center
|
||||
// aligned region that can be used from the source while preserving aspect
|
||||
// ratio.
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 56, 352, 176,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 100, 50, 24.0, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 100, 50, 24.0, vp_);
|
||||
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 30, 352, 225,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 400, 256, 31.3, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 400, 256, 31.3, vp_);
|
||||
|
||||
CropFrame(video_buffer.get(), width_, height_, 68, 0, 216, 288,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 480, 640, 32.15, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 480, 640, 32.15, vp_);
|
||||
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 12, 352, 264,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 960, 720, 32.2, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 960, 720, 32.2, vp_);
|
||||
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 44, 352, 198,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 1280, 720, 32.15, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 1280, 720, 32.15, vp_);
|
||||
|
||||
// Upsampling to odd size.
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 26, 352, 233,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 501, 333, 32.05, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 501, 333, 32.05, vp_);
|
||||
// Downsample to odd size.
|
||||
CropFrame(video_buffer.get(), width_, height_, 0, 34, 352, 219,
|
||||
&cropped_source_frame);
|
||||
TestSize(video_frame_, cropped_source_frame, 281, 175, 29.3, vpm_);
|
||||
TestSize(video_frame_, cropped_source_frame, 281, 175, 29.3, vp_);
|
||||
|
||||
// Stop timer.
|
||||
const int64_t runtime = (TickTime::Now() - time_start).Microseconds();
|
||||
@ -286,23 +288,24 @@ TEST_F(VideoProcessingModuleTest, DISABLED_ON_IOS(Resampler)) {
|
||||
void PreprocessFrameAndVerify(const VideoFrame& source,
|
||||
int target_width,
|
||||
int target_height,
|
||||
VideoProcessingModule* vpm,
|
||||
VideoFrame** out_frame) {
|
||||
VideoProcessing* vpm,
|
||||
const VideoFrame* out_frame) {
|
||||
ASSERT_EQ(VPM_OK, vpm->SetTargetResolution(target_width, target_height, 30));
|
||||
ASSERT_EQ(VPM_OK, vpm->PreprocessFrame(source, out_frame));
|
||||
out_frame = vpm->PreprocessFrame(source);
|
||||
EXPECT_TRUE(out_frame != nullptr);
|
||||
|
||||
// If no resizing is needed, expect NULL.
|
||||
// If no resizing is needed, expect the original frame.
|
||||
if (target_width == source.width() && target_height == source.height()) {
|
||||
EXPECT_EQ(NULL, *out_frame);
|
||||
EXPECT_EQ(&source, out_frame);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the resampled frame.
|
||||
EXPECT_TRUE(*out_frame != NULL);
|
||||
EXPECT_EQ(source.render_time_ms(), (*out_frame)->render_time_ms());
|
||||
EXPECT_EQ(source.timestamp(), (*out_frame)->timestamp());
|
||||
EXPECT_EQ(target_width, (*out_frame)->width());
|
||||
EXPECT_EQ(target_height, (*out_frame)->height());
|
||||
EXPECT_TRUE(out_frame != NULL);
|
||||
EXPECT_EQ(source.render_time_ms(), (out_frame)->render_time_ms());
|
||||
EXPECT_EQ(source.timestamp(), (out_frame)->timestamp());
|
||||
EXPECT_EQ(target_width, (out_frame)->width());
|
||||
EXPECT_EQ(target_height, (out_frame)->height());
|
||||
}
|
||||
|
||||
void CropFrame(const uint8_t* source_data,
|
||||
@ -326,12 +329,12 @@ void TestSize(const VideoFrame& source_frame,
|
||||
int target_width,
|
||||
int target_height,
|
||||
double expected_psnr,
|
||||
VideoProcessingModule* vpm) {
|
||||
VideoProcessing* vpm) {
|
||||
// Resample source_frame to out_frame.
|
||||
VideoFrame* out_frame = NULL;
|
||||
vpm->SetInputFrameResampleMode(kBox);
|
||||
PreprocessFrameAndVerify(source_frame, target_width, target_height, vpm,
|
||||
&out_frame);
|
||||
out_frame);
|
||||
if (out_frame == NULL)
|
||||
return;
|
||||
WriteProcessedFrameForVisualInspection(source_frame, *out_frame);
|
||||
@ -340,7 +343,7 @@ void TestSize(const VideoFrame& source_frame,
|
||||
VideoFrame resampled_source_frame;
|
||||
resampled_source_frame.CopyFrame(*out_frame);
|
||||
PreprocessFrameAndVerify(resampled_source_frame, cropped_source_frame.width(),
|
||||
cropped_source_frame.height(), vpm, &out_frame);
|
||||
cropped_source_frame.height(), vpm, out_frame);
|
||||
WriteProcessedFrameForVisualInspection(resampled_source_frame, *out_frame);
|
||||
|
||||
// Compute PSNR against the cropped source frame and check expectation.
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#ifndef WEBRTC_MODULES_VIDEO_PROCESSING_TEST_VIDEO_PROCESSING_UNITTEST_H_
|
||||
#define WEBRTC_MODULES_VIDEO_PROCESSING_TEST_VIDEO_PROCESSING_UNITTEST_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
@ -18,9 +20,9 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class VideoProcessingModuleTest : public ::testing::Test {
|
||||
class VideoProcessingTest : public ::testing::Test {
|
||||
protected:
|
||||
VideoProcessingModuleTest();
|
||||
VideoProcessingTest();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
static void SetUpTestCase() {
|
||||
@ -31,7 +33,7 @@ class VideoProcessingModuleTest : public ::testing::Test {
|
||||
static void TearDownTestCase() {
|
||||
Trace::ReturnTrace();
|
||||
}
|
||||
VideoProcessingModule* vpm_;
|
||||
VideoProcessing* vp_;
|
||||
FILE* source_file_;
|
||||
VideoFrame video_frame_;
|
||||
const int width_;
|
||||
|
||||
@ -92,7 +92,7 @@ bool VPMVideoDecimator::DropFrame() {
|
||||
}
|
||||
|
||||
|
||||
uint32_t VPMVideoDecimator::Decimatedframe_rate() {
|
||||
uint32_t VPMVideoDecimator::GetDecimatedFrameRate() {
|
||||
ProcessIncomingframe_rate(TickTime::MillisecondTimestamp());
|
||||
if (!enable_temporal_decimation_) {
|
||||
return static_cast<uint32_t>(incoming_frame_rate_ + 0.5f);
|
||||
|
||||
@ -32,7 +32,7 @@ class VPMVideoDecimator {
|
||||
void UpdateIncomingframe_rate();
|
||||
|
||||
// Get Decimated Frame Rate/Dimensions.
|
||||
uint32_t Decimatedframe_rate();
|
||||
uint32_t GetDecimatedFrameRate();
|
||||
|
||||
// Get input frame rate.
|
||||
uint32_t Inputframe_rate();
|
||||
|
||||
@ -20,8 +20,6 @@
|
||||
'sources': [
|
||||
'include/video_processing.h',
|
||||
'include/video_processing_defines.h',
|
||||
'brighten.cc',
|
||||
'brighten.h',
|
||||
'brightness_detection.cc',
|
||||
'brightness_detection.h',
|
||||
'content_analysis.cc',
|
||||
|
||||
@ -7,87 +7,70 @@
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "webrtc/base/logging.h"
|
||||
|
||||
#include "webrtc/modules/video_processing/video_processing_impl.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
void SetSubSampling(VideoProcessingModule::FrameStats* stats,
|
||||
const int32_t width,
|
||||
const int32_t height) {
|
||||
|
||||
int GetSubSamplingFactor(int width, int height) {
|
||||
if (width * height >= 640 * 480) {
|
||||
stats->subSamplWidth = 3;
|
||||
stats->subSamplHeight = 3;
|
||||
return 3;
|
||||
} else if (width * height >= 352 * 288) {
|
||||
stats->subSamplWidth = 2;
|
||||
stats->subSamplHeight = 2;
|
||||
return 2;
|
||||
} else if (width * height >= 176 * 144) {
|
||||
stats->subSamplWidth = 1;
|
||||
stats->subSamplHeight = 1;
|
||||
return 1;
|
||||
} else {
|
||||
stats->subSamplWidth = 0;
|
||||
stats->subSamplHeight = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
VideoProcessingModule* VideoProcessingModule::Create() {
|
||||
return new VideoProcessingModuleImpl();
|
||||
VideoProcessing* VideoProcessing::Create() {
|
||||
return new VideoProcessingImpl();
|
||||
}
|
||||
|
||||
void VideoProcessingModule::Destroy(VideoProcessingModule* module) {
|
||||
if (module)
|
||||
delete static_cast<VideoProcessingModuleImpl*>(module);
|
||||
}
|
||||
VideoProcessingImpl::VideoProcessingImpl() {}
|
||||
VideoProcessingImpl::~VideoProcessingImpl() {}
|
||||
|
||||
VideoProcessingModuleImpl::VideoProcessingModuleImpl() {}
|
||||
VideoProcessingModuleImpl::~VideoProcessingModuleImpl() {}
|
||||
|
||||
void VideoProcessingModuleImpl::Reset() {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
deflickering_.Reset();
|
||||
brightness_detection_.Reset();
|
||||
frame_pre_processor_.Reset();
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModule::GetFrameStats(FrameStats* stats,
|
||||
const VideoFrame& frame) {
|
||||
void VideoProcessing::GetFrameStats(const VideoFrame& frame,
|
||||
FrameStats* stats) {
|
||||
ClearFrameStats(stats); // The histogram needs to be zeroed out.
|
||||
if (frame.IsZeroSize()) {
|
||||
LOG(LS_ERROR) << "Zero size frame.";
|
||||
return VPM_PARAMETER_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
int width = frame.width();
|
||||
int height = frame.height();
|
||||
|
||||
ClearFrameStats(stats); // The histogram needs to be zeroed out.
|
||||
SetSubSampling(stats, width, height);
|
||||
stats->sub_sampling_factor = GetSubSamplingFactor(width, height);
|
||||
|
||||
const uint8_t* buffer = frame.buffer(kYPlane);
|
||||
// Compute histogram and sum of frame
|
||||
for (int i = 0; i < height; i += (1 << stats->subSamplHeight)) {
|
||||
for (int i = 0; i < height; i += (1 << stats->sub_sampling_factor)) {
|
||||
int k = i * width;
|
||||
for (int j = 0; j < width; j += (1 << stats->subSamplWidth)) {
|
||||
for (int j = 0; j < width; j += (1 << stats->sub_sampling_factor)) {
|
||||
stats->hist[buffer[k + j]]++;
|
||||
stats->sum += buffer[k + j];
|
||||
}
|
||||
}
|
||||
|
||||
stats->num_pixels = (width * height) / ((1 << stats->subSamplWidth) *
|
||||
(1 << stats->subSamplHeight));
|
||||
stats->num_pixels = (width * height) /
|
||||
((1 << stats->sub_sampling_factor) * (1 << stats->sub_sampling_factor));
|
||||
assert(stats->num_pixels > 0);
|
||||
|
||||
// Compute mean value of frame
|
||||
stats->mean = stats->sum / stats->num_pixels;
|
||||
|
||||
return VPM_OK;
|
||||
}
|
||||
|
||||
bool VideoProcessingModule::ValidFrameStats(const FrameStats& stats) {
|
||||
bool VideoProcessing::ValidFrameStats(const FrameStats& stats) {
|
||||
if (stats.num_pixels == 0) {
|
||||
LOG(LS_WARNING) << "Invalid frame stats.";
|
||||
return false;
|
||||
@ -95,26 +78,41 @@ bool VideoProcessingModule::ValidFrameStats(const FrameStats& stats) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void VideoProcessingModule::ClearFrameStats(FrameStats* stats) {
|
||||
void VideoProcessing::ClearFrameStats(FrameStats* stats) {
|
||||
stats->mean = 0;
|
||||
stats->sum = 0;
|
||||
stats->num_pixels = 0;
|
||||
stats->subSamplWidth = 0;
|
||||
stats->subSamplHeight = 0;
|
||||
stats->sub_sampling_factor = 0;
|
||||
memset(stats->hist, 0, sizeof(stats->hist));
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModule::Brighten(VideoFrame* frame, int delta) {
|
||||
return VideoProcessing::Brighten(frame, delta);
|
||||
void VideoProcessing::Brighten(int delta, VideoFrame* frame) {
|
||||
RTC_DCHECK(!frame->IsZeroSize());
|
||||
RTC_DCHECK(frame->width() > 0);
|
||||
RTC_DCHECK(frame->height() > 0);
|
||||
|
||||
int num_pixels = frame->width() * frame->height();
|
||||
|
||||
int look_up[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int val = i + delta;
|
||||
look_up[i] = ((((val < 0) ? 0 : val) > 255) ? 255 : val);
|
||||
}
|
||||
|
||||
uint8_t* temp_ptr = frame->buffer(kYPlane);
|
||||
for (int i = 0; i < num_pixels; i++) {
|
||||
*temp_ptr = static_cast<uint8_t>(look_up[*temp_ptr]);
|
||||
temp_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModuleImpl::Deflickering(VideoFrame* frame,
|
||||
FrameStats* stats) {
|
||||
int32_t VideoProcessingImpl::Deflickering(VideoFrame* frame,
|
||||
FrameStats* stats) {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
return deflickering_.ProcessFrame(frame, stats);
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModuleImpl::BrightnessDetection(
|
||||
int32_t VideoProcessingImpl::BrightnessDetection(
|
||||
const VideoFrame& frame,
|
||||
const FrameStats& stats) {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
@ -122,58 +120,62 @@ int32_t VideoProcessingModuleImpl::BrightnessDetection(
|
||||
}
|
||||
|
||||
|
||||
void VideoProcessingModuleImpl::EnableTemporalDecimation(bool enable) {
|
||||
void VideoProcessingImpl::EnableTemporalDecimation(bool enable) {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
frame_pre_processor_.EnableTemporalDecimation(enable);
|
||||
}
|
||||
|
||||
|
||||
void VideoProcessingModuleImpl::SetInputFrameResampleMode(VideoFrameResampling
|
||||
resampling_mode) {
|
||||
void VideoProcessingImpl::SetInputFrameResampleMode(VideoFrameResampling
|
||||
resampling_mode) {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
frame_pre_processor_.SetInputFrameResampleMode(resampling_mode);
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModuleImpl::SetTargetResolution(uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t frame_rate) {
|
||||
int32_t VideoProcessingImpl::SetTargetResolution(uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t frame_rate) {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
return frame_pre_processor_.SetTargetResolution(width, height, frame_rate);
|
||||
}
|
||||
|
||||
void VideoProcessingModuleImpl::SetTargetFramerate(int frame_rate) {
|
||||
void VideoProcessingImpl::SetTargetFramerate(int frame_rate) {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
frame_pre_processor_.SetTargetFramerate(frame_rate);
|
||||
}
|
||||
|
||||
uint32_t VideoProcessingModuleImpl::Decimatedframe_rate() {
|
||||
uint32_t VideoProcessingImpl::GetDecimatedFrameRate() {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
return frame_pre_processor_.Decimatedframe_rate();
|
||||
return frame_pre_processor_.GetDecimatedFrameRate();
|
||||
}
|
||||
|
||||
uint32_t VideoProcessingModuleImpl::DecimatedWidth() const {
|
||||
uint32_t VideoProcessingImpl::GetDecimatedWidth() const {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
return frame_pre_processor_.DecimatedWidth();
|
||||
return frame_pre_processor_.GetDecimatedWidth();
|
||||
}
|
||||
|
||||
uint32_t VideoProcessingModuleImpl::DecimatedHeight() const {
|
||||
uint32_t VideoProcessingImpl::GetDecimatedHeight() const {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
return frame_pre_processor_.DecimatedHeight();
|
||||
return frame_pre_processor_.GetDecimatedHeight();
|
||||
}
|
||||
|
||||
int32_t VideoProcessingModuleImpl::PreprocessFrame(
|
||||
const VideoFrame& frame,
|
||||
VideoFrame** processed_frame) {
|
||||
void VideoProcessingImpl::EnableDenosing(bool enable) {
|
||||
rtc::CritScope cs(&mutex_);
|
||||
frame_pre_processor_.EnableDenosing(enable);
|
||||
}
|
||||
|
||||
const VideoFrame* VideoProcessingImpl::PreprocessFrame(
|
||||
const VideoFrame& frame) {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
return frame_pre_processor_.PreprocessFrame(frame, processed_frame);
|
||||
return frame_pre_processor_.PreprocessFrame(frame);
|
||||
}
|
||||
|
||||
VideoContentMetrics* VideoProcessingModuleImpl::ContentMetrics() const {
|
||||
VideoContentMetrics* VideoProcessingImpl::GetContentMetrics() const {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
return frame_pre_processor_.ContentMetrics();
|
||||
return frame_pre_processor_.GetContentMetrics();
|
||||
}
|
||||
|
||||
void VideoProcessingModuleImpl::EnableContentAnalysis(bool enable) {
|
||||
void VideoProcessingImpl::EnableContentAnalysis(bool enable) {
|
||||
rtc::CritScope mutex(&mutex_);
|
||||
frame_pre_processor_.EnableContentAnalysis(enable);
|
||||
}
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/modules/video_processing/include/video_processing.h"
|
||||
#include "webrtc/modules/video_processing/brighten.h"
|
||||
#include "webrtc/modules/video_processing/brightness_detection.h"
|
||||
#include "webrtc/modules/video_processing/deflickering.h"
|
||||
#include "webrtc/modules/video_processing/frame_preprocessor.h"
|
||||
@ -21,47 +20,28 @@
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
|
||||
class VideoProcessingModuleImpl : public VideoProcessingModule {
|
||||
class VideoProcessingImpl : public VideoProcessing {
|
||||
public:
|
||||
VideoProcessingModuleImpl();
|
||||
~VideoProcessingModuleImpl() override;
|
||||
|
||||
void Reset() override;
|
||||
VideoProcessingImpl();
|
||||
~VideoProcessingImpl() override;
|
||||
|
||||
// Implements VideoProcessing.
|
||||
int32_t Deflickering(VideoFrame* frame, FrameStats* stats) override;
|
||||
|
||||
int32_t BrightnessDetection(const VideoFrame& frame,
|
||||
const FrameStats& stats) override;
|
||||
|
||||
// Frame pre-processor functions
|
||||
|
||||
// Enable temporal decimation
|
||||
void EnableTemporalDecimation(bool enable) override;
|
||||
|
||||
void SetInputFrameResampleMode(VideoFrameResampling resampling_mode) override;
|
||||
|
||||
// Enable content analysis
|
||||
void EnableContentAnalysis(bool enable) override;
|
||||
|
||||
// Set Target Resolution: frame rate and dimension
|
||||
int32_t SetTargetResolution(uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t frame_rate) override;
|
||||
|
||||
void SetTargetFramerate(int frame_rate) override;
|
||||
|
||||
// Get decimated values: frame rate/dimension
|
||||
uint32_t Decimatedframe_rate() override;
|
||||
uint32_t DecimatedWidth() const override;
|
||||
uint32_t DecimatedHeight() const override;
|
||||
|
||||
// Preprocess:
|
||||
// Pre-process incoming frame: Sample when needed and compute content
|
||||
// metrics when enabled.
|
||||
// If no resampling takes place - processed_frame is set to NULL.
|
||||
int32_t PreprocessFrame(const VideoFrame& frame,
|
||||
VideoFrame** processed_frame) override;
|
||||
VideoContentMetrics* ContentMetrics() const override;
|
||||
uint32_t GetDecimatedFrameRate() override;
|
||||
uint32_t GetDecimatedWidth() const override;
|
||||
uint32_t GetDecimatedHeight() const override;
|
||||
void EnableDenosing(bool enable) override;
|
||||
const VideoFrame* PreprocessFrame(const VideoFrame& frame) override;
|
||||
VideoContentMetrics* GetContentMetrics() const override;
|
||||
|
||||
private:
|
||||
mutable rtc::CriticalSection mutex_;
|
||||
@ -70,6 +50,6 @@ class VideoProcessingModuleImpl : public VideoProcessingModule {
|
||||
VPMFramePreprocessor frame_pre_processor_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_PROCESSING_VIDEO_PROCESSING_IMPL_H_
|
||||
|
||||
@ -72,7 +72,7 @@ std::vector<uint32_t> AllocateStreamBitrates(
|
||||
|
||||
class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
||||
public:
|
||||
explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
|
||||
explicit QMVideoSettingsCallback(VideoProcessing* vpm);
|
||||
|
||||
~QMVideoSettingsCallback();
|
||||
|
||||
@ -85,7 +85,7 @@ class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
||||
void SetTargetFramerate(int frame_rate);
|
||||
|
||||
private:
|
||||
VideoProcessingModule* vpm_;
|
||||
VideoProcessing* vp_;
|
||||
};
|
||||
|
||||
class ViEBitrateObserver : public BitrateObserver {
|
||||
@ -111,8 +111,8 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
||||
PacedSender* pacer,
|
||||
BitrateAllocator* bitrate_allocator)
|
||||
: number_of_cores_(number_of_cores),
|
||||
vpm_(VideoProcessingModule::Create()),
|
||||
qm_callback_(new QMVideoSettingsCallback(vpm_.get())),
|
||||
vp_(VideoProcessing::Create()),
|
||||
qm_callback_(new QMVideoSettingsCallback(vp_.get())),
|
||||
vcm_(VideoCodingModule::Create(Clock::GetRealTimeClock(),
|
||||
this,
|
||||
qm_callback_.get())),
|
||||
@ -140,10 +140,10 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores,
|
||||
}
|
||||
|
||||
bool ViEEncoder::Init() {
|
||||
vpm_->EnableTemporalDecimation(true);
|
||||
vp_->EnableTemporalDecimation(true);
|
||||
|
||||
// Enable/disable content analysis: off by default for now.
|
||||
vpm_->EnableContentAnalysis(false);
|
||||
vp_->EnableContentAnalysis(false);
|
||||
|
||||
if (vcm_->RegisterTransportCallback(this) != 0) {
|
||||
return false;
|
||||
@ -168,7 +168,6 @@ void ViEEncoder::StopThreadsAndRemoveSharedMembers() {
|
||||
if (bitrate_allocator_)
|
||||
bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get());
|
||||
module_process_thread_->DeRegisterModule(vcm_.get());
|
||||
module_process_thread_->DeRegisterModule(vpm_.get());
|
||||
}
|
||||
|
||||
ViEEncoder::~ViEEncoder() {
|
||||
@ -211,8 +210,8 @@ int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) {
|
||||
int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
|
||||
RTC_DCHECK(send_payload_router_ != NULL);
|
||||
// Setting target width and height for VPM.
|
||||
if (vpm_->SetTargetResolution(video_codec.width, video_codec.height,
|
||||
video_codec.maxFramerate) != VPM_OK) {
|
||||
if (vp_->SetTargetResolution(video_codec.width, video_codec.height,
|
||||
video_codec.maxFramerate) != VPM_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -358,16 +357,13 @@ void ViEEncoder::DeliverFrame(VideoFrame video_frame) {
|
||||
|
||||
TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
|
||||
"Encode");
|
||||
VideoFrame* decimated_frame = NULL;
|
||||
const VideoFrame* frame_to_send = &video_frame;
|
||||
// TODO(wuchengli): support texture frames.
|
||||
if (video_frame.native_handle() == NULL) {
|
||||
// Pass frame via preprocessor.
|
||||
const int ret = vpm_->PreprocessFrame(video_frame, &decimated_frame);
|
||||
if (ret == 1) {
|
||||
// Drop this frame.
|
||||
return;
|
||||
}
|
||||
if (ret != VPM_OK) {
|
||||
frame_to_send = vp_->PreprocessFrame(video_frame);
|
||||
if (!frame_to_send) {
|
||||
// Drop this frame, or there was an error processing it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -376,19 +372,11 @@ void ViEEncoder::DeliverFrame(VideoFrame video_frame) {
|
||||
// make a deep copy of |video_frame|.
|
||||
VideoFrame copied_frame;
|
||||
if (pre_encode_callback_) {
|
||||
// If the frame was not resampled or scaled => use copy of original.
|
||||
if (decimated_frame == NULL) {
|
||||
copied_frame.CopyFrame(video_frame);
|
||||
decimated_frame = &copied_frame;
|
||||
}
|
||||
pre_encode_callback_->FrameCallback(decimated_frame);
|
||||
copied_frame.CopyFrame(*frame_to_send);
|
||||
pre_encode_callback_->FrameCallback(&copied_frame);
|
||||
frame_to_send = &copied_frame;
|
||||
}
|
||||
|
||||
// If the frame was not resampled, scaled, or touched by FrameCallback => use
|
||||
// original. The frame is const from here.
|
||||
const VideoFrame* output_frame =
|
||||
(decimated_frame != NULL) ? decimated_frame : &video_frame;
|
||||
|
||||
if (codec_type == webrtc::kVideoCodecVP8) {
|
||||
webrtc::CodecSpecificInfo codec_specific_info;
|
||||
codec_specific_info.codecType = webrtc::kVideoCodecVP8;
|
||||
@ -406,11 +394,11 @@ void ViEEncoder::DeliverFrame(VideoFrame video_frame) {
|
||||
has_received_rpsi_ = false;
|
||||
}
|
||||
|
||||
vcm_->AddVideoFrame(*output_frame, vpm_->ContentMetrics(),
|
||||
vcm_->AddVideoFrame(*frame_to_send, vp_->GetContentMetrics(),
|
||||
&codec_specific_info);
|
||||
return;
|
||||
}
|
||||
vcm_->AddVideoFrame(*output_frame);
|
||||
vcm_->AddVideoFrame(*frame_to_send);
|
||||
}
|
||||
|
||||
int ViEEncoder::SendKeyFrame() {
|
||||
@ -448,10 +436,10 @@ void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) {
|
||||
if (target_delay_ms > 0) {
|
||||
// Disable external frame-droppers.
|
||||
vcm_->EnableFrameDropper(false);
|
||||
vpm_->EnableTemporalDecimation(false);
|
||||
vp_->EnableTemporalDecimation(false);
|
||||
} else {
|
||||
// Real-time mode - enable frame droppers.
|
||||
vpm_->EnableTemporalDecimation(true);
|
||||
vp_->EnableTemporalDecimation(true);
|
||||
vcm_->EnableFrameDropper(true);
|
||||
}
|
||||
}
|
||||
@ -619,8 +607,8 @@ void ViEEncoder::RegisterPostEncodeImageCallback(
|
||||
vcm_->RegisterPostEncodeImageCallback(post_encode_callback);
|
||||
}
|
||||
|
||||
QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
|
||||
: vpm_(vpm) {
|
||||
QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm)
|
||||
: vp_(vpm) {
|
||||
}
|
||||
|
||||
QMVideoSettingsCallback::~QMVideoSettingsCallback() {
|
||||
@ -630,11 +618,11 @@ int32_t QMVideoSettingsCallback::SetVideoQMSettings(
|
||||
const uint32_t frame_rate,
|
||||
const uint32_t width,
|
||||
const uint32_t height) {
|
||||
return vpm_->SetTargetResolution(width, height, frame_rate);
|
||||
return vp_->SetTargetResolution(width, height, frame_rate);
|
||||
}
|
||||
|
||||
void QMVideoSettingsCallback::SetTargetFramerate(int frame_rate) {
|
||||
vpm_->SetTargetFramerate(frame_rate);
|
||||
vp_->SetTargetFramerate(frame_rate);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -152,7 +152,7 @@ class ViEEncoder : public RtcpIntraFrameObserver,
|
||||
|
||||
const uint32_t number_of_cores_;
|
||||
|
||||
const rtc::scoped_ptr<VideoProcessingModule> vpm_;
|
||||
const rtc::scoped_ptr<VideoProcessing> vp_;
|
||||
const rtc::scoped_ptr<QMVideoSettingsCallback> qm_callback_;
|
||||
const rtc::scoped_ptr<VideoCodingModule> vcm_;
|
||||
rtc::scoped_refptr<PayloadRouter> send_payload_router_;
|
||||
|
||||
Reference in New Issue
Block a user