mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00
New VideoDecoderFactoryTemplate.
The VideoDecoderFactoryTemplate takes decoder implementations as template arguments, making it possible to easily implement a VideoDecoderFactory only using the implementations required for the particular application. This will replace the BuiltinVideoDecoderFactory. Bug: webrtc:13573 Change-Id: I0213acd20b69dacf06fc6934851b73bd19b1afc8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/268470 Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Commit-Queue: Philip Eliasson <philipel@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37523}
This commit is contained in:
parent
6f22eb55b3
commit
f0232f31fb
9 changed files with 413 additions and 0 deletions
4
api/DEPS
4
api/DEPS
|
@ -299,6 +299,10 @@ specific_include_rules = {
|
|||
"+modules/video_coding",
|
||||
],
|
||||
|
||||
"video_decoder_factory_template.*\.h": [
|
||||
"+modules/video_coding",
|
||||
],
|
||||
|
||||
"field_trials\.h": [
|
||||
"+rtc_base/containers/flat_map.h",
|
||||
],
|
||||
|
|
|
@ -189,6 +189,51 @@ rtc_source_set("video_encoder_factory_template_libaom_av1_adapter") {
|
|||
absl_deps = [ "//third_party/abseil-cpp/absl/container:inlined_vector" ]
|
||||
}
|
||||
|
||||
rtc_source_set("video_decoder_factory_template") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
public = [ "video_decoder_factory_template.h" ]
|
||||
|
||||
deps = [
|
||||
":video_codecs_api",
|
||||
"../../api:array_view",
|
||||
]
|
||||
|
||||
absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ]
|
||||
}
|
||||
|
||||
rtc_source_set("video_decoder_factory_template_libvpx_vp8_adapter") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
public = [ "video_decoder_factory_template_libvpx_vp8_adapter.h" ]
|
||||
|
||||
deps = [ "../../modules/video_coding:webrtc_vp8" ]
|
||||
}
|
||||
|
||||
rtc_source_set("video_decoder_factory_template_libvpx_vp9_adapter") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
public = [ "video_decoder_factory_template_libvpx_vp9_adapter.h" ]
|
||||
|
||||
deps = [ "../../modules/video_coding:webrtc_vp9" ]
|
||||
}
|
||||
|
||||
rtc_source_set("video_decoder_factory_template_open_h264_adapter") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
public = [ "video_decoder_factory_template_open_h264_adapter.h" ]
|
||||
|
||||
deps = [ "../../modules/video_coding:webrtc_h264" ]
|
||||
}
|
||||
|
||||
rtc_source_set("video_decoder_factory_template_dav1d_adapter") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
public = [ "video_decoder_factory_template_dav1d_adapter.h" ]
|
||||
|
||||
deps = [ "../../modules/video_coding/codecs/av1:dav1d_decoder" ]
|
||||
}
|
||||
|
||||
rtc_library("vp8_temporal_layers_factory") {
|
||||
visibility = [ "*" ]
|
||||
allow_poison = [ "software_video_codecs" ]
|
||||
|
|
|
@ -20,6 +20,7 @@ if (rtc_include_tests) {
|
|||
]
|
||||
|
||||
deps = [
|
||||
":video_decoder_factory_template_tests",
|
||||
":video_encoder_factory_template_tests",
|
||||
"..:builtin_video_encoder_factory",
|
||||
"..:rtc_software_fallback_wrappers",
|
||||
|
@ -60,4 +61,20 @@ if (rtc_include_tests) {
|
|||
"//testing/gtest",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_library("video_decoder_factory_template_tests") {
|
||||
testonly = true
|
||||
sources = [ "video_decoder_factory_template_tests.cc" ]
|
||||
|
||||
deps = [
|
||||
"..:video_decoder_factory_template",
|
||||
"..:video_decoder_factory_template_dav1d_adapter",
|
||||
"..:video_decoder_factory_template_libvpx_vp8_adapter",
|
||||
"..:video_decoder_factory_template_libvpx_vp9_adapter",
|
||||
"..:video_decoder_factory_template_open_h264_adapter",
|
||||
"../../:mock_video_decoder",
|
||||
"../../../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
119
api/video_codecs/test/video_decoder_factory_template_tests.cc
Normal file
119
api/video_codecs/test/video_decoder_factory_template_tests.cc
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 "api/test/mock_video_decoder.h"
|
||||
#include "api/video_codecs/video_decoder_factory_template.h"
|
||||
#include "api/video_codecs/video_decoder_factory_template_dav1d_adapter.h"
|
||||
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp8_adapter.h"
|
||||
#include "api/video_codecs/video_decoder_factory_template_libvpx_vp9_adapter.h"
|
||||
#include "api/video_codecs/video_decoder_factory_template_open_h264_adapter.h"
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
using ::testing::Contains;
|
||||
using ::testing::Each;
|
||||
using ::testing::Eq;
|
||||
using ::testing::Field;
|
||||
using ::testing::IsEmpty;
|
||||
using ::testing::Ne;
|
||||
using ::testing::Not;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
const SdpVideoFormat kFooSdp("Foo");
|
||||
const SdpVideoFormat kBarLowSdp("Bar", {{"profile", "low"}});
|
||||
const SdpVideoFormat kBarHighSdp("Bar", {{"profile", "high"}});
|
||||
|
||||
struct FooDecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() { return {kFooSdp}; }
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return std::make_unique<testing::StrictMock<MockVideoDecoder>>();
|
||||
}
|
||||
};
|
||||
|
||||
struct BarDecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() {
|
||||
return {kBarLowSdp, kBarHighSdp};
|
||||
}
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return std::make_unique<testing::StrictMock<MockVideoDecoder>>();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, OneTemplateAdapterCreateDecoder) {
|
||||
VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter> factory;
|
||||
EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(kFooSdp), Ne(nullptr));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("FooX")), Eq(nullptr));
|
||||
}
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, TwoTemplateAdaptersNoDuplicates) {
|
||||
VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter,
|
||||
FooDecoderTemplateAdapter>
|
||||
factory;
|
||||
EXPECT_THAT(factory.GetSupportedFormats(), UnorderedElementsAre(kFooSdp));
|
||||
}
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, TwoTemplateAdaptersCreateDecoders) {
|
||||
VideoDecoderFactoryTemplate<FooDecoderTemplateAdapter,
|
||||
BarDecoderTemplateAdapter>
|
||||
factory;
|
||||
EXPECT_THAT(factory.GetSupportedFormats(),
|
||||
UnorderedElementsAre(kFooSdp, kBarLowSdp, kBarHighSdp));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(kFooSdp), Ne(nullptr));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(kBarLowSdp), Ne(nullptr));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(kBarHighSdp), Ne(nullptr));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("FooX")), Eq(nullptr));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(SdpVideoFormat("Bar")), Eq(nullptr));
|
||||
}
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, LibvpxVp8) {
|
||||
VideoDecoderFactoryTemplate<LibvpxVp8DecoderTemplateAdapter> factory;
|
||||
auto formats = factory.GetSupportedFormats();
|
||||
EXPECT_THAT(formats.size(), 1);
|
||||
EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "VP8"));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr));
|
||||
}
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, LibvpxVp9) {
|
||||
VideoDecoderFactoryTemplate<LibvpxVp9DecoderTemplateAdapter> factory;
|
||||
auto formats = factory.GetSupportedFormats();
|
||||
EXPECT_THAT(formats, Not(IsEmpty()));
|
||||
EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "VP9")));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr));
|
||||
}
|
||||
|
||||
// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build
|
||||
// target remove this #ifdef.
|
||||
#if defined(WEBRTC_USE_H264)
|
||||
TEST(VideoDecoderFactoryTemplate, OpenH264) {
|
||||
VideoDecoderFactoryTemplate<OpenH264DecoderTemplateAdapter> factory;
|
||||
auto formats = factory.GetSupportedFormats();
|
||||
EXPECT_THAT(formats, Not(IsEmpty()));
|
||||
EXPECT_THAT(formats, Each(Field(&SdpVideoFormat::name, "H264")));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr));
|
||||
}
|
||||
#endif // defined(WEBRTC_USE_H264)
|
||||
|
||||
TEST(VideoDecoderFactoryTemplate, Dav1d) {
|
||||
VideoDecoderFactoryTemplate<Dav1dDecoderTemplateAdapter> factory;
|
||||
auto formats = factory.GetSupportedFormats();
|
||||
EXPECT_THAT(formats.size(), 1);
|
||||
EXPECT_THAT(formats[0], Field(&SdpVideoFormat::name, "AV1"));
|
||||
EXPECT_THAT(factory.CreateVideoDecoder(formats[0]), Ne(nullptr));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace webrtc
|
95
api/video_codecs/video_decoder_factory_template.h
Normal file
95
api/video_codecs/video_decoder_factory_template.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_
|
||||
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/algorithm/container.h"
|
||||
#include "api/array_view.h"
|
||||
#include "api/video_codecs/video_decoder.h"
|
||||
#include "api/video_codecs/video_decoder_factory.h"
|
||||
|
||||
namespace webrtc {
|
||||
// The VideoDecoderFactoryTemplate supports decoder implementations given as
|
||||
// template arguments.
|
||||
//
|
||||
// To include a decoder in the factory it requires two static members
|
||||
// functions to be defined:
|
||||
//
|
||||
// // Returns the supported SdpVideoFormats this decoder can decode.
|
||||
// static std::vector<SdpVideoFormat> SupportedFormats();
|
||||
//
|
||||
// // Creates a decoder instance for the given format.
|
||||
// static std::unique_ptr<VideoDecoder>
|
||||
// CreateDecoder(const SdpVideoFormat& format);
|
||||
//
|
||||
// Note that the order of the template arguments matter as the factory will
|
||||
// return the first decoder implementation supporting the given SdpVideoFormat.
|
||||
template <typename... Ts>
|
||||
class VideoDecoderFactoryTemplate : public VideoDecoderFactory {
|
||||
public:
|
||||
std::vector<SdpVideoFormat> GetSupportedFormats() const override {
|
||||
return GetSupportedFormatsInternal<Ts...>();
|
||||
}
|
||||
|
||||
std::unique_ptr<VideoDecoder> CreateVideoDecoder(
|
||||
const SdpVideoFormat& format) override {
|
||||
return CreateVideoDecoderInternal<Ts...>(format);
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsFormatInList(
|
||||
const SdpVideoFormat& format,
|
||||
rtc::ArrayView<const SdpVideoFormat> supported_formats) const {
|
||||
return absl::c_any_of(
|
||||
supported_formats, [&](const SdpVideoFormat& supported_format) {
|
||||
return supported_format.name == format.name &&
|
||||
supported_format.parameters == format.parameters;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename V, typename... Vs>
|
||||
std::vector<SdpVideoFormat> GetSupportedFormatsInternal() const {
|
||||
auto supported_formats = V::SupportedFormats();
|
||||
|
||||
if constexpr (sizeof...(Vs) > 0) {
|
||||
// Supported formats may overlap between implementations, so duplicates
|
||||
// should be filtered out.
|
||||
for (const auto& other_format : GetSupportedFormatsInternal<Vs...>()) {
|
||||
if (!IsFormatInList(other_format, supported_formats)) {
|
||||
supported_formats.push_back(other_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return supported_formats;
|
||||
}
|
||||
|
||||
template <typename V, typename... Vs>
|
||||
std::unique_ptr<VideoDecoder> CreateVideoDecoderInternal(
|
||||
const SdpVideoFormat& format) {
|
||||
if (IsFormatInList(format, V::SupportedFormats())) {
|
||||
return V::CreateDecoder(format);
|
||||
}
|
||||
|
||||
if constexpr (sizeof...(Vs) > 0) {
|
||||
return CreateVideoDecoderInternal<Vs...>(format);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_H_
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_
|
||||
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/video_coding/codecs/av1/dav1d_decoder.h"
|
||||
|
||||
namespace webrtc {
|
||||
struct Dav1dDecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() {
|
||||
return {SdpVideoFormat("AV1")};
|
||||
}
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return CreateDav1dDecoder();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_DAV1D_ADAPTER_H_
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_
|
||||
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/video_coding/codecs/vp8/include/vp8.h"
|
||||
|
||||
namespace webrtc {
|
||||
struct LibvpxVp8DecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() {
|
||||
return {SdpVideoFormat("VP8")};
|
||||
}
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return VP8Decoder::Create();
|
||||
}
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP8_ADAPTER_H_
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_
|
||||
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/video_coding/codecs/vp9/include/vp9.h"
|
||||
|
||||
namespace webrtc {
|
||||
struct LibvpxVp9DecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() {
|
||||
return SupportedVP9DecoderCodecs();
|
||||
}
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return VP9Decoder::Create();
|
||||
}
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_LIBVPX_VP9_ADAPTER_H_
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2022 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 API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_
|
||||
#define API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/video_coding/codecs/h264/include/h264.h"
|
||||
|
||||
namespace webrtc {
|
||||
// TODO(bugs.webrtc.org/13573): When OpenH264 is no longer a conditional build
|
||||
// target remove this #ifdef.
|
||||
#if defined(WEBRTC_USE_H264)
|
||||
struct OpenH264DecoderTemplateAdapter {
|
||||
static std::vector<SdpVideoFormat> SupportedFormats() {
|
||||
return SupportedH264DecoderCodecs();
|
||||
}
|
||||
|
||||
static std::unique_ptr<VideoDecoder> CreateDecoder(
|
||||
const SdpVideoFormat& format) {
|
||||
return H264Decoder::Create();
|
||||
}
|
||||
};
|
||||
#endif // defined(WEBRTC_USE_H264)
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // API_VIDEO_CODECS_VIDEO_DECODER_FACTORY_TEMPLATE_OPEN_H264_ADAPTER_H_
|
Loading…
Reference in a new issue