Add ability to enable frame dumping decoder via field trial.

--force_fieldtrial=/WebRTC-DecoderDataDumpDirectory/./ will create a
file ./webrtc_receive_stream_[ssrc].ivf containing the exact data that
is fed to the decoder.

Bug: None
Change-Id: I4042298c9b851fc4b61c417652315fa2610de1ed
Reviewed-on: https://webrtc-review.googlesource.com/c/107644
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25467}
This commit is contained in:
Erik Språng 2018-10-23 15:42:37 +02:00 committed by Commit Bot
parent fe45da4f04
commit 96965aeba9
5 changed files with 148 additions and 49 deletions

View File

@ -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",

View File

@ -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 <utility>
#include "modules/video_coding/include/video_codec_interface.h"
namespace webrtc {
FrameDumpingDecoder::FrameDumpingDecoder(std::unique_ptr<VideoDecoder> 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

View File

@ -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 <memory>
#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<VideoDecoder> 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<VideoDecoder> decoder_;
std::unique_ptr<IvfFileWriter> writer_;
};
} // namespace webrtc
#endif // VIDEO_FRAME_DUMPING_DECODER_H_

View File

@ -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<VideoStream> streams_;
};
// A decoder wrapper that writes the encoded frames to a file.
class FrameDumpingDecoder : public VideoDecoder {
public:
FrameDumpingDecoder(std::unique_ptr<VideoDecoder> 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<VideoDecoder> decoder_;
std::unique_ptr<IvfFileWriter> 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<InjectionComponents>();
}

View File

@ -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<NullVideoDecoder>();
}
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<FrameDumpingDecoder>(
std::move(video_decoder), rtc::CreatePlatformFile(ssb.str()));
}
video_decoders_.push_back(std::move(video_decoder));
video_receiver_.RegisterExternalDecoder(video_decoders_.back().get(),