| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 packet_manipulator_(packet_manipulator), | 148 packet_manipulator_(packet_manipulator), |
| 149 analysis_frame_reader_(analysis_frame_reader), | 149 analysis_frame_reader_(analysis_frame_reader), |
| 150 analysis_frame_writer_(analysis_frame_writer), | 150 analysis_frame_writer_(analysis_frame_writer), |
| 151 encoded_frame_writer_(encoded_frame_writer), | 151 encoded_frame_writer_(encoded_frame_writer), |
| 152 decoded_frame_writer_(decoded_frame_writer), | 152 decoded_frame_writer_(decoded_frame_writer), |
| 153 last_encoded_frame_num_(-1), | 153 last_encoded_frame_num_(-1), |
| 154 last_decoded_frame_num_(-1), | 154 last_decoded_frame_num_(-1), |
| 155 first_key_frame_has_been_excluded_(false), | 155 first_key_frame_has_been_excluded_(false), |
| 156 last_decoded_frame_buffer_(analysis_frame_reader->FrameLength()), | 156 last_decoded_frame_buffer_(analysis_frame_reader->FrameLength()), |
| 157 stats_(stats), | 157 stats_(stats), |
| 158 num_dropped_frames_(0), | 158 rate_update_index_(-1) { |
| 159 num_spatial_resizes_(0) { | |
| 160 RTC_DCHECK(encoder); | 159 RTC_DCHECK(encoder); |
| 161 RTC_DCHECK(decoder); | 160 RTC_DCHECK(decoder); |
| 162 RTC_DCHECK(packet_manipulator); | 161 RTC_DCHECK(packet_manipulator); |
| 163 RTC_DCHECK(analysis_frame_reader); | 162 RTC_DCHECK(analysis_frame_reader); |
| 164 RTC_DCHECK(analysis_frame_writer); | 163 RTC_DCHECK(analysis_frame_writer); |
| 165 RTC_DCHECK(stats); | 164 RTC_DCHECK(stats); |
| 166 frame_infos_.reserve(analysis_frame_reader->NumberOfFrames()); | 165 frame_infos_.reserve(analysis_frame_reader->NumberOfFrames()); |
| 167 } | 166 } |
| 168 | 167 |
| 169 VideoProcessor::~VideoProcessor() = default; | 168 VideoProcessor::~VideoProcessor() = default; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 void VideoProcessor::ProcessFrame(int frame_number) { | 228 void VideoProcessor::ProcessFrame(int frame_number) { |
| 230 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 229 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 231 RTC_DCHECK_EQ(frame_number, frame_infos_.size()) | 230 RTC_DCHECK_EQ(frame_number, frame_infos_.size()) |
| 232 << "Must process frames in sequence."; | 231 << "Must process frames in sequence."; |
| 233 RTC_DCHECK(initialized_) << "VideoProcessor not initialized."; | 232 RTC_DCHECK(initialized_) << "VideoProcessor not initialized."; |
| 234 | 233 |
| 235 // Get frame from file. | 234 // Get frame from file. |
| 236 rtc::scoped_refptr<I420BufferInterface> buffer( | 235 rtc::scoped_refptr<I420BufferInterface> buffer( |
| 237 analysis_frame_reader_->ReadFrame()); | 236 analysis_frame_reader_->ReadFrame()); |
| 238 RTC_CHECK(buffer) << "Tried to read too many frames from the file."; | 237 RTC_CHECK(buffer) << "Tried to read too many frames from the file."; |
| 238 // Use the frame number as the basis for timestamp to identify frames. Let the |
| 239 // first timestamp be non-zero, to not make the IvfFileWriter believe that we |
| 240 // want to use capture timestamps in the IVF files. |
| 241 const uint32_t rtp_timestamp = (frame_number + 1) * kRtpClockRateHz / |
| 242 config_.codec_settings.maxFramerate; |
| 243 rtp_timestamp_to_frame_num_[rtp_timestamp] = frame_number; |
| 239 const int64_t kNoRenderTime = 0; | 244 const int64_t kNoRenderTime = 0; |
| 240 VideoFrame source_frame(buffer, FrameNumberToTimestamp(frame_number), | 245 VideoFrame source_frame(buffer, rtp_timestamp, kNoRenderTime, |
| 241 kNoRenderTime, webrtc::kVideoRotation_0); | 246 webrtc::kVideoRotation_0); |
| 242 | 247 |
| 243 // Decide if we are going to force a keyframe. | 248 // Decide if we are going to force a keyframe. |
| 244 std::vector<FrameType> frame_types(1, kVideoFrameDelta); | 249 std::vector<FrameType> frame_types(1, kVideoFrameDelta); |
| 245 if (config_.keyframe_interval > 0 && | 250 if (config_.keyframe_interval > 0 && |
| 246 frame_number % config_.keyframe_interval == 0) { | 251 frame_number % config_.keyframe_interval == 0) { |
| 247 frame_types[0] = kVideoFrameKey; | 252 frame_types[0] = kVideoFrameKey; |
| 248 } | 253 } |
| 249 | 254 |
| 250 // Store frame information during the different stages of encode and decode. | 255 // Store frame information during the different stages of encode and decode. |
| 251 frame_infos_.emplace_back(); | 256 frame_infos_.emplace_back(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 262 | 267 |
| 263 if (frame_stat->encode_return_code != WEBRTC_VIDEO_CODEC_OK) { | 268 if (frame_stat->encode_return_code != WEBRTC_VIDEO_CODEC_OK) { |
| 264 LOG(LS_WARNING) << "Failed to encode frame " << frame_number | 269 LOG(LS_WARNING) << "Failed to encode frame " << frame_number |
| 265 << ", return code: " << frame_stat->encode_return_code | 270 << ", return code: " << frame_stat->encode_return_code |
| 266 << "."; | 271 << "."; |
| 267 } | 272 } |
| 268 } | 273 } |
| 269 | 274 |
| 270 void VideoProcessor::SetRates(int bitrate_kbps, int framerate_fps) { | 275 void VideoProcessor::SetRates(int bitrate_kbps, int framerate_fps) { |
| 271 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 276 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 272 | |
| 273 config_.codec_settings.maxFramerate = framerate_fps; | 277 config_.codec_settings.maxFramerate = framerate_fps; |
| 274 int set_rates_result = encoder_->SetRateAllocation( | 278 int set_rates_result = encoder_->SetRateAllocation( |
| 275 bitrate_allocator_->GetAllocation(bitrate_kbps * 1000, framerate_fps), | 279 bitrate_allocator_->GetAllocation(bitrate_kbps * 1000, framerate_fps), |
| 276 framerate_fps); | 280 framerate_fps); |
| 277 RTC_DCHECK_GE(set_rates_result, 0) | 281 RTC_DCHECK_GE(set_rates_result, 0) |
| 278 << "Failed to update encoder with new rate " << bitrate_kbps << "."; | 282 << "Failed to update encoder with new rate " << bitrate_kbps << "."; |
| 279 num_dropped_frames_ = 0; | 283 ++rate_update_index_; |
| 280 num_spatial_resizes_ = 0; | 284 num_dropped_frames_.push_back(0); |
| 285 num_spatial_resizes_.push_back(0); |
| 281 } | 286 } |
| 282 | 287 |
| 283 int VideoProcessor::NumberDroppedFrames() { | 288 std::vector<int> VideoProcessor::NumberDroppedFramesPerRateUpdate() const { |
| 284 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 289 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 285 return num_dropped_frames_; | 290 return num_dropped_frames_; |
| 286 } | 291 } |
| 287 | 292 |
| 288 int VideoProcessor::NumberSpatialResizes() { | 293 std::vector<int> VideoProcessor::NumberSpatialResizesPerRateUpdate() const { |
| 289 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 294 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 290 return num_spatial_resizes_; | 295 return num_spatial_resizes_; |
| 291 } | 296 } |
| 292 | 297 |
| 293 void VideoProcessor::FrameEncoded(webrtc::VideoCodecType codec, | 298 void VideoProcessor::FrameEncoded(webrtc::VideoCodecType codec, |
| 294 const EncodedImage& encoded_image) { | 299 const EncodedImage& encoded_image) { |
| 295 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 300 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 296 | 301 |
| 297 // For the highest measurement accuracy of the encode time, the start/stop | 302 // For the highest measurement accuracy of the encode time, the start/stop |
| 298 // time recordings should wrap the Encode call as tightly as possible. | 303 // time recordings should wrap the Encode call as tightly as possible. |
| 299 int64_t encode_stop_ns = rtc::TimeNanos(); | 304 int64_t encode_stop_ns = rtc::TimeNanos(); |
| 300 | 305 |
| 301 if (encoded_frame_writer_) { | 306 if (encoded_frame_writer_) { |
| 302 RTC_CHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec)); | 307 RTC_CHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec)); |
| 303 } | 308 } |
| 304 | 309 |
| 305 // Timestamp is proportional to frame number, so this gives us number of | 310 // Check for dropped frames. |
| 306 // dropped frames. | 311 const int frame_number = |
| 307 int frame_number = TimestampToFrameNumber(encoded_image._timeStamp); | 312 rtp_timestamp_to_frame_num_[encoded_image._timeStamp]; |
| 308 bool last_frame_missing = false; | 313 bool last_frame_missing = false; |
| 309 if (frame_number > 0) { | 314 if (frame_number > 0) { |
| 310 RTC_DCHECK_GE(last_encoded_frame_num_, 0); | 315 RTC_DCHECK_GE(last_encoded_frame_num_, 0); |
| 311 int num_dropped_from_last_encode = | 316 int num_dropped_from_last_encode = |
| 312 frame_number - last_encoded_frame_num_ - 1; | 317 frame_number - last_encoded_frame_num_ - 1; |
| 313 RTC_DCHECK_GE(num_dropped_from_last_encode, 0); | 318 RTC_DCHECK_GE(num_dropped_from_last_encode, 0); |
| 314 num_dropped_frames_ += num_dropped_from_last_encode; | 319 RTC_CHECK_GE(rate_update_index_, 0); |
| 320 num_dropped_frames_[rate_update_index_] += num_dropped_from_last_encode; |
| 315 if (num_dropped_from_last_encode > 0) { | 321 if (num_dropped_from_last_encode > 0) { |
| 316 // For dropped frames, we write out the last decoded frame to avoid | 322 // For dropped frames, we write out the last decoded frame to avoid |
| 317 // getting out of sync for the computation of PSNR and SSIM. | 323 // getting out of sync for the computation of PSNR and SSIM. |
| 318 for (int i = 0; i < num_dropped_from_last_encode; i++) { | 324 for (int i = 0; i < num_dropped_from_last_encode; i++) { |
| 319 RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), | 325 RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), |
| 320 analysis_frame_writer_->FrameLength()); | 326 analysis_frame_writer_->FrameLength()); |
| 321 RTC_CHECK(analysis_frame_writer_->WriteFrame( | 327 RTC_CHECK(analysis_frame_writer_->WriteFrame( |
| 322 last_decoded_frame_buffer_.data())); | 328 last_decoded_frame_buffer_.data())); |
| 323 if (decoded_frame_writer_) { | 329 if (decoded_frame_writer_) { |
| 324 RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), | 330 RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), |
| 325 decoded_frame_writer_->FrameLength()); | 331 decoded_frame_writer_->FrameLength()); |
| 326 RTC_CHECK(decoded_frame_writer_->WriteFrame( | 332 RTC_CHECK(decoded_frame_writer_->WriteFrame( |
| 327 last_decoded_frame_buffer_.data())); | 333 last_decoded_frame_buffer_.data())); |
| 328 } | 334 } |
| 329 } | 335 } |
| 330 } | 336 } |
| 331 | |
| 332 last_frame_missing = | 337 last_frame_missing = |
| 333 (frame_infos_[last_encoded_frame_num_].manipulated_length == 0); | 338 (frame_infos_[last_encoded_frame_num_].manipulated_length == 0); |
| 334 } | 339 } |
| 335 // Ensure strict monotonicity. | 340 // Ensure strict monotonicity. |
| 336 RTC_CHECK_GT(frame_number, last_encoded_frame_num_); | 341 RTC_CHECK_GT(frame_number, last_encoded_frame_num_); |
| 337 last_encoded_frame_num_ = frame_number; | 342 last_encoded_frame_num_ = frame_number; |
| 338 | 343 |
| 339 // Frame is not dropped, so update frame information and statistics. | 344 // Update frame information and statistics. |
| 340 VerifyQpParser(encoded_image, config_); | 345 VerifyQpParser(encoded_image, config_); |
| 341 RTC_CHECK_LT(frame_number, frame_infos_.size()); | 346 RTC_CHECK_LT(frame_number, frame_infos_.size()); |
| 342 FrameInfo* frame_info = &frame_infos_[frame_number]; | 347 FrameInfo* frame_info = &frame_infos_[frame_number]; |
| 343 FrameStatistic* frame_stat = &stats_->stats_[frame_number]; | 348 FrameStatistic* frame_stat = &stats_->stats_[frame_number]; |
| 344 frame_stat->encode_time_in_us = | 349 frame_stat->encode_time_in_us = |
| 345 GetElapsedTimeMicroseconds(frame_info->encode_start_ns, encode_stop_ns); | 350 GetElapsedTimeMicroseconds(frame_info->encode_start_ns, encode_stop_ns); |
| 346 frame_stat->encoding_successful = true; | 351 frame_stat->encoding_successful = true; |
| 347 frame_stat->encoded_frame_length_in_bytes = encoded_image._length; | 352 frame_stat->encoded_frame_length_in_bytes = encoded_image._length; |
| 348 frame_stat->frame_number = frame_number; | 353 frame_stat->frame_number = frame_number; |
| 349 frame_stat->frame_type = encoded_image._frameType; | 354 frame_stat->frame_type = encoded_image._frameType; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 } | 418 } |
| 414 | 419 |
| 415 void VideoProcessor::FrameDecoded(const VideoFrame& image) { | 420 void VideoProcessor::FrameDecoded(const VideoFrame& image) { |
| 416 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | 421 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); |
| 417 | 422 |
| 418 // For the highest measurement accuracy of the decode time, the start/stop | 423 // For the highest measurement accuracy of the decode time, the start/stop |
| 419 // time recordings should wrap the Decode call as tightly as possible. | 424 // time recordings should wrap the Decode call as tightly as possible. |
| 420 int64_t decode_stop_ns = rtc::TimeNanos(); | 425 int64_t decode_stop_ns = rtc::TimeNanos(); |
| 421 | 426 |
| 422 // Update frame information and statistics. | 427 // Update frame information and statistics. |
| 423 int frame_number = TimestampToFrameNumber(image.timestamp()); | 428 const int frame_number = rtp_timestamp_to_frame_num_[image.timestamp()]; |
| 424 RTC_DCHECK_LT(frame_number, frame_infos_.size()); | 429 RTC_CHECK_LT(frame_number, frame_infos_.size()); |
| 425 FrameInfo* frame_info = &frame_infos_[frame_number]; | 430 FrameInfo* frame_info = &frame_infos_[frame_number]; |
| 426 frame_info->decoded_width = image.width(); | 431 frame_info->decoded_width = image.width(); |
| 427 frame_info->decoded_height = image.height(); | 432 frame_info->decoded_height = image.height(); |
| 428 FrameStatistic* frame_stat = &stats_->stats_[frame_number]; | 433 FrameStatistic* frame_stat = &stats_->stats_[frame_number]; |
| 429 frame_stat->decode_time_in_us = | 434 frame_stat->decode_time_in_us = |
| 430 GetElapsedTimeMicroseconds(frame_info->decode_start_ns, decode_stop_ns); | 435 GetElapsedTimeMicroseconds(frame_info->decode_start_ns, decode_stop_ns); |
| 431 frame_stat->decoding_successful = true; | 436 frame_stat->decoding_successful = true; |
| 432 | 437 |
| 433 // Check if the codecs have resized the frame since previously decoded frame. | 438 // Check if the codecs have resized the frame since previously decoded frame. |
| 434 if (frame_number > 0) { | 439 if (frame_number > 0) { |
| 435 RTC_DCHECK_GE(last_decoded_frame_num_, 0); | 440 RTC_CHECK_GE(last_decoded_frame_num_, 0); |
| 436 const FrameInfo& last_decoded_frame_info = | 441 const FrameInfo& last_decoded_frame_info = |
| 437 frame_infos_[last_decoded_frame_num_]; | 442 frame_infos_[last_decoded_frame_num_]; |
| 438 if (static_cast<int>(image.width()) != | 443 if (static_cast<int>(image.width()) != |
| 439 last_decoded_frame_info.decoded_width || | 444 last_decoded_frame_info.decoded_width || |
| 440 static_cast<int>(image.height()) != | 445 static_cast<int>(image.height()) != |
| 441 last_decoded_frame_info.decoded_height) { | 446 last_decoded_frame_info.decoded_height) { |
| 442 ++num_spatial_resizes_; | 447 RTC_CHECK_GE(rate_update_index_, 0); |
| 448 ++num_spatial_resizes_[rate_update_index_]; |
| 443 } | 449 } |
| 444 } | 450 } |
| 445 // Ensure strict monotonicity. | 451 // Ensure strict monotonicity. |
| 446 RTC_CHECK_GT(frame_number, last_decoded_frame_num_); | 452 RTC_CHECK_GT(frame_number, last_decoded_frame_num_); |
| 447 last_decoded_frame_num_ = frame_number; | 453 last_decoded_frame_num_ = frame_number; |
| 448 | 454 |
| 449 // Check if codec size is different from the original size, and if so, | 455 // Check if codec size is different from the original size, and if so, |
| 450 // scale back to original size. This is needed for the PSNR and SSIM | 456 // scale back to original size. This is needed for the PSNR and SSIM |
| 451 // calculations. | 457 // calculations. |
| 452 size_t extracted_length; | 458 size_t extracted_length; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 475 RTC_DCHECK_EQ(extracted_length, analysis_frame_writer_->FrameLength()); | 481 RTC_DCHECK_EQ(extracted_length, analysis_frame_writer_->FrameLength()); |
| 476 RTC_CHECK(analysis_frame_writer_->WriteFrame(extracted_buffer.data())); | 482 RTC_CHECK(analysis_frame_writer_->WriteFrame(extracted_buffer.data())); |
| 477 if (decoded_frame_writer_) { | 483 if (decoded_frame_writer_) { |
| 478 RTC_DCHECK_EQ(extracted_length, decoded_frame_writer_->FrameLength()); | 484 RTC_DCHECK_EQ(extracted_length, decoded_frame_writer_->FrameLength()); |
| 479 RTC_CHECK(decoded_frame_writer_->WriteFrame(extracted_buffer.data())); | 485 RTC_CHECK(decoded_frame_writer_->WriteFrame(extracted_buffer.data())); |
| 480 } | 486 } |
| 481 | 487 |
| 482 last_decoded_frame_buffer_ = std::move(extracted_buffer); | 488 last_decoded_frame_buffer_ = std::move(extracted_buffer); |
| 483 } | 489 } |
| 484 | 490 |
| 485 uint32_t VideoProcessor::FrameNumberToTimestamp(int frame_number) const { | |
| 486 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | |
| 487 | |
| 488 RTC_DCHECK_GE(frame_number, 0); | |
| 489 const int ticks_per_frame = | |
| 490 kRtpClockRateHz / config_.codec_settings.maxFramerate; | |
| 491 return (frame_number + 1) * ticks_per_frame; | |
| 492 } | |
| 493 | |
| 494 int VideoProcessor::TimestampToFrameNumber(uint32_t timestamp) const { | |
| 495 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); | |
| 496 | |
| 497 RTC_DCHECK_GT(timestamp, 0); | |
| 498 const int ticks_per_frame = | |
| 499 kRtpClockRateHz / config_.codec_settings.maxFramerate; | |
| 500 RTC_DCHECK_EQ(timestamp % ticks_per_frame, 0); | |
| 501 return (timestamp / ticks_per_frame) - 1; | |
| 502 } | |
| 503 | |
| 504 } // namespace test | 491 } // namespace test |
| 505 } // namespace webrtc | 492 } // namespace webrtc |
| OLD | NEW |