123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- // Copyright 2020 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 <cstring>
- #include <memory>
- #include <string>
- #include "base/check.h"
- #include "base/containers/queue.h"
- #include "base/containers/span.h"
- #include "base/files/file_util.h"
- #include "base/memory/raw_ptr.h"
- #include "media/base/test_data_util.h"
- #include "media/gpu/h265_decoder.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::_;
- using ::testing::Args;
- using ::testing::Expectation;
- using ::testing::InSequence;
- using ::testing::Invoke;
- using ::testing::MakeMatcher;
- using ::testing::Matcher;
- using ::testing::MatcherInterface;
- using ::testing::MatchResultListener;
- using ::testing::Mock;
- using ::testing::Return;
- using ::testing::WithArg;
- namespace media {
- namespace {
- constexpr char kSpsPps[] = "bear-sps-pps.hevc";
- constexpr char kFrame0[] = "bear-frame0.hevc";
- constexpr char kFrame1[] = "bear-frame1.hevc";
- constexpr char kFrame2[] = "bear-frame2.hevc";
- constexpr char kFrame3[] = "bear-frame3.hevc";
- constexpr char kFrame4[] = "bear-frame4.hevc";
- constexpr char kFrame5[] = "bear-frame5.hevc";
- constexpr char k10BitFrame0[] = "bear-320x180-10bit-frame-0.hevc";
- constexpr char k10BitFrame1[] = "bear-320x180-10bit-frame-1.hevc";
- constexpr char k10BitFrame2[] = "bear-320x180-10bit-frame-2.hevc";
- constexpr char k10BitFrame3[] = "bear-320x180-10bit-frame-3.hevc";
- constexpr char kYUV444Frame[] = "blackwhite_yuv444p-frame.hevc";
- // Checks whether the decrypt config in the picture matches the decrypt config
- // passed to this matcher.
- MATCHER_P(DecryptConfigMatches, decrypt_config, "") {
- return arg->decrypt_config()->Matches(*decrypt_config);
- }
- MATCHER(SubsampleSizeMatches, "Verify subsample sizes match buffer size") {
- const size_t buffer_size = ::testing::get<0>(arg);
- const std::vector<SubsampleEntry>& subsamples = ::testing::get<1>(arg);
- size_t subsample_total_size = 0;
- for (const auto& sample : subsamples) {
- subsample_total_size += sample.cypher_bytes;
- subsample_total_size += sample.clear_bytes;
- }
- return subsample_total_size == buffer_size;
- }
- // To have better description on mismatch.
- class HasPocMatcher : public MatcherInterface<scoped_refptr<H265Picture>> {
- public:
- explicit HasPocMatcher(int expected_poc) : expected_poc_(expected_poc) {}
- bool MatchAndExplain(scoped_refptr<H265Picture> p,
- MatchResultListener* listener) const override {
- if (p->pic_order_cnt_val_ == expected_poc_)
- return true;
- *listener << "with poc: " << p->pic_order_cnt_val_;
- return false;
- }
- void DescribeTo(std::ostream* os) const override {
- *os << "with poc " << expected_poc_;
- }
- private:
- int expected_poc_;
- };
- Matcher<scoped_refptr<H265Picture>> HasPoc(int expected_poc) {
- return MakeMatcher(new HasPocMatcher(expected_poc));
- }
- } // namespace
- class MockH265Accelerator : public H265Decoder::H265Accelerator {
- public:
- MockH265Accelerator() = default;
- MOCK_METHOD0(CreateH265Picture, scoped_refptr<H265Picture>());
- MOCK_METHOD5(SubmitFrameMetadata,
- Status(const H265SPS* sps,
- const H265PPS* pps,
- const H265SliceHeader* slice_hdr,
- const H265Picture::Vector& ref_pic_list,
- scoped_refptr<H265Picture> pic));
- MOCK_METHOD(Status,
- SubmitSlice,
- (const H265SPS* sps,
- const H265PPS* pps,
- const H265SliceHeader* slice_hdr,
- const H265Picture::Vector& ref_pic_list0,
- const H265Picture::Vector& ref_pic_list1,
- const H265Picture::Vector& ref_pic_set_lt_curr,
- const H265Picture::Vector& ref_pic_set_st_curr_after,
- const H265Picture::Vector& ref_pic_set_st_curr_before,
- scoped_refptr<H265Picture> pic,
- const uint8_t* data,
- size_t size,
- const std::vector<SubsampleEntry>& subsamples));
- MOCK_METHOD1(SubmitDecode, Status(scoped_refptr<H265Picture> pic));
- MOCK_METHOD1(OutputPicture, bool(scoped_refptr<H265Picture>));
- MOCK_METHOD2(SetStream,
- Status(base::span<const uint8_t> stream,
- const DecryptConfig* decrypt_config));
- bool IsChromaSamplingSupported(VideoChromaSampling format) override {
- return format == VideoChromaSampling::k420;
- }
- void Reset() override {}
- };
- // Test H265Decoder by feeding different h265 frame sequences and make sure it
- // behaves as expected.
- class H265DecoderTest : public ::testing::Test {
- public:
- H265DecoderTest() = default;
- void SetUp() override;
- // Sets the bitstreams to be decoded, frame by frame. The content of each
- // file is the encoded bitstream of a single video frame.
- void SetInputFrameFiles(const std::vector<std::string>& frame_files);
- // Keeps decoding the input bitstream set at |SetInputFrameFiles| until the
- // decoder has consumed all bitstreams or returned from
- // |H265Decoder::Decode|. Returns the same result as |H265Decoder::Decode|.
- // If |set_stream_expect| is true, it will setup EXPECT_CALL for SetStream.
- AcceleratedVideoDecoder::DecodeResult Decode(bool set_stream_expect = true);
- protected:
- std::unique_ptr<H265Decoder> decoder_;
- raw_ptr<MockH265Accelerator> accelerator_;
- private:
- base::queue<std::string> input_frame_files_;
- std::string bitstream_;
- scoped_refptr<DecoderBuffer> decoder_buffer_;
- };
- void H265DecoderTest::SetUp() {
- auto mock_accelerator = std::make_unique<MockH265Accelerator>();
- accelerator_ = mock_accelerator.get();
- decoder_.reset(new H265Decoder(std::move(mock_accelerator),
- VIDEO_CODEC_PROFILE_UNKNOWN));
- // Sets default behaviors for mock methods for convenience.
- ON_CALL(*accelerator_, CreateH265Picture()).WillByDefault(Invoke([]() {
- return new H265Picture();
- }));
- ON_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _))
- .WillByDefault(Return(H265Decoder::H265Accelerator::Status::kOk));
- ON_CALL(*accelerator_, SubmitDecode(_))
- .WillByDefault(Return(H265Decoder::H265Accelerator::Status::kOk));
- ON_CALL(*accelerator_, OutputPicture(_)).WillByDefault(Return(true));
- ON_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .With(Args<10, 11>(SubsampleSizeMatches()))
- .WillByDefault(Return(H265Decoder::H265Accelerator::Status::kOk));
- ON_CALL(*accelerator_, SetStream(_, _))
- .WillByDefault(
- Return(H265Decoder::H265Accelerator::Status::kNotSupported));
- }
- void H265DecoderTest::SetInputFrameFiles(
- const std::vector<std::string>& input_frame_files) {
- for (auto f : input_frame_files)
- input_frame_files_.push(f);
- }
- AcceleratedVideoDecoder::DecodeResult H265DecoderTest::Decode(
- bool set_stream_expect) {
- while (true) {
- auto result = decoder_->Decode();
- int32_t bitstream_id = 0;
- if (result != AcceleratedVideoDecoder::kRanOutOfStreamData ||
- input_frame_files_.empty())
- return result;
- auto input_file = GetTestDataFilePath(input_frame_files_.front());
- input_frame_files_.pop();
- CHECK(base::ReadFileToString(input_file, &bitstream_));
- decoder_buffer_ = DecoderBuffer::CopyFrom(
- reinterpret_cast<const uint8_t*>(bitstream_.data()), bitstream_.size());
- EXPECT_NE(decoder_buffer_.get(), nullptr);
- if (set_stream_expect)
- EXPECT_CALL(*accelerator_, SetStream(_, _));
- decoder_->SetStream(bitstream_id++, *decoder_buffer_);
- }
- }
- TEST_F(H265DecoderTest, DecodeSingleFrame) {
- SetInputFrameFiles({kSpsPps, kFrame0});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- // Also test running out of surfaces.
- EXPECT_CALL(*accelerator_, CreateH265Picture()).WillOnce(Return(nullptr));
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfSurfaces, Decode());
- EXPECT_TRUE(Mock::VerifyAndClearExpectations(&*accelerator_));
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(1);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(1);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(1);
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0))).Times(1);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0)));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, SkipNonIDRFrames) {
- SetInputFrameFiles({kSpsPps, kFrame1, kFrame2, kFrame0});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(1);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(1);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(1);
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0))).Times(1);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0)));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, DecodeProfileMain) {
- SetInputFrameFiles(
- {kSpsPps, kFrame0, kFrame1, kFrame2, kFrame3, kFrame4, kFrame5});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(6);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(6);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(6);
- Expectation decode_poc0, decode_poc1, decode_poc2, decode_poc3, decode_poc4,
- decode_poc8;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(4)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(2)));
- decode_poc1 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(1)));
- decode_poc3 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(3)));
- decode_poc8 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(8)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(1))).After(decode_poc1);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(3))).After(decode_poc3);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(8))).After(decode_poc8);
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, Decode10BitStream) {
- SetInputFrameFiles({k10BitFrame0, k10BitFrame1, k10BitFrame2, k10BitFrame3});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(gfx::Rect(320, 180), decoder_->GetVisibleRect());
- EXPECT_EQ(HEVCPROFILE_MAIN10, decoder_->GetProfile());
- EXPECT_EQ(10u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(4);
- // Two pictures will be kept in the DPB for reordering. The second and third
- // pictures should be outputted after feeding the fourth frame.
- Expectation decode_poc0, decode_poc1, decode_poc2, decode_poc3;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)));
- decode_poc3 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(3)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(2)));
- decode_poc1 = EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(1)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(1))).After(decode_poc1);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(3))).After(decode_poc3);
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, DenyDecodeNonYUV420) {
- // YUV444 frame causes kDecodeError.
- SetInputFrameFiles({kYUV444Frame});
- ASSERT_EQ(AcceleratedVideoDecoder::kDecodeError, Decode());
- }
- TEST_F(H265DecoderTest, OutputPictureFailureCausesDecodeToFail) {
- // Provide enough data that Decode() will try to output a frame.
- SetInputFrameFiles({kSpsPps, kFrame0, kFrame1, kFrame2, kFrame3});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(3);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(3);
- EXPECT_CALL(*accelerator_, SubmitDecode(_)).Times(3);
- EXPECT_CALL(*accelerator_, OutputPicture(_)).WillRepeatedly(Return(false));
- EXPECT_EQ(AcceleratedVideoDecoder::kDecodeError, Decode());
- }
- // Verify that the decryption config is passed to the accelerator.
- TEST_F(H265DecoderTest, SetEncryptedStream) {
- std::string bitstream, bitstream1, bitstream2;
- auto input_file1 = GetTestDataFilePath(kSpsPps);
- CHECK(base::ReadFileToString(input_file1, &bitstream1));
- auto input_file2 = GetTestDataFilePath(kFrame0);
- CHECK(base::ReadFileToString(input_file2, &bitstream2));
- bitstream = bitstream1 + bitstream2;
- const char kAnyKeyId[] = "any_16byte_keyid";
- const char kAnyIv[] = "any_16byte_iv___";
- const std::vector<SubsampleEntry> subsamples = {
- // No encrypted bytes. This test only checks whether the data is passed
- // thru to the acclerator so making this completely clear.
- {static_cast<uint32_t>(bitstream.size()), 0},
- };
- std::unique_ptr<DecryptConfig> decrypt_config =
- DecryptConfig::CreateCencConfig(kAnyKeyId, kAnyIv, subsamples);
- EXPECT_CALL(*accelerator_,
- SubmitFrameMetadata(_, _, _, _,
- DecryptConfigMatches(decrypt_config.get())))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kOk));
- EXPECT_CALL(*accelerator_,
- SubmitDecode(DecryptConfigMatches(decrypt_config.get())))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kOk));
- auto buffer = DecoderBuffer::CopyFrom(
- reinterpret_cast<const uint8_t*>(bitstream.data()), bitstream.size());
- ASSERT_NE(buffer.get(), nullptr);
- buffer->set_decrypt_config(std::move(decrypt_config));
- decoder_->SetStream(0, *buffer);
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, decoder_->Decode());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, decoder_->Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, SubmitFrameMetadataRetry) {
- SetInputFrameFiles({kSpsPps, kFrame0});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitFrameMetadata()
- // should be called again.
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Assume key has been provided now, next call to Decode() should proceed.
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0)));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, SubmitSliceRetry) {
- SetInputFrameFiles({kSpsPps, kFrame0});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitSlice() should be
- // called again.
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Assume key has been provided now, next call to Decode() should proceed.
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0)));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, SubmitDecodeRetry) {
- SetInputFrameFiles({kSpsPps, kFrame0, kFrame1});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitDecode() should be
- // called again.
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(0);
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain));
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Assume key has been provided now, next call to Decode() should output
- // the first frame.
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0)));
- EXPECT_CALL(*accelerator_, CreateH265Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(4)));
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(4)));
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, SetStreamRetry) {
- SetInputFrameFiles({kSpsPps, kFrame0});
- EXPECT_CALL(*accelerator_, SetStream(_, _))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kTryAgain))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kOk))
- .WillOnce(Return(H265Decoder::H265Accelerator::Status::kOk));
- EXPECT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode(false));
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode(false));
- EXPECT_EQ(gfx::Size(320, 184), decoder_->GetPicSize());
- EXPECT_EQ(HEVCPROFILE_MAIN, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(17u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH265Picture()).Times(1);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _)).Times(1);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _, _, _, _, _))
- .Times(1);
- EXPECT_CALL(*accelerator_, SubmitDecode(HasPoc(0))).Times(1);
- EXPECT_CALL(*accelerator_, OutputPicture(HasPoc(0))).Times(1);
- }
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode(false));
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H265DecoderTest, DecodeMultiFrameInput) {
- SetInputFrameFiles({"bear.hevc"});
- EXPECT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- } // namespace media
|