diff --git a/video/BUILD.gn b/video/BUILD.gn index 33dcbe6485..e6a39e7c18 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -52,6 +52,7 @@ rtc_static_library("video") { } deps = [ + ":frame_dumping_decoder", "..:webrtc_common", "../api:fec_controller_api", "../api:libjingle_peerconnection_api", @@ -133,6 +134,25 @@ rtc_source_set("video_stream_decoder_impl") { ] } +rtc_source_set("frame_dumping_decoder") { + visibility = [ "*" ] + + sources = [ + "frame_dumping_decoder.cc", + "frame_dumping_decoder.h", + ] + + deps = [ + "../api/video:encoded_frame", + "../api/video_codecs:video_codecs_api", + "../modules/video_coding:video_codec_interface", + "../modules/video_coding:video_coding", + "../modules/video_coding:video_coding_utility", + "../rtc_base:rtc_base_approved", + "//third_party/abseil-cpp/absl/memory", + ] +} + rtc_source_set("video_stream_encoder_impl") { visibility = [ "*" ] @@ -204,6 +224,7 @@ if (rtc_include_tests) { "video_quality_test.h", ] deps = [ + ":frame_dumping_decoder", "../api:fec_controller_api", "../api:test_dependency_factory", "../api:video_quality_test_fixture_api", diff --git a/video/frame_dumping_decoder.cc b/video/frame_dumping_decoder.cc new file mode 100644 index 0000000000..7798511b54 --- /dev/null +++ b/video/frame_dumping_decoder.cc @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "video/frame_dumping_decoder.h" + +#include + +#include "modules/video_coding/include/video_codec_interface.h" + +namespace webrtc { + +FrameDumpingDecoder::FrameDumpingDecoder(std::unique_ptr decoder, + rtc::PlatformFile file) + : decoder_(std::move(decoder)), + writer_(IvfFileWriter::Wrap(rtc::File(file), + /* byte_limit= */ 100000000)) {} + +FrameDumpingDecoder::~FrameDumpingDecoder() = default; + +int32_t FrameDumpingDecoder::InitDecode(const VideoCodec* codec_settings, + int32_t number_of_cores) { + return decoder_->InitDecode(codec_settings, number_of_cores); +} + +int32_t FrameDumpingDecoder::Decode( + const EncodedImage& input_image, + bool missing_frames, + const CodecSpecificInfo* codec_specific_info, + int64_t render_time_ms) { + int32_t ret = decoder_->Decode(input_image, missing_frames, + codec_specific_info, render_time_ms); + writer_->WriteFrame(input_image, codec_specific_info->codecType); + + return ret; +} + +int32_t FrameDumpingDecoder::RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) { + return decoder_->RegisterDecodeCompleteCallback(callback); +} + +int32_t FrameDumpingDecoder::Release() { + return decoder_->Release(); +} + +bool FrameDumpingDecoder::PrefersLateDecoding() const { + return decoder_->PrefersLateDecoding(); +} + +const char* FrameDumpingDecoder::ImplementationName() const { + return decoder_->ImplementationName(); +} + +} // namespace webrtc diff --git a/video/frame_dumping_decoder.h b/video/frame_dumping_decoder.h new file mode 100644 index 0000000000..e19e9b4db0 --- /dev/null +++ b/video/frame_dumping_decoder.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VIDEO_FRAME_DUMPING_DECODER_H_ +#define VIDEO_FRAME_DUMPING_DECODER_H_ + +#include + +#include "api/video_codecs/video_decoder.h" +#include "modules/video_coding/utility/ivf_file_writer.h" +#include "rtc_base/platform_file.h" + +namespace webrtc { + +// A decoder wrapper that writes the encoded frames to a file. +class FrameDumpingDecoder : public VideoDecoder { + public: + FrameDumpingDecoder(std::unique_ptr decoder, + rtc::PlatformFile file); + ~FrameDumpingDecoder() override; + + int32_t InitDecode(const VideoCodec* codec_settings, + int32_t number_of_cores) override; + int32_t Decode(const EncodedImage& input_image, + bool missing_frames, + const CodecSpecificInfo* codec_specific_info, + int64_t render_time_ms) override; + int32_t RegisterDecodeCompleteCallback( + DecodedImageCallback* callback) override; + int32_t Release() override; + bool PrefersLateDecoding() const override; + const char* ImplementationName() const override; + + private: + std::unique_ptr decoder_; + std::unique_ptr writer_; +}; + +} // namespace webrtc + +#endif // VIDEO_FRAME_DUMPING_DECODER_H_ diff --git a/video/video_quality_test.cc b/video/video_quality_test.cc index 15579d855b..6517c97e8c 100644 --- a/video/video_quality_test.cc +++ b/video/video_quality_test.cc @@ -35,6 +35,7 @@ #include "test/run_loop.h" #include "test/testsupport/fileutils.h" #include "test/video_renderer.h" +#include "video/frame_dumping_decoder.h" #ifdef WEBRTC_WIN #include "modules/audio_device/include/audio_device_factory.h" #endif @@ -74,54 +75,6 @@ class VideoStreamFactory std::vector streams_; }; -// A decoder wrapper that writes the encoded frames to a file. -class FrameDumpingDecoder : public VideoDecoder { - public: - FrameDumpingDecoder(std::unique_ptr decoder, - rtc::PlatformFile file) - : decoder_(std::move(decoder)), - writer_(IvfFileWriter::Wrap(rtc::File(file), - /* byte_limit= */ 100000000)) {} - - int32_t InitDecode(const VideoCodec* codec_settings, - int32_t number_of_cores) override { - return decoder_->InitDecode(codec_settings, number_of_cores); - } - - int32_t Decode(const EncodedImage& input_image, - bool missing_frames, - const CodecSpecificInfo* codec_specific_info, - int64_t render_time_ms) override { - int32_t ret = decoder_->Decode(input_image, missing_frames, - codec_specific_info, render_time_ms); - writer_->WriteFrame(input_image, codec_specific_info->codecType); - - return ret; - } - - int32_t RegisterDecodeCompleteCallback( - DecodedImageCallback* callback) override { - return decoder_->RegisterDecodeCompleteCallback(callback); - } - - int32_t Release() override { return decoder_->Release(); } - - // Returns true if the decoder prefer to decode frames late. - // That is, it can not decode infinite number of frames before the decoded - // frame is consumed. - bool PrefersLateDecoding() const override { - return decoder_->PrefersLateDecoding(); - } - - const char* ImplementationName() const override { - return decoder_->ImplementationName(); - } - - private: - std::unique_ptr decoder_; - std::unique_ptr writer_; -}; - // This wrapper provides two features needed by the video quality tests: // 1. Invoke VideoAnalyzer callbacks before and after encoding each frame. // 2. Write the encoded frames to file, one file per simulcast layer. @@ -285,7 +238,8 @@ VideoQualityTest::VideoQualityTest( }), receive_logs_(0), send_logs_(0), - injection_components_(std::move(injection_components)) { + injection_components_(std::move(injection_components)), + num_video_streams_(0) { if (injection_components_ == nullptr) { injection_components_ = absl::make_unique(); } diff --git a/video/video_receive_stream.cc b/video/video_receive_stream.cc index 9ffd278371..2f78a8034a 100644 --- a/video/video_receive_stream.cc +++ b/video/video_receive_stream.cc @@ -35,10 +35,13 @@ #include "rtc_base/checks.h" #include "rtc_base/location.h" #include "rtc_base/logging.h" +#include "rtc_base/platform_file.h" +#include "rtc_base/strings/string_builder.h" #include "rtc_base/trace_event.h" #include "system_wrappers/include/clock.h" #include "system_wrappers/include/field_trial.h" #include "video/call_stats.h" +#include "video/frame_dumping_decoder.h" #include "video/receive_statistics_proxy.h" namespace webrtc { @@ -246,6 +249,18 @@ void VideoReceiveStream::Start() { if (!video_decoder) { video_decoder = absl::make_unique(); } + + std::string decoded_output_file = + field_trial::FindFullName("WebRTC-DecoderDataDumpDirectory"); + if (!decoded_output_file.empty()) { + char filename_buffer[256]; + rtc::SimpleStringBuilder ssb(filename_buffer); + ssb << decoded_output_file << "/webrtc_receive_stream_" + << this->config_.rtp.local_ssrc << ".ivf"; + video_decoder = absl::make_unique( + std::move(video_decoder), rtc::CreatePlatformFile(ssb.str())); + } + video_decoders_.push_back(std::move(video_decoder)); video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),