| Index: webrtc/modules/video_coding/codecs/test/videoprocessor.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor.cc b/webrtc/modules/video_coding/codecs/test/videoprocessor.cc
|
| index 81e0488407b43ed678161feadbf3c4bbfe65b15b..60eade66009410bd1f8d2945170a128e7645387a 100644
|
| --- a/webrtc/modules/video_coding/codecs/test/videoprocessor.cc
|
| +++ b/webrtc/modules/video_coding/codecs/test/videoprocessor.cc
|
| @@ -59,19 +59,30 @@ void PrintCodecSettings(const VideoCodec& codec_settings) {
|
| printf(" QPmax : %d\n", codec_settings.qpMax);
|
| if (codec_settings.codecType == kVideoCodecVP8) {
|
| printf(" Complexity : %d\n", codec_settings.VP8().complexity);
|
| + printf(" Resilience : %d\n", codec_settings.VP8().resilience);
|
| + printf(" # temporal layers : %d\n",
|
| + codec_settings.VP8().numberOfTemporalLayers);
|
| printf(" Denoising : %d\n", codec_settings.VP8().denoisingOn);
|
| printf(" Error concealment : %d\n",
|
| codec_settings.VP8().errorConcealmentOn);
|
| + printf(" Automatic resize : %d\n",
|
| + codec_settings.VP8().automaticResizeOn);
|
| printf(" Frame dropping : %d\n", codec_settings.VP8().frameDroppingOn);
|
| - printf(" Resilience : %d\n", codec_settings.VP8().resilience);
|
| printf(" Key frame interval: %d\n", codec_settings.VP8().keyFrameInterval);
|
| } else if (codec_settings.codecType == kVideoCodecVP9) {
|
| printf(" Complexity : %d\n", codec_settings.VP9().complexity);
|
| + printf(" Resilience : %d\n", codec_settings.VP9().resilienceOn);
|
| + printf(" # temporal layers : %d\n",
|
| + codec_settings.VP9().numberOfTemporalLayers);
|
| printf(" Denoising : %d\n", codec_settings.VP9().denoisingOn);
|
| printf(" Frame dropping : %d\n", codec_settings.VP9().frameDroppingOn);
|
| - printf(" Resilience : %d\n", codec_settings.VP9().resilienceOn);
|
| printf(" Key frame interval: %d\n", codec_settings.VP9().keyFrameInterval);
|
| printf(" Adaptive QP mode : %d\n", codec_settings.VP9().adaptiveQpMode);
|
| + printf(" Automatic resize : %d\n",
|
| + codec_settings.VP9().automaticResizeOn);
|
| + printf(" # spatial layers : %d\n",
|
| + codec_settings.VP9().numberOfSpatialLayers);
|
| + printf(" Flexible mode : %d\n", codec_settings.VP9().flexibleMode);
|
| } else if (codec_settings.codecType == kVideoCodecH264) {
|
| printf(" Frame dropping : %d\n", codec_settings.H264().frameDroppingOn);
|
| printf(" Key frame interval: %d\n",
|
| @@ -110,25 +121,25 @@ VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder,
|
| Stats* stats,
|
| IvfFileWriter* encoded_frame_writer,
|
| FrameWriter* decoded_frame_writer)
|
| - : config_(config),
|
| + : initialized_(false),
|
| + config_(config),
|
| encoder_(encoder),
|
| decoder_(decoder),
|
| bitrate_allocator_(CreateBitrateAllocator(&config_)),
|
| - encode_callback_(new VideoProcessorEncodeCompleteCallback(this)),
|
| - decode_callback_(new VideoProcessorDecodeCompleteCallback(this)),
|
| + encode_callback_(this),
|
| + decode_callback_(this),
|
| + num_frames_decoded_(0),
|
| packet_manipulator_(packet_manipulator),
|
| analysis_frame_reader_(analysis_frame_reader),
|
| analysis_frame_writer_(analysis_frame_writer),
|
| encoded_frame_writer_(encoded_frame_writer),
|
| decoded_frame_writer_(decoded_frame_writer),
|
| - initialized_(false),
|
| last_encoded_frame_num_(-1),
|
| last_decoded_frame_num_(-1),
|
| first_key_frame_has_been_excluded_(false),
|
| - last_decoded_frame_buffer_(0, analysis_frame_reader->FrameLength()),
|
| + last_decoded_frame_buffer_(analysis_frame_reader->FrameLength()),
|
| stats_(stats),
|
| - num_dropped_frames_(0),
|
| - num_spatial_resizes_(0) {
|
| + rate_update_index_(-1) {
|
| RTC_DCHECK(encoder);
|
| RTC_DCHECK(decoder);
|
| RTC_DCHECK(packet_manipulator);
|
| @@ -141,14 +152,15 @@ VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder,
|
| VideoProcessor::~VideoProcessor() = default;
|
|
|
| void VideoProcessor::Init() {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| RTC_DCHECK(!initialized_) << "VideoProcessor already initialized.";
|
| initialized_ = true;
|
|
|
| // Setup required callbacks for the encoder and decoder.
|
| - RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(encode_callback_.get()),
|
| + RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(&encode_callback_),
|
| WEBRTC_VIDEO_CODEC_OK)
|
| << "Failed to register encode complete callback";
|
| - RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(decode_callback_.get()),
|
| + RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(&decode_callback_),
|
| WEBRTC_VIDEO_CODEC_OK)
|
| << "Failed to register decode complete callback";
|
|
|
| @@ -187,36 +199,30 @@ void VideoProcessor::Init() {
|
| }
|
|
|
| void VideoProcessor::Release() {
|
| - encoder_->RegisterEncodeCompleteCallback(nullptr);
|
| - decoder_->RegisterDecodeCompleteCallback(nullptr);
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
|
|
| RTC_CHECK_EQ(encoder_->Release(), WEBRTC_VIDEO_CODEC_OK);
|
| RTC_CHECK_EQ(decoder_->Release(), WEBRTC_VIDEO_CODEC_OK);
|
|
|
| + encoder_->RegisterEncodeCompleteCallback(nullptr);
|
| + decoder_->RegisterDecodeCompleteCallback(nullptr);
|
| +
|
| initialized_ = false;
|
| }
|
|
|
| -bool VideoProcessor::ProcessFrame(int frame_number) {
|
| - RTC_DCHECK_GE(frame_number, 0);
|
| - RTC_DCHECK_LE(frame_number, frame_infos_.size())
|
| - << "Must process frames without gaps.";
|
| +void VideoProcessor::ProcessFrame(int frame_number) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| + RTC_DCHECK_EQ(frame_number, frame_infos_.size())
|
| + << "Must process frames in sequence.";
|
| RTC_DCHECK(initialized_) << "VideoProcessor not initialized.";
|
|
|
| + // Get frame from file.
|
| rtc::scoped_refptr<I420BufferInterface> buffer(
|
| analysis_frame_reader_->ReadFrame());
|
| -
|
| - if (!buffer) {
|
| - // Last frame has been reached.
|
| - return false;
|
| - }
|
| -
|
| - uint32_t timestamp = FrameNumberToTimestamp(frame_number);
|
| - VideoFrame source_frame(buffer, timestamp, 0, webrtc::kVideoRotation_0);
|
| -
|
| - // Store frame information during the different stages of encode and decode.
|
| - frame_infos_.emplace_back();
|
| - FrameInfo* frame_info = &frame_infos_.back();
|
| - frame_info->timestamp = timestamp;
|
| + RTC_CHECK(buffer) << "Tried to read too many frames from the file.";
|
| + const int64_t kNoRenderTime = 0;
|
| + VideoFrame source_frame(buffer, FrameNumberToTimestamp(frame_number),
|
| + kNoRenderTime, webrtc::kVideoRotation_0);
|
|
|
| // Decide if we are going to force a keyframe.
|
| std::vector<FrameType> frame_types(1, kVideoFrameDelta);
|
| @@ -225,6 +231,10 @@ bool VideoProcessor::ProcessFrame(int frame_number) {
|
| frame_types[0] = kVideoFrameKey;
|
| }
|
|
|
| + // Store frame information during the different stages of encode and decode.
|
| + frame_infos_.emplace_back();
|
| + FrameInfo* frame_info = &frame_infos_.back();
|
| +
|
| // Create frame statistics object used for aggregation at end of test run.
|
| FrameStatistic* frame_stat = &stats_->NewFrame(frame_number);
|
|
|
| @@ -239,46 +249,46 @@ bool VideoProcessor::ProcessFrame(int frame_number) {
|
| << ", return code: " << frame_stat->encode_return_code
|
| << ".";
|
| }
|
| -
|
| - return true;
|
| }
|
|
|
| -void VideoProcessor::SetRates(int bit_rate, int frame_rate) {
|
| - config_.codec_settings.maxFramerate = frame_rate;
|
| +void VideoProcessor::SetRates(int bitrate_kbps, int framerate_fps) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| +
|
| + config_.codec_settings.maxFramerate = framerate_fps;
|
| int set_rates_result = encoder_->SetRateAllocation(
|
| - bitrate_allocator_->GetAllocation(bit_rate * 1000, frame_rate),
|
| - frame_rate);
|
| + bitrate_allocator_->GetAllocation(bitrate_kbps * 1000, framerate_fps),
|
| + framerate_fps);
|
| RTC_DCHECK_GE(set_rates_result, 0)
|
| - << "Failed to update encoder with new rate " << bit_rate;
|
| - num_dropped_frames_ = 0;
|
| - num_spatial_resizes_ = 0;
|
| + << "Failed to update encoder with new rate " << bitrate_kbps << ".";
|
| + ++rate_update_index_;
|
| + num_dropped_frames_.push_back(0);
|
| + num_spatial_resizes_.push_back(0);
|
| }
|
|
|
| -size_t VideoProcessor::EncodedFrameSize(int frame_number) {
|
| - RTC_DCHECK_LT(frame_number, frame_infos_.size());
|
| - return frame_infos_[frame_number].encoded_frame_size;
|
| -}
|
| -
|
| -FrameType VideoProcessor::EncodedFrameType(int frame_number) {
|
| - RTC_DCHECK_LT(frame_number, frame_infos_.size());
|
| - return frame_infos_[frame_number].encoded_frame_type;
|
| +int VideoProcessor::NumFramesDecoded() const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| + return num_frames_decoded_;
|
| }
|
|
|
| -int VideoProcessor::GetQpFromEncoder(int frame_number) {
|
| - RTC_DCHECK_LT(frame_number, frame_infos_.size());
|
| +int VideoProcessor::GetQpFromEncoder(int frame_number) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| + RTC_CHECK_LT(frame_number, frame_infos_.size());
|
| return frame_infos_[frame_number].qp_encoder;
|
| }
|
|
|
| -int VideoProcessor::GetQpFromBitstream(int frame_number) {
|
| - RTC_DCHECK_LT(frame_number, frame_infos_.size());
|
| +int VideoProcessor::GetQpFromBitstream(int frame_number) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| + RTC_CHECK_LT(frame_number, frame_infos_.size());
|
| return frame_infos_[frame_number].qp_bitstream;
|
| }
|
|
|
| -int VideoProcessor::NumberDroppedFrames() {
|
| +std::vector<int> VideoProcessor::NumberDroppedFramesPerRateUpdate() const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| return num_dropped_frames_;
|
| }
|
|
|
| -int VideoProcessor::NumberSpatialResizes() {
|
| +std::vector<int> VideoProcessor::NumberSpatialResizesPerRateUpdate() const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| return num_spatial_resizes_;
|
| }
|
|
|
| @@ -286,6 +296,8 @@ void VideoProcessor::FrameEncoded(
|
| webrtc::VideoCodecType codec,
|
| const EncodedImage& encoded_image,
|
| const webrtc::RTPFragmentationHeader* fragmentation) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| +
|
| // For the highest measurement accuracy of the encode time, the start/stop
|
| // time recordings should wrap the Encode call as tightly as possible.
|
| int64_t encode_stop_ns = rtc::TimeNanos();
|
| @@ -303,7 +315,8 @@ void VideoProcessor::FrameEncoded(
|
| int num_dropped_from_last_encode =
|
| frame_number - last_encoded_frame_num_ - 1;
|
| RTC_DCHECK_GE(num_dropped_from_last_encode, 0);
|
| - num_dropped_frames_ += num_dropped_from_last_encode;
|
| + RTC_CHECK_GE(rate_update_index_, 0);
|
| + num_dropped_frames_[rate_update_index_] += num_dropped_from_last_encode;
|
| if (num_dropped_from_last_encode > 0) {
|
| // For dropped frames, we write out the last decoded frame to avoid
|
| // getting out of sync for the computation of PSNR and SSIM.
|
| @@ -329,10 +342,8 @@ void VideoProcessor::FrameEncoded(
|
| last_encoded_frame_num_ = frame_number;
|
|
|
| // Frame is not dropped, so update frame information and statistics.
|
| - RTC_DCHECK_LT(frame_number, frame_infos_.size());
|
| + RTC_CHECK_LT(frame_number, frame_infos_.size());
|
| FrameInfo* frame_info = &frame_infos_[frame_number];
|
| - frame_info->encoded_frame_size = encoded_image._length;
|
| - frame_info->encoded_frame_type = encoded_image._frameType;
|
| frame_info->qp_encoder = encoded_image.qp_;
|
| if (codec == kVideoCodecVP8) {
|
| vp8::GetQp(encoded_image._buffer, encoded_image._length,
|
| @@ -419,6 +430,8 @@ void VideoProcessor::FrameEncoded(
|
| }
|
|
|
| void VideoProcessor::FrameDecoded(const VideoFrame& image) {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| +
|
| // For the highest measurement accuracy of the decode time, the start/stop
|
| // time recordings should wrap the Decode call as tightly as possible.
|
| int64_t decode_stop_ns = rtc::TimeNanos();
|
| @@ -443,7 +456,8 @@ void VideoProcessor::FrameDecoded(const VideoFrame& image) {
|
| last_decoded_frame_info.decoded_width ||
|
| static_cast<int>(image.height()) !=
|
| last_decoded_frame_info.decoded_height) {
|
| - ++num_spatial_resizes_;
|
| + RTC_CHECK_GE(rate_update_index_, 0);
|
| + ++num_spatial_resizes_[rate_update_index_];
|
| }
|
| }
|
| // Ensure strict monotonicity.
|
| @@ -484,16 +498,22 @@ void VideoProcessor::FrameDecoded(const VideoFrame& image) {
|
| }
|
|
|
| last_decoded_frame_buffer_ = std::move(extracted_buffer);
|
| +
|
| + ++num_frames_decoded_;
|
| }
|
|
|
| -uint32_t VideoProcessor::FrameNumberToTimestamp(int frame_number) {
|
| +uint32_t VideoProcessor::FrameNumberToTimestamp(int frame_number) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| +
|
| RTC_DCHECK_GE(frame_number, 0);
|
| const int ticks_per_frame =
|
| kRtpClockRateHz / config_.codec_settings.maxFramerate;
|
| return (frame_number + 1) * ticks_per_frame;
|
| }
|
|
|
| -int VideoProcessor::TimestampToFrameNumber(uint32_t timestamp) {
|
| +int VideoProcessor::TimestampToFrameNumber(uint32_t timestamp) const {
|
| + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
|
| +
|
| RTC_DCHECK_GT(timestamp, 0);
|
| const int ticks_per_frame =
|
| kRtpClockRateHz / config_.codec_settings.maxFramerate;
|
|
|