1 /*
2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "third_party/googletest/src/include/gtest/gtest.h"
12
13 #include "./vpx_config.h"
14 #include "test/ivf_video_source.h"
15 #include "vpx/vp8dx.h"
16 #include "vpx/vpx_decoder.h"
17
18 namespace {
19
20 #define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
21
TEST(DecodeAPI,InvalidParams)22 TEST(DecodeAPI, InvalidParams) {
23 static const vpx_codec_iface_t *kCodecs[] = {
24 #if CONFIG_VP8_DECODER
25 &vpx_codec_vp8_dx_algo,
26 #endif
27 #if CONFIG_VP9_DECODER
28 &vpx_codec_vp9_dx_algo,
29 #endif
30 };
31 uint8_t buf[1] = { 0 };
32 vpx_codec_ctx_t dec;
33
34 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(NULL, NULL, NULL, 0));
35 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(&dec, NULL, NULL, 0));
36 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, NULL, 0, NULL, 0));
37 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, buf, 0, NULL, 0));
38 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
39 vpx_codec_decode(NULL, buf, NELEMENTS(buf), NULL, 0));
40 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
41 vpx_codec_decode(NULL, NULL, NELEMENTS(buf), NULL, 0));
42 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL));
43 EXPECT_TRUE(vpx_codec_error(NULL) != NULL);
44
45 for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
46 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
47 vpx_codec_dec_init(NULL, kCodecs[i], NULL, 0));
48
49 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, kCodecs[i], NULL, 0));
50 EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
51 vpx_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0));
52 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
53 vpx_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0));
54 EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(&dec, buf, 0, NULL, 0));
55
56 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
57 }
58 }
59
60 #if CONFIG_VP8_DECODER
TEST(DecodeAPI,OptionalParams)61 TEST(DecodeAPI, OptionalParams) {
62 vpx_codec_ctx_t dec;
63
64 #if CONFIG_ERROR_CONCEALMENT
65 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL,
66 VPX_CODEC_USE_ERROR_CONCEALMENT));
67 #else
68 EXPECT_EQ(VPX_CODEC_INCAPABLE,
69 vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL,
70 VPX_CODEC_USE_ERROR_CONCEALMENT));
71 #endif // CONFIG_ERROR_CONCEALMENT
72 }
73 #endif // CONFIG_VP8_DECODER
74
75 #if CONFIG_VP9_DECODER
76 // Test VP9 codec controls after a decode error to ensure the code doesn't
77 // misbehave.
TestVp9Controls(vpx_codec_ctx_t * dec)78 void TestVp9Controls(vpx_codec_ctx_t *dec) {
79 static const int kControls[] = { VP8D_GET_LAST_REF_UPDATES,
80 VP8D_GET_FRAME_CORRUPTED,
81 VP9D_GET_DISPLAY_SIZE, VP9D_GET_FRAME_SIZE };
82 int val[2];
83
84 for (int i = 0; i < NELEMENTS(kControls); ++i) {
85 const vpx_codec_err_t res = vpx_codec_control_(dec, kControls[i], val);
86 switch (kControls[i]) {
87 case VP8D_GET_FRAME_CORRUPTED:
88 EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i];
89 break;
90 default: EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i]; break;
91 }
92 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
93 vpx_codec_control_(dec, kControls[i], NULL));
94 }
95
96 vp9_ref_frame_t ref;
97 ref.idx = 0;
98 EXPECT_EQ(VPX_CODEC_ERROR, vpx_codec_control(dec, VP9_GET_REFERENCE, &ref));
99 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
100 vpx_codec_control(dec, VP9_GET_REFERENCE, NULL));
101
102 vpx_ref_frame_t ref_copy;
103 const int width = 352;
104 const int height = 288;
105 ASSERT_TRUE(
106 vpx_img_alloc(&ref_copy.img, VPX_IMG_FMT_I420, width, height, 1) != NULL);
107 ref_copy.frame_type = VP8_LAST_FRAME;
108 EXPECT_EQ(VPX_CODEC_ERROR,
109 vpx_codec_control(dec, VP8_COPY_REFERENCE, &ref_copy));
110 EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
111 vpx_codec_control(dec, VP8_COPY_REFERENCE, NULL));
112 vpx_img_free(&ref_copy.img);
113 }
114
TEST(DecodeAPI,Vp9InvalidDecode)115 TEST(DecodeAPI, Vp9InvalidDecode) {
116 const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
117 const char filename[] =
118 "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf";
119 libvpx_test::IVFVideoSource video(filename);
120 video.Init();
121 video.Begin();
122 ASSERT_TRUE(!HasFailure());
123
124 vpx_codec_ctx_t dec;
125 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
126 const uint32_t frame_size = static_cast<uint32_t>(video.frame_size());
127 #if CONFIG_VP9_HIGHBITDEPTH
128 EXPECT_EQ(VPX_CODEC_MEM_ERROR,
129 vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0));
130 #else
131 EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
132 vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0));
133 #endif
134 vpx_codec_iter_t iter = NULL;
135 EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
136
137 TestVp9Controls(&dec);
138 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
139 }
140
TestPeekInfo(const uint8_t * const data,uint32_t data_sz,uint32_t peek_size)141 void TestPeekInfo(const uint8_t *const data, uint32_t data_sz,
142 uint32_t peek_size) {
143 const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
144 // Verify behavior of vpx_codec_decode. vpx_codec_decode doesn't even get
145 // to decoder_peek_si_internal on frames of size < 8.
146 if (data_sz >= 8) {
147 vpx_codec_ctx_t dec;
148 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
149 EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM
150 : VPX_CODEC_CORRUPT_FRAME,
151 vpx_codec_decode(&dec, data, data_sz, NULL, 0));
152 vpx_codec_iter_t iter = NULL;
153 EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
154 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
155 }
156
157 // Verify behavior of vpx_codec_peek_stream_info.
158 vpx_codec_stream_info_t si;
159 si.sz = sizeof(si);
160 EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_OK,
161 vpx_codec_peek_stream_info(codec, data, data_sz, &si));
162 }
163
TEST(DecodeAPI,Vp9PeekStreamInfo)164 TEST(DecodeAPI, Vp9PeekStreamInfo) {
165 // The first 9 bytes are valid and the rest of the bytes are made up. Until
166 // size 10, this should return VPX_CODEC_UNSUP_BITSTREAM and after that it
167 // should return VPX_CODEC_CORRUPT_FRAME.
168 const uint8_t data[32] = {
169 0x85, 0xa4, 0xc1, 0xa1, 0x38, 0x81, 0xa3, 0x49, 0x83, 0xff, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 };
173
174 for (uint32_t data_sz = 1; data_sz <= 32; ++data_sz) {
175 TestPeekInfo(data, data_sz, 10);
176 }
177 }
178
TEST(DecodeAPI,Vp9PeekStreamInfoTruncated)179 TEST(DecodeAPI, Vp9PeekStreamInfoTruncated) {
180 // This profile 1 header requires 10.25 bytes, ensure
181 // vpx_codec_peek_stream_info doesn't over read.
182 const uint8_t profile1_data[10] = { 0xa4, 0xe9, 0x30, 0x68, 0x53,
183 0xe9, 0x30, 0x68, 0x53, 0x04 };
184
185 for (uint32_t data_sz = 1; data_sz <= 10; ++data_sz) {
186 TestPeekInfo(profile1_data, data_sz, 11);
187 }
188 }
189 #endif // CONFIG_VP9_DECODER
190
TEST(DecodeAPI,HighBitDepthCapability)191 TEST(DecodeAPI, HighBitDepthCapability) {
192 // VP8 should not claim VP9 HBD as a capability.
193 #if CONFIG_VP8_DECODER
194 const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_dx_algo);
195 EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
196 #endif
197
198 #if CONFIG_VP9_DECODER
199 const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_dx_algo);
200 #if CONFIG_VP9_HIGHBITDEPTH
201 EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH);
202 #else
203 EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
204 #endif
205 #endif
206 }
207
208 } // namespace
209