Bug 1043808: Don't allow content_analysis to half-initialize on small capture sizes r=pkerr a=sylvestre
authorRandell Jesup <rjesup@jesup.org>
Wed, 30 Jul 2014 17:35:05 -0400
changeset 217432 b13ba3879b2eb3c11e73173c3cfa55a704a21807
parent 217431 6ca5b28fb162bc0837db6fcb6c3224ffbc3bee04
child 217433 d08b3b54c0f5d0c99fb2c28d75a63e7987d556cd
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspkerr, sylvestre
bugs1043808
milestone33.0a2
Bug 1043808: Don't allow content_analysis to half-initialize on small capture sizes r=pkerr a=sylvestre
media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.cc
media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.h
media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis_sse2.cc
--- a/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.cc
@@ -14,28 +14,26 @@
 
 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h"
 #include "webrtc/system_wrappers/interface/tick_util.h"
 
 namespace webrtc {
 
 VPMContentAnalysis::VPMContentAnalysis(bool runtime_cpu_detection)
     : orig_frame_(NULL),
-      prev_frame_(NULL),
       width_(0),
       height_(0),
       skip_num_(1),
       border_(8),
       motion_magnitude_(0.0f),
       spatial_pred_err_(0.0f),
       spatial_pred_err_h_(0.0f),
       spatial_pred_err_v_(0.0f),
       first_frame_(true),
-      ca_Init_(false),
-      content_metrics_(NULL) {
+      ca_Init_(false) {
   ComputeSpatialMetrics = &VPMContentAnalysis::ComputeSpatialMetrics_C;
   TemporalDiffMetric = &VPMContentAnalysis::TemporalDiffMetric_C;
 
   if (runtime_cpu_detection) {
 #if defined(WEBRTC_ARCH_X86_FAMILY)
     if (WebRtc_GetCPUInfo(kSSE2)) {
       ComputeSpatialMetrics = &VPMContentAnalysis::ComputeSpatialMetrics_SSE2;
       TemporalDiffMetric = &VPMContentAnalysis::TemporalDiffMetric_SSE2;
@@ -55,54 +53,50 @@ VideoContentMetrics* VPMContentAnalysis:
   if (inputFrame.IsZeroSize())
     return NULL;
 
   // Init if needed (native dimension change).
   if (width_ != inputFrame.width() || height_ != inputFrame.height()) {
     if (VPM_OK != Initialize(inputFrame.width(), inputFrame.height()))
       return NULL;
   }
-  // Only interested in the Y plane.
-  orig_frame_ = inputFrame.buffer(kYPlane);
+  // Compute motion metrics
+  if (ca_Init_) {
+    // Only interested in the Y plane.
+    orig_frame_ = inputFrame.buffer(kYPlane);
 
-  // Compute spatial metrics: 3 spatial prediction errors.
-  (this->*ComputeSpatialMetrics)();
+    // Compute spatial metrics: 3 spatial prediction errors.
+    (this->*ComputeSpatialMetrics)();
 
-  // Compute motion metrics
-  if (first_frame_ == false)
-    ComputeMotionMetrics();
+    if (first_frame_ == false) {
+      ComputeMotionMetrics();
+    }
 
-  // Saving current frame as previous one: Y only.
-  memcpy(prev_frame_, orig_frame_, width_ * height_);
+    // Saving current frame as previous one: Y only.
+    memcpy(prev_frame_.get(), orig_frame_, width_ * height_);
 
-  first_frame_ =  false;
-  ca_Init_ = true;
+    first_frame_ =  false;
+  }
 
   return ContentMetrics();
 }
 
 int32_t VPMContentAnalysis::Release() {
-  if (content_metrics_ != NULL) {
-    delete content_metrics_;
-    content_metrics_ = NULL;
-  }
-
-  if (prev_frame_ != NULL) {
-    delete [] prev_frame_;
-    prev_frame_ = NULL;
-  }
+  content_metrics_.reset(NULL);
+  prev_frame_.reset(NULL);
 
   width_ = 0;
   height_ = 0;
   first_frame_ = true;
 
   return VPM_OK;
 }
 
 int32_t VPMContentAnalysis::Initialize(int width, int height) {
+  ca_Init_ = false;
   width_ = width;
   height_ = height;
   first_frame_ = true;
 
   // skip parameter: # of skipped rows: for complexity reduction
   //  temporal also currently uses it for column reduction.
   skip_num_ = 1;
 
@@ -110,39 +104,37 @@ int32_t VPMContentAnalysis::Initialize(i
   if ( (height_ >=  576) && (width_ >= 704) ) {
     skip_num_ = 2;
   }
   // use skipNum = 4 for FULLL_HD images
   if ( (height_ >=  1080) && (width_ >= 1920) ) {
     skip_num_ = 4;
   }
 
-  if (content_metrics_ != NULL) {
-    delete content_metrics_;
-  }
-
-  if (prev_frame_ != NULL) {
-    delete [] prev_frame_;
-  }
+  content_metrics_.reset(NULL);
+  prev_frame_.reset(NULL);
 
   // Spatial Metrics don't work on a border of 8. Minimum processing
   // block size is 16 pixels.  So make sure the width and height support this.
   if (width_ <= 32 || height_ <= 32) {
-    ca_Init_ = false;
     return VPM_PARAMETER_ERROR;
   }
 
-  content_metrics_ = new VideoContentMetrics();
-  if (content_metrics_ == NULL) {
+  content_metrics_.reset(new VideoContentMetrics());
+  if (!content_metrics_) {
     return VPM_MEMORY;
   }
 
-  prev_frame_ = new uint8_t[width_ * height_];  // Y only.
-  if (prev_frame_ == NULL) return VPM_MEMORY;
+  prev_frame_.reset(new uint8_t[width_ * height_]);  // Y only.
+  if (!prev_frame_) {
+    return VPM_MEMORY;
+  }
 
+  // ok, all initialized
+  ca_Init_ = true;
   return VPM_OK;
 }
 
 
 // Compute motion metrics: magnitude over non-zero motion vectors,
 //  and size of zero cluster
 int32_t VPMContentAnalysis::ComputeMotionMetrics() {
   // Motion metrics: only one is derived from normalized
@@ -160,24 +152,25 @@ int32_t VPMContentAnalysis::TemporalDiff
   int sizei = height_;
   int sizej = width_;
   uint32_t tempDiffSum = 0;
   uint32_t pixelSum = 0;
   uint64_t pixelSqSum = 0;
 
   uint32_t num_pixels = 0;  // Counter for # of pixels.
   const int width_end = ((width_ - 2*border_) & -16) + border_;
+  uint8_t *prev_frame = prev_frame_.get();
 
   for (int i = border_; i < sizei - border_; i += skip_num_) {
     for (int j = border_; j < width_end; j++) {
       num_pixels += 1;
       int ssn =  i * sizej + j;
 
       uint8_t currPixel  = orig_frame_[ssn];
-      uint8_t prevPixel  = prev_frame_[ssn];
+      uint8_t prevPixel  = prev_frame[ssn];
 
       tempDiffSum += (uint32_t)abs((int16_t)(currPixel - prevPixel));
       pixelSum += (uint32_t) currPixel;
       pixelSqSum += (uint64_t) (currPixel * currPixel);
     }
   }
 
   // Default.
@@ -258,18 +251,20 @@ int32_t VPMContentAnalysis::ComputeSpati
   // 2X1:
   spatial_pred_err_v_ = spatialErrV / norm;
   return VPM_OK;
 }
 
 VideoContentMetrics* VPMContentAnalysis::ContentMetrics() {
   if (ca_Init_ == false) return NULL;
 
-  content_metrics_->spatial_pred_err = spatial_pred_err_;
-  content_metrics_->spatial_pred_err_h = spatial_pred_err_h_;
-  content_metrics_->spatial_pred_err_v = spatial_pred_err_v_;
-  // Motion metric: normalized temporal difference (MAD).
-  content_metrics_->motion_magnitude = motion_magnitude_;
+  if (content_metrics_) {
+    content_metrics_->spatial_pred_err = spatial_pred_err_;
+    content_metrics_->spatial_pred_err_h = spatial_pred_err_h_;
+    content_metrics_->spatial_pred_err_v = spatial_pred_err_v_;
+    // Motion metric: normalized temporal difference (MAD).
+    content_metrics_->motion_magnitude = motion_magnitude_;
+  }
 
-  return content_metrics_;
+  return content_metrics_.get();
 }
 
 }  // namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.h
+++ b/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis.h
@@ -61,28 +61,28 @@ class VPMContentAnalysis {
   int32_t ComputeSpatialMetrics_C();
 
 #if defined(WEBRTC_ARCH_X86_FAMILY)
   int32_t ComputeSpatialMetrics_SSE2();
   int32_t TemporalDiffMetric_SSE2();
 #endif
 
   const uint8_t* orig_frame_;
-  uint8_t* prev_frame_;
+  scoped_ptr<uint8_t> prev_frame_;
   int width_;
   int height_;
   int skip_num_;
   int border_;
 
   // Content Metrics: Stores the local average of the metrics.
   float motion_magnitude_;   // motion class
   float spatial_pred_err_;   // spatial class
   float spatial_pred_err_h_;  // spatial class
   float spatial_pred_err_v_;  // spatial class
   bool first_frame_;
   bool ca_Init_;
 
-  VideoContentMetrics*   content_metrics_;
+  scoped_ptr<VideoContentMetrics> content_metrics_;
 };
 
 }  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_VIDEO_PROCESSING_MAIN_SOURCE_CONTENT_ANALYSIS_H
--- a/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis_sse2.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_processing/main/source/content_analysis_sse2.cc
@@ -13,17 +13,17 @@
 #include <emmintrin.h>
 #include <math.h>
 
 namespace webrtc {
 
 int32_t VPMContentAnalysis::TemporalDiffMetric_SSE2() {
   uint32_t num_pixels = 0;       // counter for # of pixels
   const uint8_t* imgBufO = orig_frame_ + border_*width_ + border_;
-  const uint8_t* imgBufP = prev_frame_ + border_*width_ + border_;
+  const uint8_t* imgBufP = prev_frame_.get() + border_*width_ + border_;
 
   const int32_t width_end = ((width_ - 2*border_) & -16) + border_;
 
   __m128i sad_64   = _mm_setzero_si128();
   __m128i sum_64   = _mm_setzero_si128();
   __m128i sqsum_64 = _mm_setzero_si128();
   const __m128i z  = _mm_setzero_si128();