diff --git a/modules/video_coding/codecs/test/test_config.cc b/modules/video_coding/codecs/test/test_config.cc index 042c2b6f3c..3905b03f0b 100644 --- a/modules/video_coding/codecs/test/test_config.cc +++ b/modules/video_coding/codecs/test/test_config.cc @@ -10,7 +10,7 @@ #include "modules/video_coding/codecs/test/test_config.h" -#include +#include #include "modules/video_coding/include/video_codec_interface.h" #include "rtc_base/checks.h" @@ -22,6 +22,46 @@ namespace test { namespace { const int kBaseKeyFrameInterval = 3000; + +std::string CodecSpecificToString(const webrtc::VideoCodec& codec) { + std::stringstream ss; + switch (codec.codecType) { + case kVideoCodecVP8: + ss << "\n Complexity : " << codec.VP8().complexity; + ss << "\n Resilience : " << codec.VP8().resilience; + ss << "\n # temporal layers : " + << static_cast(codec.VP8().numberOfTemporalLayers); + ss << "\n Denoising : " << codec.VP8().denoisingOn; + ss << "\n Error concealment : " << codec.VP8().errorConcealmentOn; + ss << "\n Automatic resize : " << codec.VP8().automaticResizeOn; + ss << "\n Frame dropping : " << codec.VP8().frameDroppingOn; + ss << "\n Key frame interval: " << codec.VP8().keyFrameInterval; + break; + case kVideoCodecVP9: + ss << "\n Complexity : " << codec.VP9().complexity; + ss << "\n Resilience : " << codec.VP9().resilienceOn; + ss << "\n # temporal layers : " + << static_cast(codec.VP9().numberOfTemporalLayers); + ss << "\n Denoising : " << codec.VP9().denoisingOn; + ss << "\n Frame dropping : " << codec.VP9().frameDroppingOn; + ss << "\n Key frame interval: " << codec.VP9().keyFrameInterval; + ss << "\n Adaptive QP mode : " << codec.VP9().adaptiveQpMode; + ss << "\n Automatic resize : " << codec.VP9().automaticResizeOn; + ss << "\n # spatial layers : " + << static_cast(codec.VP9().numberOfSpatialLayers); + ss << "\n Flexible mode : " << codec.VP9().flexibleMode; + break; + case kVideoCodecH264: + ss << "\n Frame dropping : " << codec.H264().frameDroppingOn; + ss << "\n Key frame interval: " << codec.H264().keyFrameInterval; + ss << "\n Profile : " << codec.H264().profile; + break; + default: + break; + } + ss << "\n"; + return ss.str(); +} } // namespace void TestConfig::SetCodecSettings(VideoCodecType codec_type, @@ -83,57 +123,53 @@ int TestConfig::NumberOfTemporalLayers() const { } } -void TestConfig::Print() const { - printf("Video config:\n"); - printf(" Filename : %s\n", filename.c_str()); - printf(" # CPU cores used : %u\n", NumberOfCores()); - PrintCodecSettings(); - printf("\n"); +int TestConfig::TemporalLayerForFrame(int frame_idx) const { + int tl = -1; + switch (NumberOfTemporalLayers()) { + case 1: + tl = 0; + break; + case 2: + // temporal layer 1: 1 3 + // temporal layer 0: 0 2 4 ... + tl = (frame_idx % 2 == 0) ? 0 : 1; + break; + case 3: + // temporal layer 2: 1 3 5 7 + // temporal layer 1: 2 6 + // temporal layer 0: 0 4 8 ... + if (frame_idx % 4 == 0) { + tl = 0; + } else if ((frame_idx + 2) % 4 == 0) { + tl = 1; + } else if ((frame_idx + 1) % 2 == 0) { + tl = 2; + } + break; + default: + RTC_NOTREACHED(); + break; + } + return tl; } -void TestConfig::PrintCodecSettings() const { - printf(" Codec settings:\n"); - printf(" Codec type : %s\n", - CodecTypeToPayloadString(codec_settings.codecType)); - printf(" Start bitrate : %d kbps\n", codec_settings.startBitrate); - printf(" Max bitrate : %d kbps\n", codec_settings.maxBitrate); - printf(" Min bitrate : %d kbps\n", codec_settings.minBitrate); - printf(" Width : %d\n", codec_settings.width); - printf(" Height : %d\n", codec_settings.height); - printf(" Max frame rate : %d\n", codec_settings.maxFramerate); - 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(" 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(" 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", - codec_settings.H264().keyFrameInterval); - printf(" Profile : %d\n", codec_settings.H264().profile); - } +std::string TestConfig::ToString() const { + std::stringstream ss; + ss << "Video config:"; + ss << "\n Filename : " << filename; + ss << "\n # CPU cores used : " << NumberOfCores(); + ss << "\n Codec settings:"; + ss << "\n Codec type : " + << CodecTypeToPayloadString(codec_settings.codecType); + ss << "\n Start bitrate : " << codec_settings.startBitrate << " kbps"; + ss << "\n Max bitrate : " << codec_settings.maxBitrate << " kbps"; + ss << "\n Min bitrate : " << codec_settings.minBitrate << " kbps"; + ss << "\n Width : " << codec_settings.width; + ss << "\n Height : " << codec_settings.height; + ss << "\n Max frame rate : " << codec_settings.maxFramerate; + ss << "\n QPmax : " << codec_settings.qpMax; + ss << CodecSpecificToString(codec_settings); + return ss.str(); } } // namespace test diff --git a/modules/video_coding/codecs/test/test_config.h b/modules/video_coding/codecs/test/test_config.h index 11db47bf08..a6fcd5c308 100644 --- a/modules/video_coding/codecs/test/test_config.h +++ b/modules/video_coding/codecs/test/test_config.h @@ -52,8 +52,8 @@ struct TestConfig { int NumberOfCores() const; int NumberOfTemporalLayers() const; - void Print() const; - void PrintCodecSettings() const; + int TemporalLayerForFrame(int frame_idx) const; + std::string ToString() const; // Plain name of YUV file to process without file extension. std::string filename; diff --git a/modules/video_coding/codecs/test/test_config_unittest.cc b/modules/video_coding/codecs/test/test_config_unittest.cc index 0ec784c0e7..30b7f22258 100644 --- a/modules/video_coding/codecs/test/test_config_unittest.cc +++ b/modules/video_coding/codecs/test/test_config_unittest.cc @@ -51,5 +51,81 @@ TEST(TestConfig, NumberOfTemporalLayers_Vp9) { EXPECT_EQ(kNumTemporalLayers, config.NumberOfTemporalLayers()); } +TEST(TestConfig, TemporalLayersForFrame_OneLayer) { + TestConfig config; + webrtc::test::CodecSettings(kVideoCodecVP8, &config.codec_settings); + config.codec_settings.VP8()->numberOfTemporalLayers = 1; + EXPECT_EQ(0, config.TemporalLayerForFrame(0)); + EXPECT_EQ(0, config.TemporalLayerForFrame(1)); + EXPECT_EQ(0, config.TemporalLayerForFrame(2)); +} + +TEST(TestConfig, TemporalLayersForFrame_TwoLayers) { + TestConfig config; + webrtc::test::CodecSettings(kVideoCodecVP8, &config.codec_settings); + config.codec_settings.VP8()->numberOfTemporalLayers = 2; + EXPECT_EQ(0, config.TemporalLayerForFrame(0)); + EXPECT_EQ(1, config.TemporalLayerForFrame(1)); + EXPECT_EQ(0, config.TemporalLayerForFrame(2)); + EXPECT_EQ(1, config.TemporalLayerForFrame(3)); +} + +TEST(TestConfig, TemporalLayersForFrame_ThreeLayers) { + TestConfig config; + webrtc::test::CodecSettings(kVideoCodecVP8, &config.codec_settings); + config.codec_settings.VP8()->numberOfTemporalLayers = 3; + EXPECT_EQ(0, config.TemporalLayerForFrame(0)); + EXPECT_EQ(2, config.TemporalLayerForFrame(1)); + EXPECT_EQ(1, config.TemporalLayerForFrame(2)); + EXPECT_EQ(2, config.TemporalLayerForFrame(3)); + EXPECT_EQ(0, config.TemporalLayerForFrame(4)); + EXPECT_EQ(2, config.TemporalLayerForFrame(5)); + EXPECT_EQ(1, config.TemporalLayerForFrame(6)); + EXPECT_EQ(2, config.TemporalLayerForFrame(7)); +} + +TEST(TestConfig, ToString_Vp8) { + TestConfig config; + config.filename = "yuvfile"; + config.use_single_core = true; + + config.SetCodecSettings(kVideoCodecVP8, 2, true, // error_concealment_on, + false, // denoising_on, + false, // frame_dropper_on, + true, // spatial_resize_on, + false, // resilience_on, + 320, 180); + config.codec_settings.startBitrate = 400; + config.codec_settings.maxBitrate = 500; + config.codec_settings.minBitrate = 70; + config.codec_settings.maxFramerate = 35; + config.codec_settings.qpMax = 66; + config.codec_settings.VP8()->complexity = kComplexityNormal; + config.codec_settings.VP8()->keyFrameInterval = 999; + + EXPECT_EQ( + "Video config:" + "\n Filename : yuvfile" + "\n # CPU cores used : 1" + "\n Codec settings:" + "\n Codec type : VP8" + "\n Start bitrate : 400 kbps" + "\n Max bitrate : 500 kbps" + "\n Min bitrate : 70 kbps" + "\n Width : 320" + "\n Height : 180" + "\n Max frame rate : 35" + "\n QPmax : 66" + "\n Complexity : 0" + "\n Resilience : 0" + "\n # temporal layers : 2" + "\n Denoising : 0" + "\n Error concealment : 1" + "\n Automatic resize : 1" + "\n Frame dropping : 0" + "\n Key frame interval: 999\n", + config.ToString()); +} + } // namespace test } // namespace webrtc diff --git a/modules/video_coding/codecs/test/videoprocessor.cc b/modules/video_coding/codecs/test/videoprocessor.cc index 8b063d5861..0ed380cc86 100644 --- a/modules/video_coding/codecs/test/videoprocessor.cc +++ b/modules/video_coding/codecs/test/videoprocessor.cc @@ -68,6 +68,31 @@ int GetElapsedTimeMicroseconds(int64_t start_ns, int64_t stop_ns) { return static_cast(diff_us); } +void ExtractBufferWithSize(const VideoFrame& image, + int width, + int height, + rtc::Buffer* buffer) { + if (image.width() != width || image.height() != height) { + EXPECT_DOUBLE_EQ(static_cast(width) / height, + static_cast(image.width()) / image.height()); + // Same aspect ratio, no cropping needed. + rtc::scoped_refptr scaled(I420Buffer::Create(width, height)); + scaled->ScaleFrom(*image.video_frame_buffer()->ToI420()); + + size_t length = + CalcBufferSize(VideoType::kI420, scaled->width(), scaled->height()); + buffer->SetSize(length); + RTC_CHECK_NE(ExtractBuffer(scaled, length, buffer->data()), -1); + return; + } + + // No resize. + size_t length = + CalcBufferSize(VideoType::kI420, image.width(), image.height()); + buffer->SetSize(length); + RTC_CHECK_NE(ExtractBuffer(image, length, buffer->data()), -1); +} + } // namespace VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder, @@ -79,8 +104,7 @@ VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder, Stats* stats, IvfFileWriter* encoded_frame_writer, FrameWriter* decoded_frame_writer) - : initialized_(false), - config_(config), + : config_(config), encoder_(encoder), decoder_(decoder), bitrate_allocator_(CreateBitrateAllocator(&config_)), @@ -104,37 +128,24 @@ VideoProcessor::VideoProcessor(webrtc::VideoEncoder* encoder, RTC_DCHECK(analysis_frame_reader); RTC_DCHECK(analysis_frame_writer); RTC_DCHECK(stats); -} - -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_), - WEBRTC_VIDEO_CODEC_OK) - << "Failed to register encode complete callback"; + WEBRTC_VIDEO_CODEC_OK); RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(&decode_callback_), - WEBRTC_VIDEO_CODEC_OK) - << "Failed to register decode complete callback"; + WEBRTC_VIDEO_CODEC_OK); // Initialize the encoder and decoder. RTC_CHECK_EQ( encoder_->InitEncode(&config_.codec_settings, config_.NumberOfCores(), config_.networking_config.max_payload_size_in_bytes), - WEBRTC_VIDEO_CODEC_OK) - << "Failed to initialize VideoEncoder"; - + WEBRTC_VIDEO_CODEC_OK); RTC_CHECK_EQ( decoder_->InitDecode(&config_.codec_settings, config_.NumberOfCores()), - WEBRTC_VIDEO_CODEC_OK) - << "Failed to initialize VideoDecoder"; + WEBRTC_VIDEO_CODEC_OK); } -void VideoProcessor::Release() { +VideoProcessor::~VideoProcessor() { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); RTC_CHECK_EQ(encoder_->Release(), WEBRTC_VIDEO_CODEC_OK); @@ -142,13 +153,10 @@ void VideoProcessor::Release() { encoder_->RegisterEncodeCompleteCallback(nullptr); decoder_->RegisterDecodeCompleteCallback(nullptr); - - initialized_ = false; } void VideoProcessor::ProcessFrame() { RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); - RTC_DCHECK(initialized_) << "VideoProcessor not initialized."; ++last_inputed_frame_num_; // Get frame from file. @@ -233,16 +241,7 @@ void VideoProcessor::FrameEncoded(webrtc::VideoCodecType codec, // For dropped frames, we write out the last decoded frame to avoid // getting out of sync for the computation of PSNR and SSIM. for (int i = 0; i < num_dropped_from_last_encode; i++) { - RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), - analysis_frame_writer_->FrameLength()); - RTC_CHECK(analysis_frame_writer_->WriteFrame( - last_decoded_frame_buffer_.data())); - if (decoded_frame_writer_) { - RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), - decoded_frame_writer_->FrameLength()); - RTC_CHECK(decoded_frame_writer_->WriteFrame( - last_decoded_frame_buffer_.data())); - } + WriteDecodedFrameToFile(&last_decoded_frame_buffer_); } } const FrameStatistic* last_encoded_frame_stat = @@ -266,40 +265,19 @@ void VideoProcessor::FrameEncoded(webrtc::VideoCodecType codec, frame_stat->total_packets = encoded_image._length / config_.networking_config.packet_size_in_bytes + 1; - frame_stat->max_nalu_length = GetMaxNaluLength(encoded_image, config_); - // Simulate packet loss. - bool exclude_this_frame = false; - if (encoded_image._frameType == kVideoFrameKey) { - // Only keyframes can be excluded. - switch (config_.exclude_frame_types) { - case kExcludeOnlyFirstKeyFrame: - if (!first_key_frame_has_been_excluded_) { - first_key_frame_has_been_excluded_ = true; - exclude_this_frame = true; - } - break; - case kExcludeAllKeyFrames: - exclude_this_frame = true; - break; - default: - RTC_NOTREACHED(); - } - } - - // Make a raw copy of the |encoded_image| buffer. + // Make a raw copy of |encoded_image| to feed to the decoder. size_t copied_buffer_size = encoded_image._length + EncodedImage::GetBufferPaddingBytes(codec); std::unique_ptr copied_buffer(new uint8_t[copied_buffer_size]); memcpy(copied_buffer.get(), encoded_image._buffer, encoded_image._length); - // The image to feed to the decoder. - EncodedImage copied_image; - memcpy(&copied_image, &encoded_image, sizeof(copied_image)); + EncodedImage copied_image = encoded_image; copied_image._size = copied_buffer_size; copied_image._buffer = copied_buffer.get(); - if (!exclude_this_frame) { + // Simulate packet loss. + if (!ExcludeFrame(copied_image)) { frame_stat->packets_dropped = packet_manipulator_->ManipulatePackets(&copied_image); } @@ -314,16 +292,7 @@ void VideoProcessor::FrameEncoded(webrtc::VideoCodecType codec, if (frame_stat->decode_return_code != WEBRTC_VIDEO_CODEC_OK) { // Write the last successful frame the output file to avoid getting it out // of sync with the source file for SSIM and PSNR comparisons. - RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), - analysis_frame_writer_->FrameLength()); - RTC_CHECK( - analysis_frame_writer_->WriteFrame(last_decoded_frame_buffer_.data())); - if (decoded_frame_writer_) { - RTC_DCHECK_EQ(last_decoded_frame_buffer_.size(), - decoded_frame_writer_->FrameLength()); - RTC_CHECK( - decoded_frame_writer_->WriteFrame(last_decoded_frame_buffer_.data())); - } + WriteDecodedFrameToFile(&last_decoded_frame_buffer_); } if (encoded_frame_writer_) { @@ -364,39 +333,45 @@ void VideoProcessor::FrameDecoded(const VideoFrame& image) { RTC_CHECK_GT(frame_number, last_decoded_frame_num_); last_decoded_frame_num_ = frame_number; - // Check if frame size is different from the original size, and if so, scale - // back to original size. This is needed for the PSNR and SSIM calculations. - size_t extracted_length; - rtc::Buffer extracted_buffer; - if (image.width() != config_.codec_settings.width || - image.height() != config_.codec_settings.height) { - rtc::scoped_refptr scaled_buffer(I420Buffer::Create( - config_.codec_settings.width, config_.codec_settings.height)); - // Should be the same aspect ratio, no cropping needed. - scaled_buffer->ScaleFrom(*image.video_frame_buffer()->ToI420()); + // If the frame size is different from the original size, scale back to the + // original size. This is needed for the PSNR and SSIM calculations. + rtc::Buffer buffer; + ExtractBufferWithSize(image, config_.codec_settings.width, + config_.codec_settings.height, &buffer); + WriteDecodedFrameToFile(&buffer); - size_t length = CalcBufferSize(VideoType::kI420, scaled_buffer->width(), - scaled_buffer->height()); - extracted_buffer.SetSize(length); - extracted_length = - ExtractBuffer(scaled_buffer, length, extracted_buffer.data()); - } else { - // No resize. - size_t length = - CalcBufferSize(VideoType::kI420, image.width(), image.height()); - extracted_buffer.SetSize(length); - extracted_length = ExtractBuffer(image.video_frame_buffer()->ToI420(), - length, extracted_buffer.data()); - } + last_decoded_frame_buffer_ = std::move(buffer); +} - RTC_DCHECK_EQ(extracted_length, analysis_frame_writer_->FrameLength()); - RTC_CHECK(analysis_frame_writer_->WriteFrame(extracted_buffer.data())); +void VideoProcessor::WriteDecodedFrameToFile(rtc::Buffer* buffer) { + RTC_DCHECK_EQ(buffer->size(), analysis_frame_writer_->FrameLength()); + RTC_CHECK(analysis_frame_writer_->WriteFrame(buffer->data())); if (decoded_frame_writer_) { - RTC_DCHECK_EQ(extracted_length, decoded_frame_writer_->FrameLength()); - RTC_CHECK(decoded_frame_writer_->WriteFrame(extracted_buffer.data())); + RTC_DCHECK_EQ(buffer->size(), decoded_frame_writer_->FrameLength()); + RTC_CHECK(decoded_frame_writer_->WriteFrame(buffer->data())); } +} - last_decoded_frame_buffer_ = std::move(extracted_buffer); +bool VideoProcessor::ExcludeFrame(const EncodedImage& encoded_image) { + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); + if (encoded_image._frameType != kVideoFrameKey) { + return false; + } + bool exclude_frame = false; + switch (config_.exclude_frame_types) { + case kExcludeOnlyFirstKeyFrame: + if (!first_key_frame_has_been_excluded_) { + first_key_frame_has_been_excluded_ = true; + exclude_frame = true; + } + break; + case kExcludeAllKeyFrames: + exclude_frame = true; + break; + default: + RTC_NOTREACHED(); + } + return exclude_frame; } } // namespace test diff --git a/modules/video_coding/codecs/test/videoprocessor.h b/modules/video_coding/codecs/test/videoprocessor.h index d82ae9a87a..0960744b01 100644 --- a/modules/video_coding/codecs/test/videoprocessor.h +++ b/modules/video_coding/codecs/test/videoprocessor.h @@ -70,12 +70,6 @@ class VideoProcessor { FrameWriter* decoded_frame_writer); ~VideoProcessor(); - // Sets up callbacks and initializes the encoder and decoder. - void Init(); - - // Tears down callbacks and releases the encoder and decoder. - void Release(); - // Reads a frame from the analysis frame reader and sends it to the encoder. // When the encode callback is received, the encoded frame is sent to the // decoder. The decoded frame is written to disk by the analysis frame writer. @@ -189,7 +183,9 @@ class VideoProcessor { // Invoked by the callback adapter when a frame has completed decoding. void FrameDecoded(const webrtc::VideoFrame& image); - bool initialized_ RTC_GUARDED_BY(sequence_checker_); + void WriteDecodedFrameToFile(rtc::Buffer* buffer); + bool ExcludeFrame(const EncodedImage& encoded_image); + TestConfig config_ RTC_GUARDED_BY(sequence_checker_); webrtc::VideoEncoder* const encoder_; diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc index b3b4e2efee..08b64deada 100644 --- a/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc +++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc @@ -212,9 +212,7 @@ void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify( SleepMs(1 * rtc::kNumMillisecsPerSec); } cpu_process_time_->Stop(); - ReleaseAndCloseObjects(&task_queue); - // Calculate and print rate control statistics. std::vector num_dropped_frames; std::vector num_spatial_resizes; sync_event.Reset(); @@ -226,6 +224,9 @@ void VideoProcessorIntegrationTest::ProcessFramesAndMaybeVerify( }); sync_event.Wait(rtc::Event::kForever); + ReleaseAndCloseObjects(&task_queue); + + // Calculate and print rate control statistics. rate_update_index = 0; frame_number = 0; ResetRateControlMetrics(rate_update_index, rate_profiles); @@ -416,7 +417,6 @@ void VideoProcessorIntegrationTest::SetUpAndInitObjects( encoder_.get(), decoder_.get(), analysis_frame_reader_.get(), analysis_frame_writer_.get(), packet_manipulator_.get(), config_, &stats_, encoded_frame_writer_.get(), decoded_frame_writer_.get()); - processor_->Init(); sync_event.Set(); }); sync_event.Wait(rtc::Event::kForever); @@ -426,12 +426,12 @@ void VideoProcessorIntegrationTest::ReleaseAndCloseObjects( rtc::TaskQueue* task_queue) { rtc::Event sync_event(false, false); task_queue->PostTask([this, &sync_event]() { - processor_->Release(); + processor_.reset(); sync_event.Set(); }); sync_event.Wait(rtc::Event::kForever); - // The VideoProcessor must be ::Release()'d before we destroy the codecs. + // The VideoProcessor must be destroyed before the codecs. DestroyEncoderAndDecoder(); // Close the analysis files before we use them for SSIM/PSNR calculations. @@ -451,7 +451,7 @@ void VideoProcessorIntegrationTest::ReleaseAndCloseObjects( void VideoProcessorIntegrationTest::UpdateRateControlMetrics(int frame_number) { RTC_CHECK_GE(frame_number, 0); - const int tl_idx = TemporalLayerIndexForFrame(frame_number); + const int tl_idx = config_.TemporalLayerForFrame(frame_number); ++actual_.num_frames_layer[tl_idx]; ++actual_.num_frames; @@ -563,7 +563,7 @@ void VideoProcessorIntegrationTest::MaybePrintSettings() const { if (!config_.verbose) return; - config_.Print(); + printf("%s\n", config_.ToString().c_str()); printf(" Total # of frames: %d\n", analysis_frame_reader_->NumberOfFrames()); const char* encoder_name = encoder_->ImplementationName(); const char* decoder_name = decoder_->ImplementationName(); @@ -585,38 +585,6 @@ void VideoProcessorIntegrationTest::VerifyBitstream( EXPECT_LE(*(frame_stat->max_nalu_length), bs_thresholds.max_nalu_length); } -// Temporal layer index corresponding to frame number, for up to 3 layers. -int VideoProcessorIntegrationTest::TemporalLayerIndexForFrame( - int frame_number) const { - int tl_idx = -1; - switch (config_.NumberOfTemporalLayers()) { - case 1: - tl_idx = 0; - break; - case 2: - // temporal layer 0: 0 2 4 ... - // temporal layer 1: 1 3 - tl_idx = (frame_number % 2 == 0) ? 0 : 1; - break; - case 3: - // temporal layer 0: 0 4 8 ... - // temporal layer 1: 2 6 - // temporal layer 2: 1 3 5 7 - if (frame_number % 4 == 0) { - tl_idx = 0; - } else if ((frame_number + 2) % 4 == 0) { - tl_idx = 1; - } else if ((frame_number + 1) % 2 == 0) { - tl_idx = 2; - } - break; - default: - RTC_NOTREACHED(); - break; - } - return tl_idx; -} - // Reset quantities before each encoder rate update. void VideoProcessorIntegrationTest::ResetRateControlMetrics( int rate_update_index, diff --git a/modules/video_coding/codecs/test/videoprocessor_integrationtest.h b/modules/video_coding/codecs/test/videoprocessor_integrationtest.h index 8dcade6024..511b7d9439 100644 --- a/modules/video_coding/codecs/test/videoprocessor_integrationtest.h +++ b/modules/video_coding/codecs/test/videoprocessor_integrationtest.h @@ -164,7 +164,6 @@ class VideoProcessorIntegrationTest : public testing::Test { const int initial_framerate_fps, const VisualizationParams* visualization_params); void ReleaseAndCloseObjects(rtc::TaskQueue* task_queue); - int TemporalLayerIndexForFrame(int frame_number) const; // Rate control metrics. void ResetRateControlMetrics(int rate_update_index, diff --git a/modules/video_coding/codecs/test/videoprocessor_unittest.cc b/modules/video_coding/codecs/test/videoprocessor_unittest.cc index e116a9ecb2..a3bf9e30fd 100644 --- a/modules/video_coding/codecs/test/videoprocessor_unittest.cc +++ b/modules/video_coding/codecs/test/videoprocessor_unittest.cc @@ -27,7 +27,6 @@ #include "typedefs.h" // NOLINT(build/include) using ::testing::_; -using ::testing::AtLeast; using ::testing::ElementsAre; using ::testing::Property; using ::testing::Return; @@ -40,7 +39,6 @@ namespace { const int kWidth = 352; const int kHeight = 288; const int kFrameSize = kWidth * kHeight * 3 / 2; // I420. -const int kNumFrames = 2; } // namespace @@ -52,8 +50,7 @@ class VideoProcessorTest : public testing::Test { config_.codec_settings.width = kWidth; config_.codec_settings.height = kHeight; - EXPECT_CALL(frame_reader_mock_, NumberOfFrames()) - .WillRepeatedly(Return(kNumFrames)); + ExpectInit(); EXPECT_CALL(frame_reader_mock_, FrameLength()) .WillRepeatedly(Return(kFrameSize)); video_processor_ = rtc::MakeUnique( @@ -88,19 +85,15 @@ class VideoProcessorTest : public testing::Test { }; TEST_F(VideoProcessorTest, InitRelease) { - ExpectInit(); - video_processor_->Init(); - ExpectRelease(); - video_processor_->Release(); } TEST_F(VideoProcessorTest, ProcessFrames_FixedFramerate) { - ExpectInit(); - video_processor_->Init(); - const int kBitrateKbps = 456; const int kFramerateFps = 31; + EXPECT_CALL(encoder_mock_, SetRateAllocation(_, kFramerateFps)) + .Times(1) + .WillOnce(Return(0)); video_processor_->SetRates(kBitrateKbps, kFramerateFps); EXPECT_CALL(frame_reader_mock_, ReadFrame()) @@ -118,15 +111,14 @@ TEST_F(VideoProcessorTest, ProcessFrames_FixedFramerate) { video_processor_->ProcessFrame(); ExpectRelease(); - video_processor_->Release(); } TEST_F(VideoProcessorTest, ProcessFrames_VariableFramerate) { - ExpectInit(); - video_processor_->Init(); - const int kBitrateKbps = 456; const int kStartFramerateFps = 27; + EXPECT_CALL(encoder_mock_, SetRateAllocation(_, kStartFramerateFps)) + .Times(1) + .WillOnce(Return(0)); video_processor_->SetRates(kBitrateKbps, kStartFramerateFps); EXPECT_CALL(frame_reader_mock_, ReadFrame()) @@ -138,6 +130,9 @@ TEST_F(VideoProcessorTest, ProcessFrames_VariableFramerate) { video_processor_->ProcessFrame(); const int kNewFramerateFps = 13; + EXPECT_CALL(encoder_mock_, SetRateAllocation(_, kNewFramerateFps)) + .Times(1) + .WillOnce(Return(0)); video_processor_->SetRates(kBitrateKbps, kNewFramerateFps); EXPECT_CALL(encoder_mock_, Encode(Property(&VideoFrame::timestamp, @@ -147,13 +142,9 @@ TEST_F(VideoProcessorTest, ProcessFrames_VariableFramerate) { video_processor_->ProcessFrame(); ExpectRelease(); - video_processor_->Release(); } TEST_F(VideoProcessorTest, SetRates) { - ExpectInit(); - video_processor_->Init(); - const int kBitrateKbps = 123; const int kFramerateFps = 17; EXPECT_CALL(encoder_mock_, @@ -181,7 +172,6 @@ TEST_F(VideoProcessorTest, SetRates) { ElementsAre(0, 0)); ExpectRelease(); - video_processor_->Release(); } } // namespace test