Introduce VideoQualityAnalyzerInjectionHelper.

VideoQualityAnalyzerInjectionHelper will be used to provide all required
entities to inject video quality analyzer into peer connection pipeline.

Bug: webrtc:10138
Change-Id: Iea7cf453311d809619839d5cf94b78a020ce9167
Reviewed-on: https://webrtc-review.googlesource.com/c/119642
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26395}
This commit is contained in:
Artem Titov 2019-01-24 16:54:03 +01:00 committed by Commit Bot
parent 3ea55d56eb
commit f50c6c2fb4
5 changed files with 245 additions and 4 deletions

View File

@ -467,6 +467,10 @@ bool FrameForwarder::has_sinks() const {
return sink_ != nullptr;
}
void FrameGenerator::ChangeResolution(size_t width, size_t height) {
RTC_NOTREACHED();
}
std::unique_ptr<FrameGenerator> FrameGenerator::CreateSquareGenerator(
int width,
int height,

View File

@ -29,7 +29,7 @@ namespace test {
class FrameForwarder : public rtc::VideoSourceInterface<VideoFrame> {
public:
FrameForwarder();
virtual ~FrameForwarder();
~FrameForwarder() override;
// Forwards |video_frame| to the registered |sink_|.
virtual void IncomingCapturedFrame(const VideoFrame& video_frame);
rtc::VideoSinkWants sink_wants() const;
@ -56,9 +56,7 @@ class FrameGenerator {
virtual VideoFrame* NextFrame() = 0;
// Change the capture resolution.
virtual void ChangeResolution(size_t width, size_t height) {
RTC_NOTREACHED();
}
virtual void ChangeResolution(size_t width, size_t height);
enum class OutputType { I420, I420A, I010 };

View File

@ -20,6 +20,9 @@ group("e2e") {
":quality_analyzing_video_encoder",
":single_process_encoded_image_id_injector",
]
if (rtc_include_tests) {
deps += [ ":video_quality_analyzer_injection_helper" ]
}
}
if (rtc_include_tests) {
@ -127,6 +130,27 @@ rtc_source_set("quality_analyzing_video_encoder") {
}
if (rtc_include_tests) {
rtc_source_set("video_quality_analyzer_injection_helper") {
visibility = [ "*" ]
testonly = true
sources = [
"analyzer/video/video_quality_analyzer_injection_helper.cc",
"analyzer/video/video_quality_analyzer_injection_helper.h",
]
deps = [
":encoded_image_id_injector_api",
":id_generator",
":quality_analyzing_video_decoder",
":quality_analyzing_video_encoder",
"../../../api/video:video_frame",
"../../../api/video_codecs:video_codecs_api",
"../../../test:video_test_common",
"../../../test:video_test_support",
"api:video_quality_analyzer_api",
"//third_party/abseil-cpp/absl/memory:memory",
]
}
rtc_source_set("single_process_encoded_image_id_injector_unittest") {
testonly = true
sources = [

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2019 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 "test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h"
#include <utility>
#include "absl/memory/memory.h"
#include "test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h"
#include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h"
namespace webrtc {
namespace test {
namespace {
// Intercepts generated frames and passes them also to video quality analyzer
// and into video frame writer, if the last one is provided.
class InterceptingFrameGenerator : public FrameGenerator {
public:
InterceptingFrameGenerator(std::string stream_label,
std::unique_ptr<FrameGenerator> delegate,
VideoQualityAnalyzerInterface* analyzer,
VideoFrameWriter* video_writer)
: stream_label_(std::move(stream_label)),
delegate_(std::move(delegate)),
analyzer_(analyzer),
video_writer_(video_writer) {
RTC_DCHECK(analyzer_);
}
~InterceptingFrameGenerator() override = default;
VideoFrame* NextFrame() override {
VideoFrame* frame = delegate_->NextFrame();
uint16_t frame_id = analyzer_->OnFrameCaptured(stream_label_, *frame);
frame->set_id(frame_id);
if (video_writer_) {
bool result = video_writer_->WriteFrame(*frame);
RTC_CHECK(result) << "Failed to write frame";
}
return frame;
}
void ChangeResolution(size_t width, size_t height) override {
delegate_->ChangeResolution(width, height);
}
private:
std::string stream_label_;
std::unique_ptr<FrameGenerator> delegate_;
VideoQualityAnalyzerInterface* analyzer_;
VideoFrameWriter* video_writer_;
};
// Implements the video sink, that forwards rendered frames to the video quality
// analyzer and to the video frame writer, if the last one is provided.
class AnalyzingVideoSink : public rtc::VideoSinkInterface<VideoFrame> {
public:
AnalyzingVideoSink(VideoQualityAnalyzerInterface* analyzer,
VideoFrameWriter* video_writer)
: analyzer_(analyzer), video_writer_(video_writer) {
RTC_DCHECK(analyzer_);
}
~AnalyzingVideoSink() override = default;
void OnFrame(const VideoFrame& frame) override {
analyzer_->OnFrameRendered(frame);
if (video_writer_) {
bool result = video_writer_->WriteFrame(frame);
RTC_CHECK(result) << "Failed to write frame";
}
}
void OnDiscardedFrame() override {}
private:
VideoQualityAnalyzerInterface* analyzer_;
VideoFrameWriter* video_writer_;
};
} // namespace
VideoQualityAnalyzerInjectionHelper::VideoQualityAnalyzerInjectionHelper(
std::unique_ptr<VideoQualityAnalyzerInterface> analyzer,
EncodedImageIdInjector* injector,
EncodedImageIdExtractor* extractor)
: analyzer_(std::move(analyzer)),
injector_(injector),
extractor_(extractor),
encoding_entities_id_generator_(absl::make_unique<IntIdGenerator>(1)) {
RTC_DCHECK(injector_);
RTC_DCHECK(extractor_);
}
VideoQualityAnalyzerInjectionHelper::~VideoQualityAnalyzerInjectionHelper() =
default;
std::unique_ptr<VideoEncoderFactory>
VideoQualityAnalyzerInjectionHelper::WrapVideoEncoderFactory(
std::unique_ptr<VideoEncoderFactory> delegate) const {
return absl::make_unique<QualityAnalyzingVideoEncoderFactory>(
std::move(delegate), encoding_entities_id_generator_.get(), injector_,
analyzer_.get());
}
std::unique_ptr<VideoDecoderFactory>
VideoQualityAnalyzerInjectionHelper::WrapVideoDecoderFactory(
std::unique_ptr<VideoDecoderFactory> delegate) const {
return absl::make_unique<QualityAnalyzingVideoDecoderFactory>(
std::move(delegate), encoding_entities_id_generator_.get(), extractor_,
analyzer_.get());
}
std::unique_ptr<FrameGenerator>
VideoQualityAnalyzerInjectionHelper::WrapFrameGenerator(
std::string stream_label,
std::unique_ptr<FrameGenerator> delegate,
VideoFrameWriter* writer) const {
return absl::make_unique<InterceptingFrameGenerator>(
std::move(stream_label), std::move(delegate), analyzer_.get(), writer);
}
std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>>
VideoQualityAnalyzerInjectionHelper::CreateVideoSink(
VideoFrameWriter* writer) const {
return absl::make_unique<AnalyzingVideoSink>(analyzer_.get(), writer);
}
void VideoQualityAnalyzerInjectionHelper::Stop() {
analyzer_->Stop();
}
} // namespace test
} // namespace webrtc

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2019 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 TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_
#define TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_
#include <memory>
#include <string>
#include "api/video/video_frame.h"
#include "api/video/video_sink_interface.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "api/video_codecs/video_encoder_factory.h"
#include "test/frame_generator.h"
#include "test/pc/e2e/analyzer/video/encoded_image_id_injector.h"
#include "test/pc/e2e/analyzer/video/id_generator.h"
#include "test/pc/e2e/api/video_quality_analyzer_interface.h"
#include "test/testsupport/video_frame_writer.h"
namespace webrtc {
namespace test {
// Provides factory methods for components, that will be used to inject
// VideoQualityAnalyzerInterface into PeerConnection pipeline.
class VideoQualityAnalyzerInjectionHelper {
public:
VideoQualityAnalyzerInjectionHelper(
std::unique_ptr<VideoQualityAnalyzerInterface> analyzer,
EncodedImageIdInjector* injector,
EncodedImageIdExtractor* extractor);
~VideoQualityAnalyzerInjectionHelper();
// Wraps video encoder factory to give video quality analyzer access to frames
// before encoding and encoded images after.
std::unique_ptr<VideoEncoderFactory> WrapVideoEncoderFactory(
std::unique_ptr<VideoEncoderFactory> delegate) const;
// Wraps video decoder factory to give video quality analyzer access to
// received encoded images and frames, that were decoded from them.
std::unique_ptr<VideoDecoderFactory> WrapVideoDecoderFactory(
std::unique_ptr<VideoDecoderFactory> delegate) const;
// Wraps frame generator, so video quality analyzer will gain access to the
// captured frames. If |writer| in not nullptr, will dump captured frames
// with provided writer.
std::unique_ptr<FrameGenerator> WrapFrameGenerator(
std::string stream_label,
std::unique_ptr<FrameGenerator> delegate,
VideoFrameWriter* writer) const;
// Creates sink, that will allow video quality analyzer to get access to the
// rendered frames. If |writer| in not nullptr, will dump rendered frames
// with provided writer.
std::unique_ptr<rtc::VideoSinkInterface<VideoFrame>> CreateVideoSink(
VideoFrameWriter* writer) const;
// Stops VideoQualityAnalyzerInterface to populate final data and metrics.
void Stop();
private:
std::unique_ptr<VideoQualityAnalyzerInterface> analyzer_;
EncodedImageIdInjector* injector_;
EncodedImageIdExtractor* extractor_;
std::unique_ptr<IdGenerator<int>> encoding_entities_id_generator_;
};
} // namespace test
} // namespace webrtc
#endif // TEST_PC_E2E_ANALYZER_VIDEO_VIDEO_QUALITY_ANALYZER_INJECTION_HELPER_H_