/src/mozilla-central/dom/media/gtest/TestVPXDecoding.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include "gtest/gtest.h" |
6 | | #include "mozilla/ArrayUtils.h" |
7 | | #include "nsTArray.h" |
8 | | #include "VPXDecoder.h" |
9 | | |
10 | | #include <stdio.h> |
11 | | |
12 | | using namespace mozilla; |
13 | | |
14 | | static void |
15 | | ReadVPXFile(const char* aPath, nsTArray<uint8_t>& aBuffer) |
16 | 0 | { |
17 | 0 | FILE* f = fopen(aPath, "rb"); |
18 | 0 | ASSERT_NE(f, (FILE *) nullptr); |
19 | 0 |
|
20 | 0 | int r = fseek(f, 0, SEEK_END); |
21 | 0 | ASSERT_EQ(r, 0); |
22 | 0 |
|
23 | 0 | long size = ftell(f); |
24 | 0 | ASSERT_NE(size, -1); |
25 | 0 | aBuffer.SetLength(size); |
26 | 0 |
|
27 | 0 | r = fseek(f, 0, SEEK_SET); |
28 | 0 | ASSERT_EQ(r, 0); |
29 | 0 |
|
30 | 0 | size_t got = fread(aBuffer.Elements(), 1, size, f); |
31 | 0 | ASSERT_EQ(got, size_t(size)); |
32 | 0 |
|
33 | 0 | r = fclose(f); |
34 | 0 | ASSERT_EQ(r, 0); |
35 | 0 | } |
36 | | |
37 | | static |
38 | | vpx_codec_iface_t* |
39 | | ParseIVFConfig(nsTArray<uint8_t>& data, vpx_codec_dec_cfg_t& config) |
40 | 0 | { |
41 | 0 | if (data.Length() < 32 + 12) { |
42 | 0 | // Not enough data for file & first frame headers. |
43 | 0 | return nullptr; |
44 | 0 | } |
45 | 0 | if (data[0] != 'D' || data[1] != 'K' || data[2] != 'I' || data[3] != 'F') { |
46 | 0 | // Expect 'DKIP' |
47 | 0 | return nullptr; |
48 | 0 | } |
49 | 0 | if (data[4] != 0 || data[5] != 0) { |
50 | 0 | // Expect version==0. |
51 | 0 | return nullptr; |
52 | 0 | } |
53 | 0 | if (data[8] != 'V' || data[9] != 'P' || |
54 | 0 | (data[10] != '8' && data[10] != '9') || data[11] != '0') { |
55 | 0 | // Expect 'VP80' or 'VP90'. |
56 | 0 | return nullptr; |
57 | 0 | } |
58 | 0 | config.w = uint32_t(data[12]) || (uint32_t(data[13]) << 8); |
59 | 0 | config.h = uint32_t(data[14]) || (uint32_t(data[15]) << 8); |
60 | 0 | vpx_codec_iface_t* codec = (data[10] == '8') |
61 | 0 | ? vpx_codec_vp8_dx() |
62 | 0 | : vpx_codec_vp9_dx(); |
63 | 0 | // Remove headers, to just leave raw VPx data to be decoded. |
64 | 0 | data.RemoveElementsAt(0, 32 + 12); |
65 | 0 | return codec; |
66 | 0 | } |
67 | | |
68 | | struct TestFileData { |
69 | | const char* mFilename; |
70 | | vpx_codec_err_t mDecodeResult; |
71 | | }; |
72 | | static const TestFileData testFiles[] = { |
73 | | { "test_case_1224361.vp8.ivf", VPX_CODEC_OK }, |
74 | | { "test_case_1224363.vp8.ivf", VPX_CODEC_CORRUPT_FRAME }, |
75 | | { "test_case_1224369.vp8.ivf", VPX_CODEC_CORRUPT_FRAME } |
76 | | }; |
77 | | |
78 | | TEST(libvpx, test_cases) |
79 | 0 | { |
80 | 0 | for (size_t test = 0; test < ArrayLength(testFiles); ++test) { |
81 | 0 | nsTArray<uint8_t> data; |
82 | 0 | ReadVPXFile(testFiles[test].mFilename, data); |
83 | 0 | ASSERT_GT(data.Length(), 0u); |
84 | 0 |
|
85 | 0 | vpx_codec_dec_cfg_t config; |
86 | 0 | vpx_codec_iface_t* dx = ParseIVFConfig(data, config); |
87 | 0 | ASSERT_TRUE(dx); |
88 | 0 | config.threads = 2; |
89 | 0 |
|
90 | 0 | vpx_codec_ctx_t ctx; |
91 | 0 | PodZero(&ctx); |
92 | 0 | vpx_codec_err_t r = vpx_codec_dec_init(&ctx, dx, &config, 0); |
93 | 0 | ASSERT_EQ(VPX_CODEC_OK, r); |
94 | 0 |
|
95 | 0 | r = vpx_codec_decode(&ctx, data.Elements(), data.Length(), nullptr, 0); |
96 | 0 | // This test case is known to be corrupt. |
97 | 0 | EXPECT_EQ(testFiles[test].mDecodeResult, r); |
98 | 0 |
|
99 | 0 | r = vpx_codec_destroy(&ctx); |
100 | 0 | EXPECT_EQ(VPX_CODEC_OK, r); |
101 | 0 | } |
102 | 0 | } |