Remove libaom decoder wrapper and tests.
It's no longer needed since libaom is not going to be used for playback decoding. Bug: 1138574 Change-Id: I7c15c99ef9fb4bc3f0f9b5affed3631e7d2e1893 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2471839 Reviewed-by: Dale Curtis <dalecurtis@chromium.org> Commit-Queue: Jerome Jiang <jianj@google.com> Cr-Commit-Position: refs/heads/master@{#817229}
This commit is contained in:
media
@ -34,10 +34,6 @@
|
||||
#include "media/filters/vpx_video_decoder.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_LIBAOM)
|
||||
#include "media/filters/aom_video_decoder.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
#include "media/filters/dav1d_video_decoder.h"
|
||||
#endif
|
||||
@ -321,9 +317,6 @@ std::unique_ptr<CdmVideoDecoder> CreateVideoDecoder(
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
if (config.codec == cdm::kCodecAv1)
|
||||
video_decoder.reset(new Dav1dVideoDecoder(null_media_log.get()));
|
||||
#elif BUILDFLAG(ENABLE_LIBAOM)
|
||||
if (config.codec == cdm::kCodecAv1)
|
||||
video_decoder.reset(new AomVideoDecoder(null_media_log.get()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -140,14 +140,6 @@ source_set("filters") {
|
||||
deps += [ "//third_party/libvpx" ]
|
||||
}
|
||||
|
||||
if (enable_libaom) {
|
||||
sources += [
|
||||
"aom_video_decoder.cc",
|
||||
"aom_video_decoder.h",
|
||||
]
|
||||
deps += [ "//third_party/libaom" ]
|
||||
}
|
||||
|
||||
if (enable_dav1d_decoder) {
|
||||
sources += [
|
||||
"dav1d_video_decoder.cc",
|
||||
@ -383,10 +375,6 @@ source_set("unit_tests") {
|
||||
sources += [ "vpx_video_decoder_unittest.cc" ]
|
||||
}
|
||||
|
||||
if (enable_libaom) {
|
||||
sources += [ "aom_video_decoder_unittest.cc" ]
|
||||
}
|
||||
|
||||
if (enable_dav1d_decoder) {
|
||||
sources += [ "dav1d_video_decoder_unittest.cc" ]
|
||||
}
|
||||
|
@ -1,314 +0,0 @@
|
||||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "media/filters/aom_video_decoder.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "media/base/bind_to_current_loop.h"
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/media_log.h"
|
||||
#include "media/base/status.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "media/filters/frame_buffer_pool.h"
|
||||
#include "third_party/libyuv/include/libyuv/convert.h"
|
||||
|
||||
// Include libaom header files.
|
||||
extern "C" {
|
||||
#include "third_party/libaom/source/libaom/aom/aom_decoder.h"
|
||||
#include "third_party/libaom/source/libaom/aom/aom_frame_buffer.h"
|
||||
#include "third_party/libaom/source/libaom/aom/aomdx.h"
|
||||
}
|
||||
|
||||
namespace media {
|
||||
|
||||
// Returns the number of threads.
|
||||
static int GetAomVideoDecoderThreadCount(const VideoDecoderConfig& config) {
|
||||
// For AOM decode when using the default thread count, increase the number
|
||||
// of decode threads to equal the maximum number of tiles possible for
|
||||
// higher resolution streams.
|
||||
return VideoDecoder::GetRecommendedThreadCount(config.coded_size().width() /
|
||||
256);
|
||||
}
|
||||
|
||||
static VideoPixelFormat AomImgFmtToVideoPixelFormat(const aom_image_t* img) {
|
||||
switch (img->fmt) {
|
||||
case AOM_IMG_FMT_I420:
|
||||
return PIXEL_FORMAT_I420;
|
||||
case AOM_IMG_FMT_I422:
|
||||
return PIXEL_FORMAT_I422;
|
||||
case AOM_IMG_FMT_I444:
|
||||
return PIXEL_FORMAT_I444;
|
||||
|
||||
case AOM_IMG_FMT_I42016:
|
||||
switch (img->bit_depth) {
|
||||
case 10:
|
||||
return PIXEL_FORMAT_YUV420P10;
|
||||
case 12:
|
||||
return PIXEL_FORMAT_YUV420P12;
|
||||
default:
|
||||
DLOG(ERROR) << "Unsupported bit depth: " << img->bit_depth;
|
||||
return PIXEL_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
case AOM_IMG_FMT_I42216:
|
||||
switch (img->bit_depth) {
|
||||
case 10:
|
||||
return PIXEL_FORMAT_YUV422P10;
|
||||
case 12:
|
||||
return PIXEL_FORMAT_YUV422P12;
|
||||
default:
|
||||
DLOG(ERROR) << "Unsupported bit depth: " << img->bit_depth;
|
||||
return PIXEL_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
case AOM_IMG_FMT_I44416:
|
||||
switch (img->bit_depth) {
|
||||
case 10:
|
||||
return PIXEL_FORMAT_YUV444P10;
|
||||
case 12:
|
||||
return PIXEL_FORMAT_YUV444P12;
|
||||
default:
|
||||
DLOG(ERROR) << "Unsupported bit depth: " << img->bit_depth;
|
||||
return PIXEL_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
default:
|
||||
DLOG(ERROR) << "Unsupported pixel format: " << img->fmt;
|
||||
return PIXEL_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetColorSpaceForFrame(const aom_image_t* img,
|
||||
const VideoDecoderConfig& config,
|
||||
VideoFrame* frame) {
|
||||
gfx::ColorSpace::RangeID range = img->range == AOM_CR_FULL_RANGE
|
||||
? gfx::ColorSpace::RangeID::FULL
|
||||
: gfx::ColorSpace::RangeID::LIMITED;
|
||||
|
||||
// AOM color space defines match ISO 23001-8:2016 via ISO/IEC 23091-4/ITU-T
|
||||
// H.273.
|
||||
// http://av1-spec.argondesign.com/av1-spec/av1-spec.html#color-config-semantics
|
||||
media::VideoColorSpace color_space(img->cp, img->tc, img->mc, range);
|
||||
|
||||
// If the bitstream doesn't specify a color space, use the one from the
|
||||
// container.
|
||||
if (!color_space.IsSpecified())
|
||||
color_space = config.color_space_info();
|
||||
|
||||
frame->set_color_space(color_space.ToGfxColorSpace());
|
||||
}
|
||||
|
||||
static int GetFrameBuffer(void* cb_priv,
|
||||
size_t min_size,
|
||||
aom_codec_frame_buffer* fb) {
|
||||
DCHECK(cb_priv);
|
||||
DCHECK(fb);
|
||||
FrameBufferPool* pool = static_cast<FrameBufferPool*>(cb_priv);
|
||||
fb->data = pool->GetFrameBuffer(min_size, &fb->priv);
|
||||
fb->size = min_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ReleaseFrameBuffer(void* cb_priv, aom_codec_frame_buffer* fb) {
|
||||
DCHECK(cb_priv);
|
||||
DCHECK(fb);
|
||||
if (!fb->priv)
|
||||
return -1;
|
||||
|
||||
FrameBufferPool* pool = static_cast<FrameBufferPool*>(cb_priv);
|
||||
pool->ReleaseFrameBuffer(fb->priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AomVideoDecoder::AomVideoDecoder(MediaLog* media_log) : media_log_(media_log) {
|
||||
DETACH_FROM_THREAD(thread_checker_);
|
||||
}
|
||||
|
||||
AomVideoDecoder::~AomVideoDecoder() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
CloseDecoder();
|
||||
}
|
||||
|
||||
std::string AomVideoDecoder::GetDisplayName() const {
|
||||
return "AomVideoDecoder";
|
||||
}
|
||||
|
||||
void AomVideoDecoder::Initialize(const VideoDecoderConfig& config,
|
||||
bool /* low_delay */,
|
||||
CdmContext* /* cdm_context */,
|
||||
InitCB init_cb,
|
||||
const OutputCB& output_cb,
|
||||
const WaitingCB& /* waiting_cb */) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
DCHECK(config.IsValidConfig());
|
||||
|
||||
InitCB bound_init_cb = BindToCurrentLoop(std::move(init_cb));
|
||||
if (config.is_encrypted() || config.codec() != kCodecAV1) {
|
||||
std::move(bound_init_cb).Run(StatusCode::kDecoderFailedInitialization);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear any previously initialized decoder.
|
||||
CloseDecoder();
|
||||
|
||||
aom_codec_dec_cfg_t aom_config = {0};
|
||||
aom_config.w = config.coded_size().width();
|
||||
aom_config.h = config.coded_size().height();
|
||||
aom_config.threads = GetAomVideoDecoderThreadCount(config);
|
||||
|
||||
// Misleading name. Required to ensure libaom doesn't output 8-bit samples
|
||||
// in uint16_t containers. Without this we have to manually pack the values
|
||||
// into uint8_t samples.
|
||||
aom_config.allow_lowbitdepth = 1;
|
||||
|
||||
// TODO(dalecurtis, tguilbert): Move decoding off the media thread to the
|
||||
// offload thread via OffloadingVideoDecoder. https://crbug.com/867613
|
||||
|
||||
std::unique_ptr<aom_codec_ctx> context = std::make_unique<aom_codec_ctx>();
|
||||
if (aom_codec_dec_init(context.get(), aom_codec_av1_dx(), &aom_config,
|
||||
0 /* flags */) != AOM_CODEC_OK) {
|
||||
MEDIA_LOG(ERROR, media_log_) << "aom_codec_dec_init() failed: "
|
||||
<< aom_codec_error(aom_decoder_.get());
|
||||
std::move(bound_init_cb).Run(StatusCode::kDecoderFailedInitialization);
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup codec for zero copy frames.
|
||||
if (!memory_pool_)
|
||||
memory_pool_ = new FrameBufferPool();
|
||||
if (aom_codec_set_frame_buffer_functions(
|
||||
context.get(), &GetFrameBuffer, &ReleaseFrameBuffer,
|
||||
memory_pool_.get()) != AOM_CODEC_OK) {
|
||||
DLOG(ERROR) << "Failed to configure external buffers. "
|
||||
<< aom_codec_error(context.get());
|
||||
std::move(bound_init_cb).Run(StatusCode::kDecoderFailedInitialization);
|
||||
return;
|
||||
}
|
||||
|
||||
config_ = config;
|
||||
state_ = DecoderState::kNormal;
|
||||
output_cb_ = BindToCurrentLoop(output_cb);
|
||||
aom_decoder_ = std::move(context);
|
||||
std::move(bound_init_cb).Run(OkStatus());
|
||||
}
|
||||
|
||||
void AomVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
|
||||
DecodeCB decode_cb) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
DCHECK(buffer);
|
||||
DCHECK(decode_cb);
|
||||
DCHECK_NE(state_, DecoderState::kUninitialized)
|
||||
<< "Called Decode() before successful Initialize()";
|
||||
|
||||
DecodeCB bound_decode_cb = BindToCurrentLoop(std::move(decode_cb));
|
||||
|
||||
if (state_ == DecoderState::kError) {
|
||||
std::move(bound_decode_cb).Run(DecodeStatus::DECODE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to flush since we retrieve all available frames after a packet is
|
||||
// provided.
|
||||
if (buffer->end_of_stream()) {
|
||||
DCHECK_EQ(state_, DecoderState::kNormal);
|
||||
state_ = DecoderState::kDecodeFinished;
|
||||
std::move(bound_decode_cb).Run(DecodeStatus::OK);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!DecodeBuffer(buffer.get())) {
|
||||
state_ = DecoderState::kError;
|
||||
std::move(bound_decode_cb).Run(DecodeStatus::DECODE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// VideoDecoderShim expects |decode_cb| call after |output_cb_|.
|
||||
std::move(bound_decode_cb).Run(DecodeStatus::OK);
|
||||
}
|
||||
|
||||
void AomVideoDecoder::Reset(base::OnceClosure closure) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
state_ = DecoderState::kNormal;
|
||||
timestamps_.clear();
|
||||
base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
||||
std::move(closure));
|
||||
}
|
||||
|
||||
void AomVideoDecoder::CloseDecoder() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
if (!aom_decoder_)
|
||||
return;
|
||||
aom_codec_destroy(aom_decoder_.get());
|
||||
aom_decoder_.reset();
|
||||
|
||||
if (memory_pool_) {
|
||||
memory_pool_->Shutdown();
|
||||
memory_pool_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AomVideoDecoder::DecodeBuffer(const DecoderBuffer* buffer) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
DCHECK(!buffer->end_of_stream());
|
||||
|
||||
timestamps_.push_back(buffer->timestamp());
|
||||
if (aom_codec_decode(aom_decoder_.get(), buffer->data(), buffer->data_size(),
|
||||
nullptr) != AOM_CODEC_OK) {
|
||||
const char* detail = aom_codec_error_detail(aom_decoder_.get());
|
||||
MEDIA_LOG(ERROR, media_log_)
|
||||
<< "aom_codec_decode() failed: " << aom_codec_error(aom_decoder_.get())
|
||||
<< (detail ? ", " : "") << (detail ? detail : "")
|
||||
<< ", input: " << buffer->AsHumanReadableString();
|
||||
return false;
|
||||
}
|
||||
|
||||
aom_codec_iter_t iter = nullptr;
|
||||
while (aom_image_t* img = aom_codec_get_frame(aom_decoder_.get(), &iter)) {
|
||||
auto frame = CopyImageToVideoFrame(img);
|
||||
if (!frame) {
|
||||
MEDIA_LOG(DEBUG, media_log_)
|
||||
<< "Failed to produce video frame from aom_image_t.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(dalecurtis): Is this true even for low resolutions?
|
||||
frame->metadata()->power_efficient = false;
|
||||
|
||||
// Ensure the frame memory is returned to the MemoryPool upon discard.
|
||||
frame->AddDestructionObserver(
|
||||
memory_pool_->CreateFrameCallback(img->fb_priv));
|
||||
|
||||
SetColorSpaceForFrame(img, config_, frame.get());
|
||||
output_cb_.Run(std::move(frame));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
scoped_refptr<VideoFrame> AomVideoDecoder::CopyImageToVideoFrame(
|
||||
const struct aom_image* img) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
|
||||
VideoPixelFormat pixel_format = AomImgFmtToVideoPixelFormat(img);
|
||||
if (pixel_format == PIXEL_FORMAT_UNKNOWN)
|
||||
return nullptr;
|
||||
|
||||
// Pull the expected timestamp from the front of the queue.
|
||||
DCHECK(!timestamps_.empty());
|
||||
const base::TimeDelta timestamp = timestamps_.front();
|
||||
timestamps_.pop_front();
|
||||
|
||||
const gfx::Rect visible_rect(img->d_w, img->d_h);
|
||||
return VideoFrame::WrapExternalYuvData(
|
||||
pixel_format, visible_rect.size(), visible_rect,
|
||||
GetNaturalSize(visible_rect, config_.GetPixelAspectRatio()),
|
||||
img->stride[AOM_PLANE_Y], img->stride[AOM_PLANE_U],
|
||||
img->stride[AOM_PLANE_V], img->planes[AOM_PLANE_Y],
|
||||
img->planes[AOM_PLANE_U], img->planes[AOM_PLANE_V], timestamp);
|
||||
}
|
||||
|
||||
} // namespace media
|
@ -1,89 +0,0 @@
|
||||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef MEDIA_FILTERS_AOM_VIDEO_DECODER_H_
|
||||
#define MEDIA_FILTERS_AOM_VIDEO_DECODER_H_
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/containers/circular_deque.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/threading/thread_checker.h"
|
||||
#include "media/base/video_decoder.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_frame.h"
|
||||
|
||||
struct aom_codec_ctx;
|
||||
struct aom_image;
|
||||
|
||||
namespace media {
|
||||
class FrameBufferPool;
|
||||
class MediaLog;
|
||||
|
||||
// libaom video decoder wrapper.
|
||||
class MEDIA_EXPORT AomVideoDecoder : public VideoDecoder {
|
||||
public:
|
||||
explicit AomVideoDecoder(MediaLog* media_log);
|
||||
~AomVideoDecoder() override;
|
||||
|
||||
// VideoDecoder implementation.
|
||||
std::string GetDisplayName() const override;
|
||||
void Initialize(const VideoDecoderConfig& config,
|
||||
bool low_delay,
|
||||
CdmContext* cdm_context,
|
||||
InitCB init_cb,
|
||||
const OutputCB& output_cb,
|
||||
const WaitingCB& waiting_cb) override;
|
||||
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
|
||||
void Reset(base::OnceClosure closure) override;
|
||||
|
||||
private:
|
||||
enum class DecoderState {
|
||||
kUninitialized,
|
||||
kNormal,
|
||||
kFlushCodec,
|
||||
kDecodeFinished,
|
||||
kError
|
||||
};
|
||||
|
||||
// Releases any configured decoder and clears |aom_decoder_|.
|
||||
void CloseDecoder();
|
||||
|
||||
// Invokes the decoder and calls |output_cb_| for any returned frames.
|
||||
bool DecodeBuffer(const DecoderBuffer* buffer);
|
||||
|
||||
// Copies the contents of |img| into a new VideoFrame; attempts to reuse
|
||||
// previously allocated memory via |frame_pool_| for performance.
|
||||
scoped_refptr<VideoFrame> CopyImageToVideoFrame(const struct aom_image* img);
|
||||
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
|
||||
// Used to report error messages to the client.
|
||||
MediaLog* const media_log_;
|
||||
|
||||
// Current decoder state. Used to ensure methods are called as expected.
|
||||
DecoderState state_ = DecoderState::kUninitialized;
|
||||
|
||||
// Callback given during Initialize() used for delivering decoded frames.
|
||||
OutputCB output_cb_;
|
||||
|
||||
// The configuration passed to Initialize(), saved since some fields are
|
||||
// needed to annotate video frames after decoding.
|
||||
VideoDecoderConfig config_;
|
||||
|
||||
// Pool used for memory efficiency when vending frames from the decoder.
|
||||
scoped_refptr<FrameBufferPool> memory_pool_;
|
||||
|
||||
// Timestamps are FIFO for libaom decoding.
|
||||
base::circular_deque<base::TimeDelta> timestamps_;
|
||||
|
||||
// The allocated decoder; null before Initialize() and anytime after
|
||||
// CloseDecoder().
|
||||
std::unique_ptr<aom_codec_ctx> aom_decoder_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AomVideoDecoder);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
||||
#endif // MEDIA_FILTERS_AOM_VIDEO_DECODER_H_
|
@ -1,288 +0,0 @@
|
||||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "build/build_config.h"
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/limits.h"
|
||||
#include "media/base/mock_media_log.h"
|
||||
#include "media/base/test_data_util.h"
|
||||
#include "media/base/test_helpers.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/ffmpeg/ffmpeg_common.h"
|
||||
#include "media/filters/aom_video_decoder.h"
|
||||
#include "media/filters/in_memory_url_protocol.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
|
||||
using ::testing::_;
|
||||
|
||||
namespace media {
|
||||
|
||||
namespace {
|
||||
|
||||
MATCHER(ContainsDecoderErrorLog, "") {
|
||||
return CONTAINS_STRING(arg, "aom_codec_decode() failed");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class AomVideoDecoderTest : public testing::Test {
|
||||
public:
|
||||
AomVideoDecoderTest()
|
||||
: decoder_(new AomVideoDecoder(&media_log_)),
|
||||
i_frame_buffer_(ReadTestDataFile("av1-I-frame-320x240")) {}
|
||||
|
||||
~AomVideoDecoderTest() override { Destroy(); }
|
||||
|
||||
void Initialize() {
|
||||
InitializeWithConfig(TestVideoConfig::Normal(kCodecAV1));
|
||||
}
|
||||
|
||||
void InitializeWithConfigWithResult(const VideoDecoderConfig& config,
|
||||
bool success) {
|
||||
decoder_->Initialize(config, false, nullptr,
|
||||
base::BindOnce(
|
||||
[](bool success, Status status) {
|
||||
EXPECT_EQ(status.is_ok(), success);
|
||||
},
|
||||
success),
|
||||
base::BindRepeating(&AomVideoDecoderTest::FrameReady,
|
||||
base::Unretained(this)),
|
||||
base::NullCallback());
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
void InitializeWithConfig(const VideoDecoderConfig& config) {
|
||||
InitializeWithConfigWithResult(config, true);
|
||||
}
|
||||
|
||||
void Reinitialize() {
|
||||
InitializeWithConfig(TestVideoConfig::Large(kCodecAV1));
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
decoder_->Reset(NewExpectedClosure());
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
void Destroy() {
|
||||
decoder_.reset();
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
// Sets up expectations and actions to put AomVideoDecoder in an active
|
||||
// decoding state.
|
||||
void ExpectDecodingState() {
|
||||
EXPECT_EQ(DecodeStatus::OK, DecodeSingleFrame(i_frame_buffer_));
|
||||
ASSERT_EQ(1U, output_frames_.size());
|
||||
}
|
||||
|
||||
// Sets up expectations and actions to put AomVideoDecoder in an end
|
||||
// of stream state.
|
||||
void ExpectEndOfStreamState() {
|
||||
EXPECT_EQ(DecodeStatus::OK,
|
||||
DecodeSingleFrame(DecoderBuffer::CreateEOSBuffer()));
|
||||
ASSERT_FALSE(output_frames_.empty());
|
||||
}
|
||||
|
||||
using InputBuffers = std::vector<scoped_refptr<DecoderBuffer>>;
|
||||
using OutputFrames = std::vector<scoped_refptr<VideoFrame>>;
|
||||
|
||||
// Decodes all buffers in |input_buffers| and push all successfully decoded
|
||||
// output frames into |output_frames|. Returns the last decode status returned
|
||||
// by the decoder.
|
||||
DecodeStatus DecodeMultipleFrames(const InputBuffers& input_buffers) {
|
||||
for (auto iter = input_buffers.begin(); iter != input_buffers.end();
|
||||
++iter) {
|
||||
DecodeStatus status = Decode(*iter);
|
||||
switch (status) {
|
||||
case DecodeStatus::OK:
|
||||
break;
|
||||
case DecodeStatus::ABORTED:
|
||||
NOTREACHED();
|
||||
FALLTHROUGH;
|
||||
case DecodeStatus::DECODE_ERROR:
|
||||
DCHECK(output_frames_.empty());
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return DecodeStatus::OK;
|
||||
}
|
||||
|
||||
// Decodes the single compressed frame in |buffer|.
|
||||
DecodeStatus DecodeSingleFrame(scoped_refptr<DecoderBuffer> buffer) {
|
||||
InputBuffers input_buffers;
|
||||
input_buffers.push_back(std::move(buffer));
|
||||
return DecodeMultipleFrames(input_buffers);
|
||||
}
|
||||
|
||||
// Decodes |i_frame_buffer_| and then decodes the data contained in the file
|
||||
// named |test_file_name|. This function expects both buffers to decode to
|
||||
// frames that are the same size.
|
||||
void DecodeIFrameThenTestFile(const std::string& test_file_name,
|
||||
const gfx::Size& expected_size) {
|
||||
Initialize();
|
||||
scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(test_file_name);
|
||||
|
||||
InputBuffers input_buffers;
|
||||
input_buffers.push_back(i_frame_buffer_);
|
||||
input_buffers.push_back(buffer);
|
||||
input_buffers.push_back(DecoderBuffer::CreateEOSBuffer());
|
||||
|
||||
DecodeStatus status = DecodeMultipleFrames(input_buffers);
|
||||
|
||||
EXPECT_EQ(DecodeStatus::OK, status);
|
||||
ASSERT_EQ(2U, output_frames_.size());
|
||||
|
||||
gfx::Size original_size = TestVideoConfig::NormalCodedSize();
|
||||
EXPECT_EQ(original_size.width(),
|
||||
output_frames_[0]->visible_rect().size().width());
|
||||
EXPECT_EQ(original_size.height(),
|
||||
output_frames_[0]->visible_rect().size().height());
|
||||
EXPECT_EQ(expected_size.width(),
|
||||
output_frames_[1]->visible_rect().size().width());
|
||||
EXPECT_EQ(expected_size.height(),
|
||||
output_frames_[1]->visible_rect().size().height());
|
||||
}
|
||||
|
||||
DecodeStatus Decode(scoped_refptr<DecoderBuffer> buffer) {
|
||||
DecodeStatus status;
|
||||
EXPECT_CALL(*this, DecodeDone(_)).WillOnce(testing::SaveArg<0>(&status));
|
||||
|
||||
decoder_->Decode(std::move(buffer),
|
||||
base::BindOnce(&AomVideoDecoderTest::DecodeDone,
|
||||
base::Unretained(this)));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void FrameReady(scoped_refptr<VideoFrame> frame) {
|
||||
DCHECK(!frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM));
|
||||
output_frames_.push_back(std::move(frame));
|
||||
}
|
||||
|
||||
MOCK_METHOD1(DecodeDone, void(DecodeStatus));
|
||||
|
||||
testing::StrictMock<MockMediaLog> media_log_;
|
||||
|
||||
base::test::SingleThreadTaskEnvironment task_environment_;
|
||||
std::unique_ptr<AomVideoDecoder> decoder_;
|
||||
|
||||
scoped_refptr<DecoderBuffer> i_frame_buffer_;
|
||||
OutputFrames output_frames_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AomVideoDecoderTest);
|
||||
};
|
||||
|
||||
TEST_F(AomVideoDecoderTest, Initialize_Normal) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
TEST_F(AomVideoDecoderTest, Reinitialize_Normal) {
|
||||
Initialize();
|
||||
Reinitialize();
|
||||
}
|
||||
|
||||
TEST_F(AomVideoDecoderTest, Reinitialize_AfterDecodeFrame) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
Reinitialize();
|
||||
}
|
||||
|
||||
TEST_F(AomVideoDecoderTest, Reinitialize_AfterReset) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
Reset();
|
||||
Reinitialize();
|
||||
}
|
||||
|
||||
TEST_F(AomVideoDecoderTest, DecodeFrame_Normal) {
|
||||
Initialize();
|
||||
|
||||
// Simulate decoding a single frame.
|
||||
EXPECT_EQ(DecodeStatus::OK, DecodeSingleFrame(i_frame_buffer_));
|
||||
ASSERT_EQ(1U, output_frames_.size());
|
||||
}
|
||||
|
||||
// Decode |i_frame_buffer_| and then a frame with a larger width and verify
|
||||
// the output size was adjusted.
|
||||
// TODO(dalecurtis): Get an I-frame from a larger video.
|
||||
TEST_F(AomVideoDecoderTest, DISABLED_DecodeFrame_LargerWidth) {
|
||||
DecodeIFrameThenTestFile("av1-I-frame-320x240", gfx::Size(1280, 720));
|
||||
}
|
||||
|
||||
// Decode a VP9 frame which should trigger a decoder error.
|
||||
TEST_F(AomVideoDecoderTest, DecodeFrame_Error) {
|
||||
Initialize();
|
||||
EXPECT_MEDIA_LOG(ContainsDecoderErrorLog());
|
||||
DecodeSingleFrame(ReadTestDataFile("vp9-I-frame-320x240"));
|
||||
}
|
||||
|
||||
// Test resetting when decoder has initialized but not decoded.
|
||||
TEST_F(AomVideoDecoderTest, Reset_Initialized) {
|
||||
Initialize();
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Test resetting when decoder has decoded single frame.
|
||||
TEST_F(AomVideoDecoderTest, Reset_Decoding) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Test resetting when decoder has hit end of stream.
|
||||
TEST_F(AomVideoDecoderTest, Reset_EndOfStream) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
ExpectEndOfStreamState();
|
||||
Reset();
|
||||
}
|
||||
|
||||
// Test destruction when decoder has initialized but not decoded.
|
||||
TEST_F(AomVideoDecoderTest, Destroy_Initialized) {
|
||||
Initialize();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// Test destruction when decoder has decoded single frame.
|
||||
TEST_F(AomVideoDecoderTest, Destroy_Decoding) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// Test destruction when decoder has hit end of stream.
|
||||
TEST_F(AomVideoDecoderTest, Destroy_EndOfStream) {
|
||||
Initialize();
|
||||
ExpectDecodingState();
|
||||
ExpectEndOfStreamState();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
TEST_F(AomVideoDecoderTest, FrameValidAfterPoolDestruction) {
|
||||
Initialize();
|
||||
Decode(i_frame_buffer_);
|
||||
Destroy();
|
||||
|
||||
ASSERT_FALSE(output_frames_.empty());
|
||||
|
||||
// Write to the Y plane. The memory tools should detect a
|
||||
// use-after-free if the storage was actually removed by pool destruction.
|
||||
memset(output_frames_.front()->data(VideoFrame::kYPlane), 0xff,
|
||||
output_frames_.front()->rows(VideoFrame::kYPlane) *
|
||||
output_frames_.front()->stride(VideoFrame::kYPlane));
|
||||
}
|
||||
|
||||
} // namespace media
|
@ -102,7 +102,7 @@ declare_args() {
|
||||
|
||||
declare_args() {
|
||||
enable_av1_decoder =
|
||||
enable_dav1d_decoder || enable_libaom || enable_libgav1_decoder
|
||||
enable_dav1d_decoder || enable_libgav1_decoder
|
||||
}
|
||||
|
||||
# enable_hls_sample_aes can only be true if enable_mse_mpeg2ts_stream_parser is.
|
||||
|
@ -30,10 +30,6 @@
|
||||
#include "media/filters/fuchsia/fuchsia_video_decoder.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_LIBAOM)
|
||||
#include "media/filters/aom_video_decoder.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
#include "media/filters/dav1d_video_decoder.h"
|
||||
#endif
|
||||
@ -161,8 +157,6 @@ void DefaultDecoderFactory::CreateVideoDecoders(
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
video_decoders->push_back(
|
||||
std::make_unique<OffloadingDav1dVideoDecoder>(media_log));
|
||||
#elif BUILDFLAG(ENABLE_LIBAOM)
|
||||
video_decoders->push_back(std::make_unique<AomVideoDecoder>(media_log));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,6 @@
|
||||
#include "media/test/test_media_source.h"
|
||||
#include "third_party/libaom/libaom_buildflags.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_LIBAOM)
|
||||
#include "media/filters/aom_video_decoder.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
#include "media/filters/dav1d_video_decoder.h"
|
||||
#endif
|
||||
@ -89,8 +85,6 @@ static std::vector<std::unique_ptr<VideoDecoder>> CreateVideoDecodersForTest(
|
||||
#if BUILDFLAG(ENABLE_DAV1D_DECODER)
|
||||
video_decoders.push_back(
|
||||
std::make_unique<OffloadingDav1dVideoDecoder>(media_log));
|
||||
#elif BUILDFLAG(ENABLE_LIBAOM)
|
||||
video_decoders.push_back(std::make_unique<AomVideoDecoder>(media_log));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user