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