123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- // 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 <stdint.h>
- #include <string.h>
- #include <cstring>
- #include <memory>
- #include <string>
- #include "base/check.h"
- #include "base/command_line.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/h264_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::MakeMatcher;
- using ::testing::Matcher;
- using ::testing::MatcherInterface;
- using ::testing::MatchResultListener;
- using ::testing::Mock;
- using ::testing::Return;
- namespace media {
- namespace {
- const std::string kBaselineFrame0 = "bear-320x192-baseline-frame-0.h264";
- const std::string kBaselineFrame1 = "bear-320x192-baseline-frame-1.h264";
- const std::string kBaselineFrame2 = "bear-320x192-baseline-frame-2.h264";
- const std::string kBaselineFrame3 = "bear-320x192-baseline-frame-3.h264";
- const std::string kHighFrame0 = "bear-320x192-high-frame-0.h264";
- const std::string kHighFrame1 = "bear-320x192-high-frame-1.h264";
- const std::string kHighFrame2 = "bear-320x192-high-frame-2.h264";
- const std::string kHighFrame3 = "bear-320x192-high-frame-3.h264";
- const std::string k10BitFrame0 = "bear-320x180-10bit-frame-0.h264";
- const std::string k10BitFrame1 = "bear-320x180-10bit-frame-1.h264";
- const std::string k10BitFrame2 = "bear-320x180-10bit-frame-2.h264";
- const std::string k10BitFrame3 = "bear-320x180-10bit-frame-3.h264";
- const std::string kYUV444Frame = "blackwhite_yuv444p-frame.h264";
- // 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;
- }
- // Emulates encrypted slice header parsing. We don't actually encrypt the data
- // so we can easily do this by just parsing it.
- H264Decoder::H264Accelerator::Status ParseSliceHeader(
- const std::vector<base::span<const uint8_t>>& data,
- const std::vector<SubsampleEntry>& subsamples,
- const std::vector<uint8_t>& sps_nalu_data,
- const std::vector<uint8_t>& pps_nalu_data,
- H264SliceHeader* slice_hdr_out) {
- // Construct the bitstream for parsing.
- std::vector<uint8_t> full_data;
- const std::vector<uint8_t> start_code = {0u, 0u, 1u};
- full_data.insert(full_data.end(), start_code.begin(), start_code.end());
- full_data.insert(full_data.end(), sps_nalu_data.begin(), sps_nalu_data.end());
- full_data.insert(full_data.end(), start_code.begin(), start_code.end());
- full_data.insert(full_data.end(), pps_nalu_data.begin(), pps_nalu_data.end());
- for (const auto& span : data) {
- full_data.insert(full_data.end(), start_code.begin(), start_code.end());
- full_data.insert(full_data.end(), span.begin(), span.end());
- }
- H264Parser parser;
- parser.SetStream(full_data.data(), full_data.size());
- while (true) {
- H264NALU nalu;
- H264Parser::Result res = parser.AdvanceToNextNALU(&nalu);
- if (res == H264Parser::kEOStream)
- break;
- EXPECT_EQ(H264Parser::kOk, res);
- switch (nalu.nal_unit_type) {
- case H264NALU::kSPS:
- int sps_id;
- EXPECT_EQ(H264Parser::kOk, parser.ParseSPS(&sps_id));
- break;
- case H264NALU::kPPS:
- int pps_id;
- EXPECT_EQ(H264Parser::kOk, parser.ParsePPS(&pps_id));
- break;
- case H264NALU::kIDRSlice: // fallthrough
- case H264NALU::kNonIDRSlice:
- EXPECT_EQ(H264Parser::kOk,
- parser.ParseSliceHeader(nalu, slice_hdr_out));
- slice_hdr_out->full_sample_encryption = true;
- break;
- }
- }
- return H264Decoder::H264Accelerator::Status::kOk;
- }
- class MockH264Accelerator : public H264Decoder::H264Accelerator {
- public:
- MockH264Accelerator() = default;
- MOCK_METHOD0(CreateH264Picture, scoped_refptr<H264Picture>());
- MOCK_METHOD1(SubmitDecode, Status(scoped_refptr<H264Picture> pic));
- MOCK_METHOD3(ParseEncryptedSliceHeader,
- Status(const std::vector<base::span<const uint8_t>>& data,
- const std::vector<SubsampleEntry>& subsamples,
- H264SliceHeader* slice_hdr_out));
- MOCK_METHOD7(SubmitFrameMetadata,
- Status(const H264SPS* sps,
- const H264PPS* pps,
- const H264DPB& dpb,
- const H264Picture::Vector& ref_pic_listp0,
- const H264Picture::Vector& ref_pic_listb0,
- const H264Picture::Vector& ref_pic_listb1,
- scoped_refptr<H264Picture> pic));
- MOCK_METHOD8(SubmitSlice,
- Status(const H264PPS* pps,
- const H264SliceHeader* slice_hdr,
- const H264Picture::Vector& ref_pic_list0,
- const H264Picture::Vector& ref_pic_list1,
- scoped_refptr<H264Picture> pic,
- const uint8_t* data,
- size_t size,
- const std::vector<SubsampleEntry>& subsamples));
- MOCK_METHOD1(OutputPicture, bool(scoped_refptr<H264Picture> pic));
- MOCK_METHOD2(SetStream,
- Status(base::span<const uint8_t> stream,
- const DecryptConfig* decrypt_config));
- void Reset() override {}
- void ProcessSPS(const H264SPS* sps,
- base::span<const uint8_t> sps_nalu_data) override {
- last_sps_nalu_data.assign(sps_nalu_data.begin(), sps_nalu_data.end());
- }
- void ProcessPPS(const H264PPS* pps,
- base::span<const uint8_t> pps_nalu_data) override {
- last_pps_nalu_data.assign(pps_nalu_data.begin(), pps_nalu_data.end());
- }
- std::vector<uint8_t> last_sps_nalu_data;
- std::vector<uint8_t> last_pps_nalu_data;
- };
- // Test H264Decoder by feeding different of h264 frame sequences and make
- // sure it behaves as expected.
- class H264DecoderTest : public ::testing::Test {
- public:
- H264DecoderTest() = 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
- // |H264Decoder::Decode|. If |full_sample_encryption| is true, then it sets
- // a DecryptConfig for the the DecoderBuffer that indicates all but the first
- // byte are encrypted. Returns the same result as |H264Decoder::Decode|.
- AcceleratedVideoDecoder::DecodeResult Decode(
- bool full_sample_encryption = false);
- protected:
- std::unique_ptr<H264Decoder> decoder_;
- raw_ptr<MockH264Accelerator> accelerator_;
- private:
- base::queue<std::string> input_frame_files_;
- std::string bitstream_;
- scoped_refptr<DecoderBuffer> decoder_buffer_;
- };
- void H264DecoderTest::SetUp() {
- auto mock_accelerator = std::make_unique<MockH264Accelerator>();
- accelerator_ = mock_accelerator.get();
- decoder_ = std::make_unique<H264Decoder>(std::move(mock_accelerator),
- VIDEO_CODEC_PROFILE_UNKNOWN);
- // Sets default behaviors for mock methods for convenience.
- ON_CALL(*accelerator_, CreateH264Picture()).WillByDefault([]() {
- return new H264Picture();
- });
- ON_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _))
- .WillByDefault(Return(H264Decoder::H264Accelerator::Status::kOk));
- ON_CALL(*accelerator_, SubmitDecode(_))
- .WillByDefault(Return(H264Decoder::H264Accelerator::Status::kOk));
- ON_CALL(*accelerator_, OutputPicture(_)).WillByDefault(Return(true));
- ON_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _))
- .With(Args<6, 7>(SubsampleSizeMatches()))
- .WillByDefault(Return(H264Decoder::H264Accelerator::Status::kOk));
- ON_CALL(*accelerator_, SetStream(_, _))
- .WillByDefault(
- Return(H264Decoder::H264Accelerator::Status::kNotSupported));
- }
- void H264DecoderTest::SetInputFrameFiles(
- const std::vector<std::string>& input_frame_files) {
- for (auto f : input_frame_files)
- input_frame_files_.push(f);
- }
- AcceleratedVideoDecoder::DecodeResult H264DecoderTest::Decode(
- bool full_sample_encryption) {
- 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());
- if (full_sample_encryption) {
- // We only use this in 2 tests, each use the same data where the offset to
- // the byte after the NALU type for the slice header is 669.
- constexpr int kOffsetToSliceHeader = 669;
- decoder_buffer_->set_decrypt_config(DecryptConfig::CreateCencConfig(
- "kFakeKeyId", std::string(DecryptConfig::kDecryptionKeySize, 'x'),
- {SubsampleEntry(kOffsetToSliceHeader,
- bitstream_.size() - kOffsetToSliceHeader)}));
- }
- EXPECT_NE(decoder_buffer_.get(), nullptr);
- decoder_->SetStream(bitstream_id++, *decoder_buffer_);
- }
- }
- // To have better description on mismatch.
- class WithPocMatcher : public MatcherInterface<scoped_refptr<H264Picture>> {
- public:
- explicit WithPocMatcher(int expected_poc) : expected_poc_(expected_poc) {}
- bool MatchAndExplain(scoped_refptr<H264Picture> p,
- MatchResultListener* listener) const override {
- if (p->pic_order_cnt == expected_poc_)
- return true;
- *listener << "with poc: " << p->pic_order_cnt;
- return false;
- }
- void DescribeTo(std::ostream* os) const override {
- *os << "with poc " << expected_poc_;
- }
- private:
- int expected_poc_;
- };
- inline Matcher<scoped_refptr<H264Picture>> WithPoc(int expected_poc) {
- return MakeMatcher(new WithPocMatcher(expected_poc));
- }
- // Test Cases
- TEST_F(H264DecoderTest, DecodeSingleFrame) {
- SetInputFrameFiles({kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- EXPECT_CALL(*accelerator_, CreateH264Picture()).WillOnce(Return(nullptr));
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfSurfaces, Decode());
- ASSERT_TRUE(Mock::VerifyAndClearExpectations(&*accelerator_));
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(_));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- // This is for CENCv1 full sample encryption.
- TEST_F(H264DecoderTest, DecodeSingleEncryptedFrame) {
- SetInputFrameFiles({kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode(true));
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, ParseEncryptedSliceHeader(_, _, _))
- .WillOnce([this](const std::vector<base::span<const uint8_t>>& data,
- const std::vector<SubsampleEntry>& subsamples,
- H264SliceHeader* slice_hdr_out) {
- return ParseSliceHeader(
- data, subsamples, accelerator_->last_sps_nalu_data,
- accelerator_->last_pps_nalu_data, slice_hdr_out);
- });
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(_));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SkipNonIDRFrames) {
- SetInputFrameFiles({kBaselineFrame1, kBaselineFrame2, kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, DecodeProfileBaseline) {
- SetInputFrameFiles({
- kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, kBaselineFrame3,
- });
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(4);
- Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(4)));
- decode_poc6 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(6)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, Decode10BitStream) {
- SetInputFrameFiles({k10BitFrame0, k10BitFrame1, k10BitFrame2, k10BitFrame3});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(gfx::Rect(320, 180), decoder_->GetVisibleRect());
- EXPECT_EQ(H264PROFILE_HIGH10PROFILE, decoder_->GetProfile());
- EXPECT_EQ(10u, decoder_->GetBitDepth());
- EXPECT_LE(14u, decoder_->GetRequiredNumOfPictures());
- // One picture will be kept in the DPB for reordering. The second picture
- // should be outputted after feeding the third and fourth frames.
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(4);
- Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- decode_poc6 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(6)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(4)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, OutputPictureFailureCausesDecodeToFail) {
- // Provide enough data that Decode() will try to output a frame.
- SetInputFrameFiles({
- kBaselineFrame0,
- kBaselineFrame1,
- });
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_CALL(*accelerator_, OutputPicture(_)).WillRepeatedly(Return(false));
- ASSERT_EQ(AcceleratedVideoDecoder::kDecodeError, Decode());
- }
- TEST_F(H264DecoderTest, DecodeProfileHigh) {
- SetInputFrameFiles({kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_HIGH, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
- // Two pictures will be kept in the DPB for reordering. The first picture
- // should be outputted after feeding the third frame.
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(4);
- Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(4)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- decode_poc6 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(6)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, DenyDecodeNonYUV420) {
- // YUV444 frame causes kDecodeError.
- SetInputFrameFiles({kYUV444Frame});
- ASSERT_EQ(AcceleratedVideoDecoder::kDecodeError, Decode());
- }
- TEST_F(H264DecoderTest, SwitchBaselineToHigh) {
- SetInputFrameFiles({
- kBaselineFrame0, kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3,
- });
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_HIGH, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
- ASSERT_TRUE(Mock::VerifyAndClearExpectations(&*accelerator_));
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(4);
- Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(4)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- decode_poc6 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(6)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SwitchHighToBaseline) {
- SetInputFrameFiles({
- kHighFrame0, kBaselineFrame0, kBaselineFrame1, kBaselineFrame2,
- kBaselineFrame3,
- });
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_HIGH, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- ASSERT_TRUE(Mock::VerifyAndClearExpectations(&*accelerator_));
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(4);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(4);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(4);
- Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
- {
- InSequence decode_order;
- decode_poc0 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- decode_poc2 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- decode_poc4 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(4)));
- decode_poc6 = EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(6)));
- }
- {
- InSequence display_order;
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SwitchYUV420ToNonYUV420) {
- SetInputFrameFiles({kBaselineFrame0, kYUV444Frame});
- // The first frame, YUV420, is decoded with no error.
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- // The second frame, YUV444, causes kDecodeError.
- ASSERT_EQ(AcceleratedVideoDecoder::kDecodeError, Decode());
- }
- // Verify that the decryption config is passed to the accelerator.
- TEST_F(H264DecoderTest, SetEncryptedStream) {
- std::string bitstream;
- auto input_file = GetTestDataFilePath(kBaselineFrame0);
- CHECK(base::ReadFileToString(input_file, &bitstream));
- 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(H264Decoder::H264Accelerator::Status::kOk));
- EXPECT_CALL(*accelerator_,
- SubmitDecode(DecryptConfigMatches(decrypt_config.get())))
- .WillOnce(Return(H264Decoder::H264Accelerator::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(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, decoder_->Decode());
- EXPECT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, ParseEncryptedSliceHeaderRetry) {
- SetInputFrameFiles({kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode(true));
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- EXPECT_CALL(*accelerator_, ParseEncryptedSliceHeader(_, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode(true));
- // Try again, assuming key still not set. Only ParseEncryptedSliceHeader()
- // should be called again.
- EXPECT_CALL(*accelerator_, ParseEncryptedSliceHeader(_, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode(true));
- // Assume key has been provided now, next call to Decode() should proceed.
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, ParseEncryptedSliceHeader(_, _, _))
- .WillOnce([this](const std::vector<base::span<const uint8_t>>& data,
- const std::vector<SubsampleEntry>& subsamples,
- H264SliceHeader* slice_hdr_out) {
- return ParseSliceHeader(
- data, subsamples, accelerator_->last_sps_nalu_data,
- accelerator_->last_pps_nalu_data, slice_hdr_out);
- });
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode(true));
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SubmitFrameMetadataRetry) {
- SetInputFrameFiles({kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitFrameMetadata()
- // should be called again.
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- ASSERT_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(WithPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SubmitSliceRetry) {
- SetInputFrameFiles({kBaselineFrame0});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitSlice() should be
- // called again.
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(0);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- ASSERT_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(WithPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SubmitDecodeRetry) {
- SetInputFrameFiles({kBaselineFrame0, kBaselineFrame1});
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(_))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- // Try again, assuming key still not set. Only SubmitDecode() should be
- // called again.
- EXPECT_CALL(*accelerator_, CreateH264Picture()).Times(0);
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _)).Times(0);
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _)).Times(0);
- EXPECT_CALL(*accelerator_, SubmitDecode(_))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain));
- ASSERT_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(WithPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(2)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(2)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- TEST_F(H264DecoderTest, SetStreamRetry) {
- SetInputFrameFiles({kBaselineFrame0});
- EXPECT_CALL(*accelerator_, SetStream(_, _))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kTryAgain))
- .WillOnce(Return(H264Decoder::H264Accelerator::Status::kOk));
- ASSERT_EQ(AcceleratedVideoDecoder::kTryAgain, Decode());
- ASSERT_EQ(AcceleratedVideoDecoder::kConfigChange, Decode());
- EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
- EXPECT_EQ(H264PROFILE_BASELINE, decoder_->GetProfile());
- EXPECT_EQ(8u, decoder_->GetBitDepth());
- EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
- {
- InSequence sequence;
- EXPECT_CALL(*accelerator_, CreateH264Picture());
- EXPECT_CALL(*accelerator_, SubmitFrameMetadata(_, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitSlice(_, _, _, _, _, _, _, _));
- EXPECT_CALL(*accelerator_, SubmitDecode(WithPoc(0)));
- EXPECT_CALL(*accelerator_, OutputPicture(WithPoc(0)));
- }
- ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
- ASSERT_TRUE(decoder_->Flush());
- }
- } // namespace
- } // namespace media
|