Migrate software decoders to new VideoDecoder::Configure
Bug: webrtc:13045 Change-Id: I1fa28a7c2dd59f0889d98c8ec5f58161c0ec9f95 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/228380 Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#34716}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
bf75041b8d
commit
53d4be223b
@ -17,7 +17,6 @@
|
|||||||
#include "api/scoped_refptr.h"
|
#include "api/scoped_refptr.h"
|
||||||
#include "api/video/encoded_image.h"
|
#include "api/video/encoded_image.h"
|
||||||
#include "api/video/i420_buffer.h"
|
#include "api/video/i420_buffer.h"
|
||||||
#include "api/video_codecs/video_codec.h"
|
|
||||||
#include "api/video_codecs/video_decoder.h"
|
#include "api/video_codecs/video_decoder.h"
|
||||||
#include "common_video/include/video_frame_buffer_pool.h"
|
#include "common_video/include/video_frame_buffer_pool.h"
|
||||||
#include "modules/video_coding/include/video_error_codes.h"
|
#include "modules/video_coding/include/video_error_codes.h"
|
||||||
@ -40,8 +39,7 @@ class LibaomAv1Decoder final : public VideoDecoder {
|
|||||||
~LibaomAv1Decoder();
|
~LibaomAv1Decoder();
|
||||||
|
|
||||||
// Implements VideoDecoder.
|
// Implements VideoDecoder.
|
||||||
int32_t InitDecode(const VideoCodec* codec_settings,
|
bool Configure(const Settings& settings) override;
|
||||||
int number_of_cores) override;
|
|
||||||
|
|
||||||
// Decode an encoded video frame.
|
// Decode an encoded video frame.
|
||||||
int32_t Decode(const EncodedImage& encoded_image,
|
int32_t Decode(const EncodedImage& encoded_image,
|
||||||
@ -74,23 +72,20 @@ LibaomAv1Decoder::~LibaomAv1Decoder() {
|
|||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t LibaomAv1Decoder::InitDecode(const VideoCodec* codec_settings,
|
bool LibaomAv1Decoder::Configure(const Settings& settings) {
|
||||||
int number_of_cores) {
|
aom_codec_dec_cfg_t config = {};
|
||||||
aom_codec_dec_cfg_t config = {
|
config.threads = static_cast<unsigned int>(settings.number_of_cores());
|
||||||
static_cast<unsigned int>(number_of_cores), // Max # of threads.
|
config.allow_lowbitdepth = kConfigLowBitDepth;
|
||||||
0, // Frame width set after decode.
|
|
||||||
0, // Frame height set after decode.
|
|
||||||
kConfigLowBitDepth}; // Enable low-bit-depth code path.
|
|
||||||
|
|
||||||
aom_codec_err_t ret =
|
aom_codec_err_t ret =
|
||||||
aom_codec_dec_init(&context_, aom_codec_av1_dx(), &config, kDecFlags);
|
aom_codec_dec_init(&context_, aom_codec_av1_dx(), &config, kDecFlags);
|
||||||
if (ret != AOM_CODEC_OK) {
|
if (ret != AOM_CODEC_OK) {
|
||||||
RTC_LOG(LS_WARNING) << "LibaomAv1Decoder::InitDecode returned " << ret
|
RTC_LOG(LS_WARNING) << "LibaomAv1Decoder::Configure returned " << ret
|
||||||
<< " on aom_codec_dec_init.";
|
<< " on aom_codec_dec_init.";
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
inited_ = true;
|
inited_ = true;
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t LibaomAv1Decoder::Decode(const EncodedImage& encoded_image,
|
int32_t LibaomAv1Decoder::Decode(const EncodedImage& encoded_image,
|
||||||
|
|||||||
@ -77,9 +77,7 @@ class TestAv1Decoder {
|
|||||||
ADD_FAILURE() << "Failed to create a decoder#" << decoder_id_;
|
ADD_FAILURE() << "Failed to create a decoder#" << decoder_id_;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EXPECT_EQ(decoder_->InitDecode(/*codec_settings=*/nullptr,
|
EXPECT_TRUE(decoder_->Configure({}));
|
||||||
/*number_of_cores=*/1),
|
|
||||||
WEBRTC_VIDEO_CODEC_OK);
|
|
||||||
EXPECT_EQ(decoder_->RegisterDecodeCompleteCallback(&callback_),
|
EXPECT_EQ(decoder_->RegisterDecodeCompleteCallback(&callback_),
|
||||||
WEBRTC_VIDEO_CODEC_OK);
|
WEBRTC_VIDEO_CODEC_OK);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,9 +69,9 @@ ScopedAVPacket MakeScopedAVPacket() {
|
|||||||
int H264DecoderImpl::AVGetBuffer2(AVCodecContext* context,
|
int H264DecoderImpl::AVGetBuffer2(AVCodecContext* context,
|
||||||
AVFrame* av_frame,
|
AVFrame* av_frame,
|
||||||
int flags) {
|
int flags) {
|
||||||
// Set in `InitDecode`.
|
// Set in `Configure`.
|
||||||
H264DecoderImpl* decoder = static_cast<H264DecoderImpl*>(context->opaque);
|
H264DecoderImpl* decoder = static_cast<H264DecoderImpl*>(context->opaque);
|
||||||
// DCHECK values set in `InitDecode`.
|
// DCHECK values set in `Configure`.
|
||||||
RTC_DCHECK(decoder);
|
RTC_DCHECK(decoder);
|
||||||
// Necessary capability to be allowed to provide our own buffers.
|
// Necessary capability to be allowed to provide our own buffers.
|
||||||
RTC_DCHECK(context->codec->capabilities | AV_CODEC_CAP_DR1);
|
RTC_DCHECK(context->codec->capabilities | AV_CODEC_CAP_DR1);
|
||||||
@ -172,19 +172,18 @@ H264DecoderImpl::~H264DecoderImpl() {
|
|||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
bool H264DecoderImpl::Configure(const Settings& settings) {
|
||||||
int32_t number_of_cores) {
|
|
||||||
ReportInit();
|
ReportInit();
|
||||||
if (codec_settings && codec_settings->codecType != kVideoCodecH264) {
|
if (settings.codec_type() != kVideoCodecH264) {
|
||||||
ReportError();
|
ReportError();
|
||||||
return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release necessary in case of re-initializing.
|
// Release necessary in case of re-initializing.
|
||||||
int32_t ret = Release();
|
int32_t ret = Release();
|
||||||
if (ret != WEBRTC_VIDEO_CODEC_OK) {
|
if (ret != WEBRTC_VIDEO_CODEC_OK) {
|
||||||
ReportError();
|
ReportError();
|
||||||
return ret;
|
return false;
|
||||||
}
|
}
|
||||||
RTC_DCHECK(!av_context_);
|
RTC_DCHECK(!av_context_);
|
||||||
|
|
||||||
@ -193,9 +192,10 @@ int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
|||||||
|
|
||||||
av_context_->codec_type = AVMEDIA_TYPE_VIDEO;
|
av_context_->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
av_context_->codec_id = AV_CODEC_ID_H264;
|
av_context_->codec_id = AV_CODEC_ID_H264;
|
||||||
if (codec_settings) {
|
const RenderResolution& resolution = settings.max_render_resolution();
|
||||||
av_context_->coded_width = codec_settings->width;
|
if (resolution.Valid()) {
|
||||||
av_context_->coded_height = codec_settings->height;
|
av_context_->coded_width = resolution.Width();
|
||||||
|
av_context_->coded_height = resolution.Height();
|
||||||
}
|
}
|
||||||
av_context_->pix_fmt = kPixelFormatDefault;
|
av_context_->pix_fmt = kPixelFormatDefault;
|
||||||
av_context_->extradata = nullptr;
|
av_context_->extradata = nullptr;
|
||||||
@ -219,25 +219,25 @@ int32_t H264DecoderImpl::InitDecode(const VideoCodec* codec_settings,
|
|||||||
RTC_LOG(LS_ERROR) << "FFmpeg H.264 decoder not found.";
|
RTC_LOG(LS_ERROR) << "FFmpeg H.264 decoder not found.";
|
||||||
Release();
|
Release();
|
||||||
ReportError();
|
ReportError();
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
int res = avcodec_open2(av_context_.get(), codec, nullptr);
|
int res = avcodec_open2(av_context_.get(), codec, nullptr);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
RTC_LOG(LS_ERROR) << "avcodec_open2 error: " << res;
|
RTC_LOG(LS_ERROR) << "avcodec_open2 error: " << res;
|
||||||
Release();
|
Release();
|
||||||
ReportError();
|
ReportError();
|
||||||
return WEBRTC_VIDEO_CODEC_ERROR;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
av_frame_.reset(av_frame_alloc());
|
av_frame_.reset(av_frame_alloc());
|
||||||
|
|
||||||
if (codec_settings && codec_settings->buffer_pool_size) {
|
if (absl::optional<int> buffer_pool_size = settings.buffer_pool_size()) {
|
||||||
if (!ffmpeg_buffer_pool_.Resize(*codec_settings->buffer_pool_size) ||
|
if (!ffmpeg_buffer_pool_.Resize(*buffer_pool_size) ||
|
||||||
!output_buffer_pool_.Resize(*codec_settings->buffer_pool_size)) {
|
!output_buffer_pool_.Resize(*buffer_pool_size)) {
|
||||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t H264DecoderImpl::Release() {
|
int32_t H264DecoderImpl::Release() {
|
||||||
@ -261,7 +261,7 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
|
|||||||
}
|
}
|
||||||
if (!decoded_image_callback_) {
|
if (!decoded_image_callback_) {
|
||||||
RTC_LOG(LS_WARNING)
|
RTC_LOG(LS_WARNING)
|
||||||
<< "InitDecode() has been called, but a callback function "
|
<< "Configure() has been called, but a callback function "
|
||||||
"has not been set with RegisterDecodeCompleteCallback()";
|
"has not been set with RegisterDecodeCompleteCallback()";
|
||||||
ReportError();
|
ReportError();
|
||||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||||
|
|||||||
@ -60,10 +60,7 @@ class H264DecoderImpl : public H264Decoder {
|
|||||||
H264DecoderImpl();
|
H264DecoderImpl();
|
||||||
~H264DecoderImpl() override;
|
~H264DecoderImpl() override;
|
||||||
|
|
||||||
// If `codec_settings` is NULL it is ignored. If it is not NULL,
|
bool Configure(const Settings& settings) override;
|
||||||
// `codec_settings->codecType` must be `kVideoCodecH264`.
|
|
||||||
int32_t InitDecode(const VideoCodec* codec_settings,
|
|
||||||
int32_t number_of_cores) override;
|
|
||||||
int32_t Release() override;
|
int32_t Release() override;
|
||||||
|
|
||||||
int32_t RegisterDecodeCompleteCallback(
|
int32_t RegisterDecodeCompleteCallback(
|
||||||
|
|||||||
@ -31,8 +31,7 @@ class MultiplexDecoderAdapter : public VideoDecoder {
|
|||||||
virtual ~MultiplexDecoderAdapter();
|
virtual ~MultiplexDecoderAdapter();
|
||||||
|
|
||||||
// Implements VideoDecoder
|
// Implements VideoDecoder
|
||||||
int32_t InitDecode(const VideoCodec* codec_settings,
|
bool Configure(const Settings& settings) override;
|
||||||
int32_t number_of_cores) override;
|
|
||||||
int32_t Decode(const EncodedImage& input_image,
|
int32_t Decode(const EncodedImage& input_image,
|
||||||
bool missing_frames,
|
bool missing_frames,
|
||||||
int64_t render_time_ms) override;
|
int64_t render_time_ms) override;
|
||||||
|
|||||||
@ -104,24 +104,24 @@ MultiplexDecoderAdapter::~MultiplexDecoderAdapter() {
|
|||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MultiplexDecoderAdapter::InitDecode(const VideoCodec* codec_settings,
|
bool MultiplexDecoderAdapter::Configure(const Settings& settings) {
|
||||||
int32_t number_of_cores) {
|
RTC_DCHECK_EQ(settings.codec_type(), kVideoCodecMultiplex);
|
||||||
RTC_DCHECK_EQ(kVideoCodecMultiplex, codec_settings->codecType);
|
Settings associated_settings = settings;
|
||||||
VideoCodec settings = *codec_settings;
|
associated_settings.set_codec_type(
|
||||||
settings.codecType = PayloadStringToCodecType(associated_format_.name);
|
PayloadStringToCodecType(associated_format_.name));
|
||||||
for (size_t i = 0; i < kAlphaCodecStreams; ++i) {
|
for (size_t i = 0; i < kAlphaCodecStreams; ++i) {
|
||||||
std::unique_ptr<VideoDecoder> decoder =
|
std::unique_ptr<VideoDecoder> decoder =
|
||||||
factory_->CreateVideoDecoder(associated_format_);
|
factory_->CreateVideoDecoder(associated_format_);
|
||||||
const int32_t rv = decoder->InitDecode(&settings, number_of_cores);
|
if (!decoder->Configure(associated_settings)) {
|
||||||
if (rv)
|
return false;
|
||||||
return rv;
|
}
|
||||||
adapter_callbacks_.emplace_back(
|
adapter_callbacks_.emplace_back(
|
||||||
new MultiplexDecoderAdapter::AdapterDecodedImageCallback(
|
new MultiplexDecoderAdapter::AdapterDecodedImageCallback(
|
||||||
this, static_cast<AlphaCodecStream>(i)));
|
this, static_cast<AlphaCodecStream>(i)));
|
||||||
decoder->RegisterDecodeCompleteCallback(adapter_callbacks_.back().get());
|
decoder->RegisterDecodeCompleteCallback(adapter_callbacks_.back().get());
|
||||||
decoders_.emplace_back(std::move(decoder));
|
decoders_.emplace_back(std::move(decoder));
|
||||||
}
|
}
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t MultiplexDecoderAdapter::Decode(const EncodedImage& input_image,
|
int32_t MultiplexDecoderAdapter::Decode(const EncodedImage& input_image,
|
||||||
|
|||||||
@ -87,8 +87,12 @@ void VideoCodecUnitTest::SetUp() {
|
|||||||
&codec_settings_,
|
&codec_settings_,
|
||||||
VideoEncoder::Settings(kCapabilities, 1 /* number of cores */,
|
VideoEncoder::Settings(kCapabilities, 1 /* number of cores */,
|
||||||
0 /* max payload size (unused) */)));
|
0 /* max payload size (unused) */)));
|
||||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
|
||||||
decoder_->InitDecode(&codec_settings_, 1 /* number of cores */));
|
VideoDecoder::Settings decoder_settings;
|
||||||
|
decoder_settings.set_codec_type(codec_settings_.codecType);
|
||||||
|
decoder_settings.set_max_render_resolution(
|
||||||
|
{codec_settings_.width, codec_settings_.height});
|
||||||
|
EXPECT_TRUE(decoder_->Configure(decoder_settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoCodecUnitTest::ModifyCodecSettings(VideoCodec* codec_settings) {}
|
void VideoCodecUnitTest::ModifyCodecSettings(VideoCodec* codec_settings) {}
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#elif defined(WEBRTC_IOS)
|
#elif defined(WEBRTC_IOS)
|
||||||
#include "modules/video_coding/codecs/test/objc_codec_factory_helper.h"
|
#include "modules/video_coding/codecs/test/objc_codec_factory_helper.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "test/gmock.h"
|
||||||
#include "test/gtest.h"
|
#include "test/gtest.h"
|
||||||
#include "test/video_codec_settings.h"
|
#include "test/video_codec_settings.h"
|
||||||
|
|
||||||
@ -28,6 +29,9 @@ namespace webrtc {
|
|||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using ::testing::NotNull;
|
||||||
|
|
||||||
const VideoEncoder::Capabilities kCapabilities(false);
|
const VideoEncoder::Capabilities kCapabilities(false);
|
||||||
|
|
||||||
int32_t InitEncoder(VideoCodecType codec_type, VideoEncoder* encoder) {
|
int32_t InitEncoder(VideoCodecType codec_type, VideoEncoder* encoder) {
|
||||||
@ -42,14 +46,11 @@ int32_t InitEncoder(VideoCodecType codec_type, VideoEncoder* encoder) {
|
|||||||
1200 /* max_payload_size */));
|
1200 /* max_payload_size */));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t InitDecoder(VideoCodecType codec_type, VideoDecoder* decoder) {
|
VideoDecoder::Settings DecoderSettings(VideoCodecType codec_type) {
|
||||||
VideoCodec codec;
|
VideoDecoder::Settings settings;
|
||||||
CodecSettings(codec_type, &codec);
|
settings.set_max_render_resolution({640, 480});
|
||||||
codec.width = 640;
|
settings.set_codec_type(codec_type);
|
||||||
codec.height = 480;
|
return settings;
|
||||||
codec.maxFramerate = 30;
|
|
||||||
RTC_CHECK(decoder);
|
|
||||||
return decoder->InitDecode(&codec, 1 /* number_of_cores */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -126,7 +127,8 @@ TEST_P(VideoEncoderDecoderInstantiationTest, DISABLED_InstantiateVp8Codecs) {
|
|||||||
for (int i = 0; i < num_decoders_; ++i) {
|
for (int i = 0; i < num_decoders_; ++i) {
|
||||||
std::unique_ptr<VideoDecoder> decoder =
|
std::unique_ptr<VideoDecoder> decoder =
|
||||||
decoder_factory_->CreateVideoDecoder(vp8_format_);
|
decoder_factory_->CreateVideoDecoder(vp8_format_);
|
||||||
EXPECT_EQ(0, InitDecoder(kVideoCodecVP8, decoder.get()));
|
ASSERT_THAT(decoder, NotNull());
|
||||||
|
EXPECT_TRUE(decoder->Configure(DecoderSettings(kVideoCodecVP8)));
|
||||||
decoders_.emplace_back(std::move(decoder));
|
decoders_.emplace_back(std::move(decoder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -143,8 +145,9 @@ TEST_P(VideoEncoderDecoderInstantiationTest,
|
|||||||
for (int i = 0; i < num_decoders_; ++i) {
|
for (int i = 0; i < num_decoders_; ++i) {
|
||||||
std::unique_ptr<VideoDecoder> decoder =
|
std::unique_ptr<VideoDecoder> decoder =
|
||||||
decoder_factory_->CreateVideoDecoder(h264cbp_format_);
|
decoder_factory_->CreateVideoDecoder(h264cbp_format_);
|
||||||
EXPECT_EQ(0, InitDecoder(kVideoCodecH264, decoder.get()));
|
ASSERT_THAT(decoder, NotNull());
|
||||||
decoders_.emplace_back(std::move(decoder));
|
EXPECT_TRUE(decoder->Configure(DecoderSettings(kVideoCodecH264)));
|
||||||
|
decoders_.push_back(std::move(decoder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -138,10 +138,9 @@ LibvpxVp8Decoder::~LibvpxVp8Decoder() {
|
|||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvpxVp8Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
bool LibvpxVp8Decoder::Configure(const Settings& settings) {
|
||||||
int ret_val = Release();
|
if (Release() < 0) {
|
||||||
if (ret_val < 0) {
|
return false;
|
||||||
return ret_val;
|
|
||||||
}
|
}
|
||||||
if (decoder_ == NULL) {
|
if (decoder_ == NULL) {
|
||||||
decoder_ = new vpx_codec_ctx_t;
|
decoder_ = new vpx_codec_ctx_t;
|
||||||
@ -157,7 +156,7 @@ int LibvpxVp8Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
|||||||
if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) {
|
if (vpx_codec_dec_init(decoder_, vpx_codec_vp8_dx(), &cfg, flags)) {
|
||||||
delete decoder_;
|
delete decoder_;
|
||||||
decoder_ = nullptr;
|
decoder_ = nullptr;
|
||||||
return WEBRTC_VIDEO_CODEC_MEMORY;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
propagation_cnt_ = -1;
|
propagation_cnt_ = -1;
|
||||||
@ -165,12 +164,12 @@ int LibvpxVp8Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
|||||||
|
|
||||||
// Always start with a complete key frame.
|
// Always start with a complete key frame.
|
||||||
key_frame_required_ = true;
|
key_frame_required_ = true;
|
||||||
if (inst && inst->buffer_pool_size) {
|
if (absl::optional<int> buffer_pool_size = settings.buffer_pool_size()) {
|
||||||
if (!buffer_pool_.Resize(*inst->buffer_pool_size)) {
|
if (!buffer_pool_.Resize(*buffer_pool_size)) {
|
||||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvpxVp8Decoder::Decode(const EncodedImage& input_image,
|
int LibvpxVp8Decoder::Decode(const EncodedImage& input_image,
|
||||||
|
|||||||
@ -29,8 +29,7 @@ class LibvpxVp8Decoder : public VideoDecoder {
|
|||||||
LibvpxVp8Decoder();
|
LibvpxVp8Decoder();
|
||||||
~LibvpxVp8Decoder() override;
|
~LibvpxVp8Decoder() override;
|
||||||
|
|
||||||
int InitDecode(const VideoCodec* inst, int number_of_cores) override;
|
bool Configure(const Settings& settings) override;
|
||||||
|
|
||||||
int Decode(const EncodedImage& input_image,
|
int Decode(const EncodedImage& input_image,
|
||||||
bool missing_frames,
|
bool missing_frames,
|
||||||
int64_t /*render_time_ms*/) override;
|
int64_t /*render_time_ms*/) override;
|
||||||
|
|||||||
@ -244,10 +244,9 @@ TEST_F(TestVp8Impl, EncodeI420FrameAfterNv12Frame) {
|
|||||||
encoder_->Encode(NextInputFrame(), nullptr));
|
encoder_->Encode(NextInputFrame(), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVp8Impl, InitDecode) {
|
TEST_F(TestVp8Impl, Configure) {
|
||||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
|
||||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
EXPECT_TRUE(decoder_->Configure({}));
|
||||||
decoder_->InitDecode(&codec_settings_, kNumCores));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVp8Impl, OnEncodedImageReportsInfo) {
|
TEST_F(TestVp8Impl, OnEncodedImageReportsInfo) {
|
||||||
|
|||||||
@ -120,10 +120,9 @@ LibvpxVp9Decoder::~LibvpxVp9Decoder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvpxVp9Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
bool LibvpxVp9Decoder::Configure(const Settings& settings) {
|
||||||
int ret_val = Release();
|
if (Release() < 0) {
|
||||||
if (ret_val < 0) {
|
return false;
|
||||||
return ret_val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decoder_ == nullptr) {
|
if (decoder_ == nullptr) {
|
||||||
@ -140,9 +139,9 @@ int LibvpxVp9Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
|||||||
// - Make peak CPU usage under control (not depending on input)
|
// - Make peak CPU usage under control (not depending on input)
|
||||||
cfg.threads = 1;
|
cfg.threads = 1;
|
||||||
#else
|
#else
|
||||||
if (!inst) {
|
const RenderResolution& resolution = settings.max_render_resolution();
|
||||||
// No config provided - don't know resolution to decode yet.
|
if (!resolution.Valid()) {
|
||||||
// Set thread count to one in the meantime.
|
// Postpone configuring number of threads until resolution is known.
|
||||||
cfg.threads = 1;
|
cfg.threads = 1;
|
||||||
} else {
|
} else {
|
||||||
// We want to use multithreading when decoding high resolution videos. But
|
// We want to use multithreading when decoding high resolution videos. But
|
||||||
@ -156,31 +155,30 @@ int LibvpxVp9Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
|||||||
// 4 for 1080p
|
// 4 for 1080p
|
||||||
// 8 for 1440p
|
// 8 for 1440p
|
||||||
// 18 for 4K
|
// 18 for 4K
|
||||||
int num_threads =
|
int num_threads = std::max(
|
||||||
std::max(1, 2 * (inst->width * inst->height) / (1280 * 720));
|
1, 2 * resolution.Width() * resolution.Height() / (1280 * 720));
|
||||||
cfg.threads = std::min(number_of_cores, num_threads);
|
cfg.threads = std::min(settings.number_of_cores(), num_threads);
|
||||||
current_codec_ = *inst;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
num_cores_ = number_of_cores;
|
current_settings_ = settings;
|
||||||
|
|
||||||
vpx_codec_flags_t flags = 0;
|
vpx_codec_flags_t flags = 0;
|
||||||
if (vpx_codec_dec_init(decoder_, vpx_codec_vp9_dx(), &cfg, flags)) {
|
if (vpx_codec_dec_init(decoder_, vpx_codec_vp9_dx(), &cfg, flags)) {
|
||||||
return WEBRTC_VIDEO_CODEC_MEMORY;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!libvpx_buffer_pool_.InitializeVpxUsePool(decoder_)) {
|
if (!libvpx_buffer_pool_.InitializeVpxUsePool(decoder_)) {
|
||||||
return WEBRTC_VIDEO_CODEC_MEMORY;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inited_ = true;
|
inited_ = true;
|
||||||
// Always start with a complete key frame.
|
// Always start with a complete key frame.
|
||||||
key_frame_required_ = true;
|
key_frame_required_ = true;
|
||||||
if (inst && inst->buffer_pool_size) {
|
if (absl::optional<int> buffer_pool_size = settings.buffer_pool_size()) {
|
||||||
if (!libvpx_buffer_pool_.Resize(*inst->buffer_pool_size) ||
|
if (!libvpx_buffer_pool_.Resize(*buffer_pool_size) ||
|
||||||
!output_buffer_pool_.Resize(*inst->buffer_pool_size)) {
|
!output_buffer_pool_.Resize(*buffer_pool_size)) {
|
||||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +187,10 @@ int LibvpxVp9Decoder::InitDecode(const VideoCodec* inst, int number_of_cores) {
|
|||||||
if (status != VPX_CODEC_OK) {
|
if (status != VPX_CODEC_OK) {
|
||||||
RTC_LOG(LS_ERROR) << "Failed to enable VP9D_SET_LOOP_FILTER_OPT. "
|
RTC_LOG(LS_ERROR) << "Failed to enable VP9D_SET_LOOP_FILTER_OPT. "
|
||||||
<< vpx_codec_error(decoder_);
|
<< vpx_codec_error(decoder_);
|
||||||
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return WEBRTC_VIDEO_CODEC_OK;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LibvpxVp9Decoder::Decode(const EncodedImage& input_image,
|
int LibvpxVp9Decoder::Decode(const EncodedImage& input_image,
|
||||||
@ -209,17 +207,16 @@ int LibvpxVp9Decoder::Decode(const EncodedImage& input_image,
|
|||||||
absl::optional<vp9::FrameInfo> frame_info =
|
absl::optional<vp9::FrameInfo> frame_info =
|
||||||
vp9::ParseIntraFrameInfo(input_image.data(), input_image.size());
|
vp9::ParseIntraFrameInfo(input_image.data(), input_image.size());
|
||||||
if (frame_info) {
|
if (frame_info) {
|
||||||
if (frame_info->frame_width != current_codec_.width ||
|
RenderResolution frame_resolution(frame_info->frame_width,
|
||||||
frame_info->frame_height != current_codec_.height) {
|
frame_info->frame_height);
|
||||||
|
if (frame_resolution != current_settings_.max_render_resolution()) {
|
||||||
// Resolution has changed, tear down and re-init a new decoder in
|
// Resolution has changed, tear down and re-init a new decoder in
|
||||||
// order to get correct sizing.
|
// order to get correct sizing.
|
||||||
Release();
|
Release();
|
||||||
current_codec_.width = frame_info->frame_width;
|
current_settings_.set_max_render_resolution(frame_resolution);
|
||||||
current_codec_.height = frame_info->frame_height;
|
if (!Configure(current_settings_)) {
|
||||||
int reinit_status = InitDecode(¤t_codec_, num_cores_);
|
|
||||||
if (reinit_status != WEBRTC_VIDEO_CODEC_OK) {
|
|
||||||
RTC_LOG(LS_WARNING) << "Failed to re-init decoder.";
|
RTC_LOG(LS_WARNING) << "Failed to re-init decoder.";
|
||||||
return reinit_status;
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class LibvpxVp9Decoder : public VP9Decoder {
|
|||||||
|
|
||||||
virtual ~LibvpxVp9Decoder();
|
virtual ~LibvpxVp9Decoder();
|
||||||
|
|
||||||
int InitDecode(const VideoCodec* inst, int number_of_cores) override;
|
bool Configure(const Settings& settings) override;
|
||||||
|
|
||||||
int Decode(const EncodedImage& input_image,
|
int Decode(const EncodedImage& input_image,
|
||||||
bool missing_frames,
|
bool missing_frames,
|
||||||
@ -57,8 +57,7 @@ class LibvpxVp9Decoder : public VP9Decoder {
|
|||||||
bool inited_;
|
bool inited_;
|
||||||
vpx_codec_ctx_t* decoder_;
|
vpx_codec_ctx_t* decoder_;
|
||||||
bool key_frame_required_;
|
bool key_frame_required_;
|
||||||
VideoCodec current_codec_;
|
Settings current_settings_;
|
||||||
int num_cores_;
|
|
||||||
|
|
||||||
// Decoder should produce this format if possible.
|
// Decoder should produce this format if possible.
|
||||||
const VideoFrameBuffer::Type preferred_output_format_;
|
const VideoFrameBuffer::Type preferred_output_format_;
|
||||||
|
|||||||
@ -2168,11 +2168,10 @@ TEST_F(TestVp9Impl, ReenablingUpperLayerAfterKFWithInterlayerPredIsEnabled) {
|
|||||||
EXPECT_EQ(encoded_frames[0]._frameType, VideoFrameType::kVideoFrameDelta);
|
EXPECT_EQ(encoded_frames[0]._frameType, VideoFrameType::kVideoFrameDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(TestVp9Impl, HandlesEmptyInitDecode) {
|
TEST_F(TestVp9Impl, HandlesEmptyDecoderConfigure) {
|
||||||
std::unique_ptr<VideoDecoder> decoder = CreateDecoder();
|
std::unique_ptr<VideoDecoder> decoder = CreateDecoder();
|
||||||
// Check that nullptr settings are ok for decoder.
|
// Check that default settings are ok for decoder.
|
||||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
EXPECT_TRUE(decoder->Configure({}));
|
||||||
decoder->InitDecode(/*codec_settings=*/nullptr, 1));
|
|
||||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder->Release());
|
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder->Release());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user