| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |    2  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 
|    3  * |    3  * | 
|    4  *  Use of this source code is governed by a BSD-style license |    4  *  Use of this source code is governed by a BSD-style license | 
|    5  *  that can be found in the LICENSE file in the root of the source |    5  *  that can be found in the LICENSE file in the root of the source | 
|    6  *  tree. An additional intellectual property rights grant can be found |    6  *  tree. An additional intellectual property rights grant can be found | 
|    7  *  in the file PATENTS.  All contributing project authors may |    7  *  in the file PATENTS.  All contributing project authors may | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |    8  *  be found in the AUTHORS file in the root of the source tree. | 
|    9  */ |    9  */ | 
|   10  |   10  | 
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   67   } |   67   } | 
|   68 } |   68 } | 
|   69 #endif |   69 #endif | 
|   70  |   70  | 
|   71 VideoDenoiser::VideoDenoiser(bool runtime_cpu_detection) |   71 VideoDenoiser::VideoDenoiser(bool runtime_cpu_detection) | 
|   72     : width_(0), |   72     : width_(0), | 
|   73       height_(0), |   73       height_(0), | 
|   74       filter_(DenoiserFilter::Create(runtime_cpu_detection, &cpu_type_)), |   74       filter_(DenoiserFilter::Create(runtime_cpu_detection, &cpu_type_)), | 
|   75       ne_(new NoiseEstimation()) {} |   75       ne_(new NoiseEstimation()) {} | 
|   76  |   76  | 
|   77 void VideoDenoiser::DenoiserReset(const VideoFrame& frame, |   77 void VideoDenoiser::DenoiserReset( | 
|   78                                   VideoFrame* denoised_frame, |   78     const rtc::scoped_refptr<VideoFrameBuffer>& frame, | 
|   79                                   VideoFrame* denoised_frame_prev) { |   79     rtc::scoped_refptr<I420Buffer>* denoised_frame, | 
|   80   width_ = frame.width(); |   80     rtc::scoped_refptr<I420Buffer>* denoised_frame_prev) { | 
|   81   height_ = frame.height(); |   81   width_ = frame->width(); | 
 |   82   height_ = frame->height(); | 
|   82   mb_cols_ = width_ >> 4; |   83   mb_cols_ = width_ >> 4; | 
|   83   mb_rows_ = height_ >> 4; |   84   mb_rows_ = height_ >> 4; | 
|   84   stride_y_ = frame.video_frame_buffer()->StrideY(); |   85   stride_y_ = frame->StrideY(); | 
|   85   stride_u_ = frame.video_frame_buffer()->StrideU(); |   86   stride_u_ = frame->StrideU(); | 
|   86   stride_v_ = frame.video_frame_buffer()->StrideV(); |   87   stride_v_ = frame->StrideV(); | 
|   87  |   88  | 
|   88   // Allocate an empty buffer for denoised_frame_prev. |   89   // Allocate an empty buffer for denoised_frame_prev. | 
|   89   denoised_frame_prev->CreateEmptyFrame(width_, height_, stride_y_, stride_u_, |   90   *denoised_frame_prev = new rtc::RefCountedObject<I420Buffer>( | 
|   90                                         stride_v_); |   91       width_, height_, stride_y_, stride_u_, stride_v_); | 
|   91   // Allocate and initialize denoised_frame with key frame. |   92   // Allocate and initialize denoised_frame with key frame. | 
|   92   denoised_frame->CreateFrame( |   93   *denoised_frame = I420Buffer::CopyKeepStride(frame); | 
|   93       frame.video_frame_buffer()->DataY(), |  | 
|   94       frame.video_frame_buffer()->DataU(), |  | 
|   95       frame.video_frame_buffer()->DataV(), |  | 
|   96       width_, height_, stride_y_, stride_u_, stride_v_, kVideoRotation_0); |  | 
|   97   // Set time parameters to the output frame. |  | 
|   98   denoised_frame->set_timestamp(frame.timestamp()); |  | 
|   99   denoised_frame->set_render_time_ms(frame.render_time_ms()); |  | 
|  100  |   94  | 
|  101   // Init noise estimator and allocate buffers. |   95   // Init noise estimator and allocate buffers. | 
|  102   ne_->Init(width_, height_, cpu_type_); |   96   ne_->Init(width_, height_, cpu_type_); | 
|  103   moving_edge_.reset(new uint8_t[mb_cols_ * mb_rows_]); |   97   moving_edge_.reset(new uint8_t[mb_cols_ * mb_rows_]); | 
|  104   mb_filter_decision_.reset(new DenoiserDecision[mb_cols_ * mb_rows_]); |   98   mb_filter_decision_.reset(new DenoiserDecision[mb_cols_ * mb_rows_]); | 
|  105   x_density_.reset(new uint8_t[mb_cols_]); |   99   x_density_.reset(new uint8_t[mb_cols_]); | 
|  106   y_density_.reset(new uint8_t[mb_rows_]); |  100   y_density_.reset(new uint8_t[mb_rows_]); | 
|  107   moving_object_.reset(new uint8_t[mb_cols_ * mb_rows_]); |  101   moving_object_.reset(new uint8_t[mb_cols_ * mb_rows_]); | 
|  108 } |  102 } | 
|  109  |  103  | 
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  219     const uint8_t* margin_y_src = y_src + (mb_cols_ << 4); |  213     const uint8_t* margin_y_src = y_src + (mb_cols_ << 4); | 
|  220     uint8_t* margin_y_dst = y_dst + (mb_cols_ << 4); |  214     uint8_t* margin_y_dst = y_dst + (mb_cols_ << 4); | 
|  221     for (int i = 0; i < height_; ++i) { |  215     for (int i = 0; i < height_; ++i) { | 
|  222       for (int j = mb_cols_ << 4; j < width_; ++j) { |  216       for (int j = mb_cols_ << 4; j < width_; ++j) { | 
|  223         margin_y_dst[i * stride_y_ + j] = margin_y_src[i * stride_y_ + j]; |  217         margin_y_dst[i * stride_y_ + j] = margin_y_src[i * stride_y_ + j]; | 
|  224       } |  218       } | 
|  225     } |  219     } | 
|  226   } |  220   } | 
|  227 } |  221 } | 
|  228  |  222  | 
|  229 void VideoDenoiser::DenoiseFrame(const VideoFrame& frame, |  223 void VideoDenoiser::DenoiseFrame( | 
|  230                                  VideoFrame* denoised_frame, |  224     const rtc::scoped_refptr<VideoFrameBuffer>& frame, | 
|  231                                  VideoFrame* denoised_frame_prev, |  225     rtc::scoped_refptr<I420Buffer>* denoised_frame, | 
|  232                                  bool noise_estimation_enabled) { |  226     rtc::scoped_refptr<I420Buffer>* denoised_frame_prev, | 
 |  227     bool noise_estimation_enabled) { | 
|  233   // If previous width and height are different from current frame's, need to |  228   // If previous width and height are different from current frame's, need to | 
|  234   // reallocate the buffers and no denoising for the current frame. |  229   // reallocate the buffers and no denoising for the current frame. | 
|  235   if (width_ != frame.width() || height_ != frame.height()) { |  230   if (width_ != frame->width() || height_ != frame->height()) { | 
|  236     DenoiserReset(frame, denoised_frame, denoised_frame_prev); |  231     DenoiserReset(frame, denoised_frame, denoised_frame_prev); | 
|  237     return; |  232     return; | 
|  238   } |  233   } | 
|  239  |  234  | 
|  240   // Set buffer pointers. |  235   // Set buffer pointers. | 
|  241   const uint8_t* y_src = frame.video_frame_buffer()->DataY(); |  236   const uint8_t* y_src = frame->DataY(); | 
|  242   const uint8_t* u_src = frame.video_frame_buffer()->DataU(); |  237   const uint8_t* u_src = frame->DataU(); | 
|  243   const uint8_t* v_src = frame.video_frame_buffer()->DataV(); |  238   const uint8_t* v_src = frame->DataV(); | 
|  244   uint8_t* y_dst = denoised_frame->video_frame_buffer()->MutableDataY(); |  239   uint8_t* y_dst = (*denoised_frame)->MutableDataY(); | 
|  245   uint8_t* u_dst = denoised_frame->video_frame_buffer()->MutableDataU(); |  240   uint8_t* u_dst = (*denoised_frame)->MutableDataU(); | 
|  246   uint8_t* v_dst = denoised_frame->video_frame_buffer()->MutableDataV(); |  241   uint8_t* v_dst = (*denoised_frame)->MutableDataV(); | 
|  247   uint8_t* y_dst_prev = |  242   uint8_t* y_dst_prev = (*denoised_frame_prev)->MutableDataY(); | 
|  248       denoised_frame_prev->video_frame_buffer()->MutableDataY(); |  | 
|  249   memset(x_density_.get(), 0, mb_cols_); |  243   memset(x_density_.get(), 0, mb_cols_); | 
|  250   memset(y_density_.get(), 0, mb_rows_); |  244   memset(y_density_.get(), 0, mb_rows_); | 
|  251   memset(moving_object_.get(), 1, mb_cols_ * mb_rows_); |  245   memset(moving_object_.get(), 1, mb_cols_ * mb_rows_); | 
|  252  |  246  | 
|  253   uint8_t noise_level = noise_estimation_enabled ? ne_->GetNoiseLevel() : 0; |  247   uint8_t noise_level = noise_estimation_enabled ? ne_->GetNoiseLevel() : 0; | 
|  254   int thr_var_base = 16 * 16 * 2; |  248   int thr_var_base = 16 * 16 * 2; | 
|  255   // Loop over blocks to accumulate/extract noise level and update x/y_density |  249   // Loop over blocks to accumulate/extract noise level and update x/y_density | 
|  256   // factors for moving object detection. |  250   // factors for moving object detection. | 
|  257   for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) { |  251   for (int mb_row = 0; mb_row < mb_rows_; ++mb_row) { | 
|  258     const int mb_index_base = mb_row * mb_cols_; |  252     const int mb_index_base = mb_row * mb_cols_; | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  332   // When frame width/height not divisible by 16, copy the margin to |  326   // When frame width/height not divisible by 16, copy the margin to | 
|  333   // denoised_frame. |  327   // denoised_frame. | 
|  334   if ((mb_rows_ << 4) != height_ || (mb_cols_ << 4) != width_) |  328   if ((mb_rows_ << 4) != height_ || (mb_cols_ << 4) != width_) | 
|  335     CopyLumaOnMargin(y_src, y_dst); |  329     CopyLumaOnMargin(y_src, y_dst); | 
|  336  |  330  | 
|  337   // TODO(jackychen): Need SSE2/NEON opt. |  331   // TODO(jackychen): Need SSE2/NEON opt. | 
|  338   // Copy u/v planes. |  332   // Copy u/v planes. | 
|  339   memcpy(u_dst, u_src, (height_ >> 1) * stride_u_); |  333   memcpy(u_dst, u_src, (height_ >> 1) * stride_u_); | 
|  340   memcpy(v_dst, v_src, (height_ >> 1) * stride_v_); |  334   memcpy(v_dst, v_src, (height_ >> 1) * stride_v_); | 
|  341  |  335  | 
|  342   // Set time parameters to the output frame. |  | 
|  343   denoised_frame->set_timestamp(frame.timestamp()); |  | 
|  344   denoised_frame->set_render_time_ms(frame.render_time_ms()); |  | 
|  345  |  | 
|  346 #if DISPLAY || DISPLAYNEON |  336 #if DISPLAY || DISPLAYNEON | 
|  347   // Show rectangular region |  337   // Show rectangular region | 
|  348   ShowRect(filter_, moving_edge_, moving_object_, x_density_, y_density_, u_src, |  338   ShowRect(filter_, moving_edge_, moving_object_, x_density_, y_density_, u_src, | 
|  349            v_src, u_dst, v_dst, mb_rows_, mb_cols_, stride_u_, stride_v_); |  339            v_src, u_dst, v_dst, mb_rows_, mb_cols_, stride_u_, stride_v_); | 
|  350 #endif |  340 #endif | 
|  351 } |  341 } | 
|  352  |  342  | 
|  353 }  // namespace webrtc |  343 }  // namespace webrtc | 
| OLD | NEW |