1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <climits>
13 #include <vector>
14 #include "third_party/googletest/src/googletest/include/gtest/gtest.h"
15 #include "test/codec_factory.h"
16 #include "test/encode_test_driver.h"
17 #include "test/i420_video_source.h"
18 #include "test/util.h"
19 
20 namespace {
21 
22 const int kTestMode = 0;
23 const int kTileCols = 1;
24 const int kTileRows = 2;
25 
26 typedef ::testing::tuple<libaom_test::TestMode, int, int> SuperframeTestParam;
27 
28 class SuperframeTest
29     : public ::libaom_test::CodecTestWithParam<SuperframeTestParam>,
30       public ::libaom_test::EncoderTest {
31  protected:
SuperframeTest()32   SuperframeTest() : EncoderTest(GET_PARAM(0)), last_sf_pts_(0) {}
~SuperframeTest()33   virtual ~SuperframeTest() {}
34 
SetUp()35   virtual void SetUp() {
36     InitializeConfig();
37     const SuperframeTestParam input = GET_PARAM(1);
38     const libaom_test::TestMode mode = ::testing::get<kTestMode>(input);
39     SetMode(mode);
40     sf_count_ = 0;
41     sf_count_max_ = INT_MAX;
42     n_tile_cols_ = ::testing::get<kTileCols>(input);
43     n_tile_rows_ = ::testing::get<kTileRows>(input);
44   }
45 
PreEncodeFrameHook(libaom_test::VideoSource * video,libaom_test::Encoder * encoder)46   virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
47                                   libaom_test::Encoder *encoder) {
48     if (video->frame() == 1) {
49       encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
50       encoder->Control(AOME_SET_CPUUSED, 2);
51       encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
52       encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
53     }
54   }
55 
MutateEncoderOutputHook(const aom_codec_cx_pkt_t * pkt)56   virtual const aom_codec_cx_pkt_t *MutateEncoderOutputHook(
57       const aom_codec_cx_pkt_t *pkt) {
58     if (pkt->kind != AOM_CODEC_CX_FRAME_PKT) return pkt;
59 
60     const uint8_t *buffer = reinterpret_cast<uint8_t *>(pkt->data.frame.buf);
61     const uint8_t marker = buffer[0];
62     const int frames = (marker & 0x7) + 1;
63     const int mag = ((marker >> 3) & 3) + 1;
64     const unsigned int index_sz = 2 + mag * (frames - 1);
65     if ((marker & 0xe0) == 0xc0 && pkt->data.frame.sz >= index_sz &&
66         buffer[index_sz - 1] == marker) {
67       // frame is a superframe. strip off the index.
68       modified_buf_.resize(pkt->data.frame.sz - index_sz);
69       memcpy(&modified_buf_[0], (uint8_t *)pkt->data.frame.buf + index_sz,
70              pkt->data.frame.sz - index_sz);
71       modified_pkt_ = *pkt;
72       modified_pkt_.data.frame.buf = &modified_buf_[0];
73       modified_pkt_.data.frame.sz -= index_sz;
74 
75       sf_count_++;
76       last_sf_pts_ = pkt->data.frame.pts;
77       return &modified_pkt_;
78     }
79 
80     // Make sure we do a few frames after the last SF
81     abort_ |=
82         sf_count_ > sf_count_max_ && pkt->data.frame.pts - last_sf_pts_ >= 5;
83     return pkt;
84   }
85 
86   int sf_count_;
87   int sf_count_max_;
88   aom_codec_cx_pkt_t modified_pkt_;
89   std::vector<uint8_t> modified_buf_;
90   aom_codec_pts_t last_sf_pts_;
91 
92  private:
93   int n_tile_cols_;
94   int n_tile_rows_;
95 };
96 
TEST_P(SuperframeTest,TestSuperframeIndexIsOptional)97 TEST_P(SuperframeTest, TestSuperframeIndexIsOptional) {
98   sf_count_max_ = 0;  // early exit on successful test.
99   cfg_.g_lag_in_frames = 25;
100   cfg_.large_scale_tile = 1;
101   ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
102                                        30, 1, 0, 40);
103   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
104   // NOTE: The use of BWDREF_FRAME will enable the coding of more non-show
105   //       frames besides ALTREF_FRAME.
106   EXPECT_GE(sf_count_, 1);
107 }
108 
109 }  // namespace
110