| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 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 23 matching lines...) Expand all Loading... |
| 34 enum { kDownsamplingFactor = 8 }; | 34 enum { kDownsamplingFactor = 8 }; |
| 35 enum { kLog2OfDownsamplingFactor = 3 }; | 35 enum { kLog2OfDownsamplingFactor = 3 }; |
| 36 | 36 |
| 37 // To generate in Matlab: | 37 // To generate in Matlab: |
| 38 // >> probUW16 = round(2^11 * | 38 // >> probUW16 = round(2^11 * |
| 39 // [0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,0.95,0.97]); | 39 // [0.05,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,0.95,0.97]); |
| 40 // >> fprintf('%d, ', probUW16) | 40 // >> fprintf('%d, ', probUW16) |
| 41 // Resolution reduced to avoid overflow when multiplying with the | 41 // Resolution reduced to avoid overflow when multiplying with the |
| 42 // (potentially) large number of pixels. | 42 // (potentially) large number of pixels. |
| 43 const uint16_t VPMDeflickering::prob_uw16_[kNumProbs] = {102, 205, 410, 614, | 43 const uint16_t VPMDeflickering::prob_uw16_[kNumProbs] = {102, 205, 410, 614, |
| 44 819, 1024, 1229, 1434, 1638, 1843, 1946, 1987}; // <Q11> | 44 819, 1024, 1229, 1434, 1638, 1843, 1946, 1987}; // <Q11> |
| 45 | 45 |
| 46 // To generate in Matlab: | 46 // To generate in Matlab: |
| 47 // >> numQuants = 14; maxOnlyLength = 5; | 47 // >> numQuants = 14; maxOnlyLength = 5; |
| 48 // >> weightUW16 = round(2^15 * | 48 // >> weightUW16 = round(2^15 * |
| 49 // [linspace(0.5, 1.0, numQuants - maxOnlyLength)]); | 49 // [linspace(0.5, 1.0, numQuants - maxOnlyLength)]); |
| 50 // >> fprintf('%d, %d,\n ', weightUW16); | 50 // >> fprintf('%d, %d,\n ', weightUW16); |
| 51 const uint16_t VPMDeflickering::weight_uw16_[kNumQuants - kMaxOnlyLength] = | 51 const uint16_t VPMDeflickering::weight_uw16_[kNumQuants - kMaxOnlyLength] = |
| 52 {16384, 18432, 20480, 22528, 24576, 26624, 28672, 30720, 32768}; // <Q15> | 52 {16384, 18432, 20480, 22528, 24576, 26624, 28672, 30720, 32768}; // <Q15> |
| 53 | 53 |
| 54 VPMDeflickering::VPMDeflickering() { | 54 VPMDeflickering::VPMDeflickering() { |
| 55 Reset(); | 55 Reset(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 VPMDeflickering::~VPMDeflickering() {} | 58 VPMDeflickering::~VPMDeflickering() {} |
| 59 | 59 |
| 60 void VPMDeflickering::Reset() { | 60 void VPMDeflickering::Reset() { |
| 61 mean_buffer_length_ = 0; | 61 mean_buffer_length_ = 0; |
| 62 detection_state_ = 0; | 62 detection_state_ = 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 75 } | 75 } |
| 76 | 76 |
| 77 for (int32_t i = 1; i < kFrameHistory_size; i++) { | 77 for (int32_t i = 1; i < kFrameHistory_size; i++) { |
| 78 memcpy(quant_hist_uw8_[i], quant_hist_uw8_[0], | 78 memcpy(quant_hist_uw8_[i], quant_hist_uw8_[0], |
| 79 sizeof(uint8_t) * kNumQuants); | 79 sizeof(uint8_t) * kNumQuants); |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 int32_t VPMDeflickering::ProcessFrame( | 83 int32_t VPMDeflickering::ProcessFrame( |
| 84 VideoFrame* frame, | 84 VideoFrame* frame, |
| 85 VideoProcessingModule::FrameStats* stats) { | 85 VideoProcessing::FrameStats* stats) { |
| 86 assert(frame); | 86 assert(frame); |
| 87 uint32_t frame_memory; | 87 uint32_t frame_memory; |
| 88 uint8_t quant_uw8[kNumQuants]; | 88 uint8_t quant_uw8[kNumQuants]; |
| 89 uint8_t maxquant_uw8[kNumQuants]; | 89 uint8_t maxquant_uw8[kNumQuants]; |
| 90 uint8_t minquant_uw8[kNumQuants]; | 90 uint8_t minquant_uw8[kNumQuants]; |
| 91 uint16_t target_quant_uw16[kNumQuants]; | 91 uint16_t target_quant_uw16[kNumQuants]; |
| 92 uint16_t increment_uw16; | 92 uint16_t increment_uw16; |
| 93 uint8_t map_uw8[256]; | 93 uint8_t map_uw8[256]; |
| 94 | 94 |
| 95 uint16_t tmp_uw16; | 95 uint16_t tmp_uw16; |
| 96 uint32_t tmp_uw32; | 96 uint32_t tmp_uw32; |
| 97 int width = frame->width(); | 97 int width = frame->width(); |
| 98 int height = frame->height(); | 98 int height = frame->height(); |
| 99 | 99 |
| 100 if (frame->IsZeroSize()) { | 100 if (frame->IsZeroSize()) { |
| 101 return VPM_GENERAL_ERROR; | 101 return VPM_GENERAL_ERROR; |
| 102 } | 102 } |
| 103 | 103 |
| 104 // Stricter height check due to subsampling size calculation below. | 104 // Stricter height check due to subsampling size calculation below. |
| 105 if (height < 2) { | 105 if (height < 2) { |
| 106 LOG(LS_ERROR) << "Invalid frame size."; | 106 LOG(LS_ERROR) << "Invalid frame size."; |
| 107 return VPM_GENERAL_ERROR; | 107 return VPM_GENERAL_ERROR; |
| 108 } | 108 } |
| 109 | 109 |
| 110 if (!VideoProcessingModule::ValidFrameStats(*stats)) { | 110 if (!VideoProcessing::ValidFrameStats(*stats)) { |
| 111 return VPM_GENERAL_ERROR; | 111 return VPM_GENERAL_ERROR; |
| 112 } | 112 } |
| 113 | 113 |
| 114 if (PreDetection(frame->timestamp(), *stats) == -1) return VPM_GENERAL_ERROR; | 114 if (PreDetection(frame->timestamp(), *stats) == -1) return VPM_GENERAL_ERROR; |
| 115 | 115 |
| 116 // Flicker detection | 116 // Flicker detection |
| 117 int32_t det_flicker = DetectFlicker(); | 117 int32_t det_flicker = DetectFlicker(); |
| 118 if (det_flicker < 0) { | 118 if (det_flicker < 0) { |
| 119 return VPM_GENERAL_ERROR; | 119 return VPM_GENERAL_ERROR; |
| 120 } else if (det_flicker != 1) { | 120 } else if (det_flicker != 1) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 // Compute the map from input to output pixels. | 202 // Compute the map from input to output pixels. |
| 203 uint16_t mapUW16; // <Q7> | 203 uint16_t mapUW16; // <Q7> |
| 204 for (int32_t i = 1; i < kNumQuants; i++) { | 204 for (int32_t i = 1; i < kNumQuants; i++) { |
| 205 // As quant and targetQuant are limited to UWord8, it's safe to use Q7 here. | 205 // As quant and targetQuant are limited to UWord8, it's safe to use Q7 here. |
| 206 tmp_uw32 = static_cast<uint32_t>(target_quant_uw16[i] - | 206 tmp_uw32 = static_cast<uint32_t>(target_quant_uw16[i] - |
| 207 target_quant_uw16[i - 1]); | 207 target_quant_uw16[i - 1]); |
| 208 tmp_uw16 = static_cast<uint16_t>(quant_uw8[i] - quant_uw8[i - 1]); // <Q0> | 208 tmp_uw16 = static_cast<uint16_t>(quant_uw8[i] - quant_uw8[i - 1]); // <Q0> |
| 209 | 209 |
| 210 if (tmp_uw16 > 0) { | 210 if (tmp_uw16 > 0) { |
| 211 increment_uw16 = static_cast<uint16_t>(WebRtcSpl_DivU32U16(tmp_uw32, | 211 increment_uw16 = static_cast<uint16_t>(WebRtcSpl_DivU32U16(tmp_uw32, |
| 212 tmp_uw16)); // <Q7> | 212 tmp_uw16)); // <Q7> |
| 213 } else { | 213 } else { |
| 214 // The value is irrelevant; the loop below will only iterate once. | 214 // The value is irrelevant; the loop below will only iterate once. |
| 215 increment_uw16 = 0; | 215 increment_uw16 = 0; |
| 216 } | 216 } |
| 217 | 217 |
| 218 mapUW16 = target_quant_uw16[i - 1]; | 218 mapUW16 = target_quant_uw16[i - 1]; |
| 219 for (uint32_t j = quant_uw8[i - 1]; j < (uint32_t)(quant_uw8[i] + 1); j++) { | 219 for (uint32_t j = quant_uw8[i - 1]; j < (uint32_t)(quant_uw8[i] + 1); j++) { |
| 220 // Unsigned round. <Q0> | 220 // Unsigned round. <Q0> |
| 221 map_uw8[j] = (uint8_t)((mapUW16 + (1 << 6)) >> 7); | 221 map_uw8[j] = (uint8_t)((mapUW16 + (1 << 6)) >> 7); |
| 222 mapUW16 += increment_uw16; | 222 mapUW16 += increment_uw16; |
| 223 } | 223 } |
| 224 } | 224 } |
| 225 | 225 |
| 226 // Map to the output frame. | 226 // Map to the output frame. |
| 227 uint8_t* buffer = frame->buffer(kYPlane); | 227 uint8_t* buffer = frame->buffer(kYPlane); |
| 228 for (uint32_t i = 0; i < y_size; i++) { | 228 for (uint32_t i = 0; i < y_size; i++) { |
| 229 buffer[i] = map_uw8[buffer[i]]; | 229 buffer[i] = map_uw8[buffer[i]]; |
| 230 } | 230 } |
| 231 | 231 |
| 232 // Frame was altered, so reset stats. | 232 // Frame was altered, so reset stats. |
| 233 VideoProcessingModule::ClearFrameStats(stats); | 233 VideoProcessing::ClearFrameStats(stats); |
| 234 | 234 |
| 235 return VPM_OK; | 235 return VPM_OK; |
| 236 } | 236 } |
| 237 | 237 |
| 238 /** | 238 /** |
| 239 Performs some pre-detection operations. Must be called before | 239 Performs some pre-detection operations. Must be called before |
| 240 DetectFlicker(). | 240 DetectFlicker(). |
| 241 | 241 |
| 242 \param[in] timestamp Timestamp of the current frame. | 242 \param[in] timestamp Timestamp of the current frame. |
| 243 \param[in] stats Statistics of the current frame. | 243 \param[in] stats Statistics of the current frame. |
| 244 | 244 |
| 245 \return 0: Success\n | 245 \return 0: Success\n |
| 246 2: Detection not possible due to flickering frequency too close to | 246 2: Detection not possible due to flickering frequency too close to |
| 247 zero.\n | 247 zero.\n |
| 248 -1: Error | 248 -1: Error |
| 249 */ | 249 */ |
| 250 int32_t VPMDeflickering::PreDetection(const uint32_t timestamp, | 250 int32_t VPMDeflickering::PreDetection(const uint32_t timestamp, |
| 251 const VideoProcessingModule::FrameStats& stats) { | 251 const VideoProcessing::FrameStats& stats) { |
| 252 int32_t mean_val; // Mean value of frame (Q4) | 252 int32_t mean_val; // Mean value of frame (Q4) |
| 253 uint32_t frame_rate = 0; | 253 uint32_t frame_rate = 0; |
| 254 int32_t meanBufferLength; // Temp variable. | 254 int32_t meanBufferLength; // Temp variable. |
| 255 | 255 |
| 256 mean_val = ((stats.sum << kmean_valueScaling) / stats.num_pixels); | 256 mean_val = ((stats.sum << kmean_valueScaling) / stats.num_pixels); |
| 257 // Update mean value buffer. | 257 // Update mean value buffer. |
| 258 // This should be done even though we might end up in an unreliable detection. | 258 // This should be done even though we might end up in an unreliable detection. |
| 259 memmove(mean_buffer_ + 1, mean_buffer_, | 259 memmove(mean_buffer_ + 1, mean_buffer_, |
| 260 (kMeanBufferLength - 1) * sizeof(int32_t)); | 260 (kMeanBufferLength - 1) * sizeof(int32_t)); |
| 261 mean_buffer_[0] = mean_val; | 261 mean_buffer_[0] = mean_val; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 (timestamp_buffer_[0] - timestamp_buffer_[mean_buffer_length_ - 1]); | 364 (timestamp_buffer_[0] - timestamp_buffer_[mean_buffer_length_ - 1]); |
| 365 | 365 |
| 366 /* Translate frequency estimate to regions close to 100 and 120 Hz */ | 366 /* Translate frequency estimate to regions close to 100 and 120 Hz */ |
| 367 uint8_t freqState = 0; // Current translation state; | 367 uint8_t freqState = 0; // Current translation state; |
| 368 // (0) Not in interval, | 368 // (0) Not in interval, |
| 369 // (1) Within valid interval, | 369 // (1) Within valid interval, |
| 370 // (2) Out of range | 370 // (2) Out of range |
| 371 int32_t freqAlias = freqEst; | 371 int32_t freqAlias = freqEst; |
| 372 if (freqEst > kMinFrequencyToDetect) { | 372 if (freqEst > kMinFrequencyToDetect) { |
| 373 uint8_t aliasState = 1; | 373 uint8_t aliasState = 1; |
| 374 while(freqState == 0) { | 374 while (freqState == 0) { |
| 375 /* Increase frequency */ | 375 /* Increase frequency */ |
| 376 freqAlias += (aliasState * frame_rate_); | 376 freqAlias += (aliasState * frame_rate_); |
| 377 freqAlias += ((freqEst << 1) * (1 - (aliasState << 1))); | 377 freqAlias += ((freqEst << 1) * (1 - (aliasState << 1))); |
| 378 /* Compute state */ | 378 /* Compute state */ |
| 379 freqState = (abs(freqAlias - (100 << 4)) <= kFrequencyDeviation); | 379 freqState = (abs(freqAlias - (100 << 4)) <= kFrequencyDeviation); |
| 380 freqState += (abs(freqAlias - (120 << 4)) <= kFrequencyDeviation); | 380 freqState += (abs(freqAlias - (120 << 4)) <= kFrequencyDeviation); |
| 381 freqState += 2 * (freqAlias > ((120 << 4) + kFrequencyDeviation)); | 381 freqState += 2 * (freqAlias > ((120 << 4) + kFrequencyDeviation)); |
| 382 /* Switch alias state */ | 382 /* Switch alias state */ |
| 383 aliasState++; | 383 aliasState++; |
| 384 aliasState &= 0x01; | 384 aliasState &= 0x01; |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 /* Is frequency estimate within detection region? */ | 387 /* Is frequency estimate within detection region? */ |
| 388 if (freqState == 1) { | 388 if (freqState == 1) { |
| 389 ret_val = 1; | 389 ret_val = 1; |
| 390 } else if (freqState == 0) { | 390 } else if (freqState == 0) { |
| 391 ret_val = 2; | 391 ret_val = 2; |
| 392 } else { | 392 } else { |
| 393 ret_val = 0; | 393 ret_val = 0; |
| 394 } | 394 } |
| 395 return ret_val; | 395 return ret_val; |
| 396 } | 396 } |
| 397 | 397 |
| 398 } // namespace webrtc | 398 } // namespace webrtc |
| OLD | NEW |