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 |