OLD | NEW |
| (Empty) |
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 <cstdio> | |
12 #include <cstdlib> | |
13 #include <string> | |
14 #include "third_party/googletest/src/include/gtest/gtest.h" | |
15 #include "./vpx_config.h" | |
16 #include "test/codec_factory.h" | |
17 #include "test/decode_test_driver.h" | |
18 #include "test/ivf_video_source.h" | |
19 #include "test/md5_helper.h" | |
20 #include "test/util.h" | |
21 #if CONFIG_WEBM_IO | |
22 #include "test/webm_video_source.h" | |
23 #endif | |
24 #include "vpx_mem/vpx_mem.h" | |
25 | |
26 namespace { | |
27 | |
28 using std::string; | |
29 | |
30 #if CONFIG_WEBM_IO | |
31 | |
32 struct FileList { | |
33 const char *name; | |
34 // md5 sum for decoded frames which does not include skipped frames. | |
35 const char *expected_md5; | |
36 const int pause_frame_num; | |
37 }; | |
38 | |
39 // Decodes |filename| with |num_threads|. Pause at the specified frame_num, | |
40 // seek to next key frame and then continue decoding until the end. Return | |
41 // the md5 of the decoded frames which does not include skipped frames. | |
42 string DecodeFile(const string &filename, int num_threads, int pause_num) { | |
43 libvpx_test::WebMVideoSource video(filename); | |
44 video.Init(); | |
45 int in_frames = 0; | |
46 int out_frames = 0; | |
47 | |
48 vpx_codec_dec_cfg_t cfg = {0}; | |
49 cfg.threads = num_threads; | |
50 vpx_codec_flags_t flags = 0; | |
51 flags |= VPX_CODEC_USE_FRAME_THREADING; | |
52 libvpx_test::VP9Decoder decoder(cfg, flags, 0); | |
53 | |
54 libvpx_test::MD5 md5; | |
55 video.Begin(); | |
56 | |
57 do { | |
58 ++in_frames; | |
59 const vpx_codec_err_t res = | |
60 decoder.DecodeFrame(video.cxdata(), video.frame_size()); | |
61 if (res != VPX_CODEC_OK) { | |
62 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); | |
63 break; | |
64 } | |
65 | |
66 // Pause at specified frame number. | |
67 if (in_frames == pause_num) { | |
68 // Flush the decoder and then seek to next key frame. | |
69 decoder.DecodeFrame(NULL, 0); | |
70 video.SeekToNextKeyFrame(); | |
71 } else { | |
72 video.Next(); | |
73 } | |
74 | |
75 // Flush the decoder at the end of the video. | |
76 if (!video.cxdata()) | |
77 decoder.DecodeFrame(NULL, 0); | |
78 | |
79 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData(); | |
80 const vpx_image_t *img; | |
81 | |
82 // Get decompressed data | |
83 while ((img = dec_iter.Next())) { | |
84 ++out_frames; | |
85 md5.Add(img); | |
86 } | |
87 } while (video.cxdata() != NULL); | |
88 | |
89 EXPECT_EQ(in_frames, out_frames) << | |
90 "Input frame count does not match output frame count"; | |
91 | |
92 return string(md5.Get()); | |
93 } | |
94 | |
95 void DecodeFiles(const FileList files[]) { | |
96 for (const FileList *iter = files; iter->name != NULL; ++iter) { | |
97 SCOPED_TRACE(iter->name); | |
98 for (int t = 2; t <= 8; ++t) { | |
99 EXPECT_EQ(iter->expected_md5, | |
100 DecodeFile(iter->name, t, iter->pause_frame_num)) | |
101 << "threads = " << t; | |
102 } | |
103 } | |
104 } | |
105 | |
106 TEST(VP9MultiThreadedFrameParallel, PauseSeekResume) { | |
107 // vp90-2-07-frame_parallel-1.webm is a 40 frame video file with | |
108 // one key frame for every ten frames. | |
109 static const FileList files[] = { | |
110 { "vp90-2-07-frame_parallel-1.webm", | |
111 "6ea7c3875d67252e7caf2bc6e75b36b1", 6}, | |
112 { "vp90-2-07-frame_parallel-1.webm", | |
113 "4bb634160c7356a8d7d4299b6dc83a45", 12}, | |
114 { "vp90-2-07-frame_parallel-1.webm", | |
115 "89772591e6ef461f9fa754f916c78ed8", 26}, | |
116 { NULL, NULL, 0}, | |
117 }; | |
118 DecodeFiles(files); | |
119 } | |
120 | |
121 struct InvalidFileList { | |
122 const char *name; | |
123 // md5 sum for decoded frames which does not include corrupted frames. | |
124 const char *expected_md5; | |
125 // Expected number of decoded frames which does not include corrupted frames. | |
126 const int expected_frame_count; | |
127 }; | |
128 | |
129 // Decodes |filename| with |num_threads|. Return the md5 of the decoded | |
130 // frames which does not include corrupted frames. | |
131 string DecodeInvalidFile(const string &filename, int num_threads, | |
132 int expected_frame_count) { | |
133 libvpx_test::WebMVideoSource video(filename); | |
134 video.Init(); | |
135 | |
136 vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t(); | |
137 cfg.threads = num_threads; | |
138 const vpx_codec_flags_t flags = VPX_CODEC_USE_FRAME_THREADING; | |
139 libvpx_test::VP9Decoder decoder(cfg, flags, 0); | |
140 | |
141 libvpx_test::MD5 md5; | |
142 video.Begin(); | |
143 | |
144 int out_frames = 0; | |
145 do { | |
146 const vpx_codec_err_t res = | |
147 decoder.DecodeFrame(video.cxdata(), video.frame_size()); | |
148 // TODO(hkuang): frame parallel mode should return an error on corruption. | |
149 if (res != VPX_CODEC_OK) { | |
150 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); | |
151 break; | |
152 } | |
153 | |
154 video.Next(); | |
155 | |
156 // Flush the decoder at the end of the video. | |
157 if (!video.cxdata()) | |
158 decoder.DecodeFrame(NULL, 0); | |
159 | |
160 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData(); | |
161 const vpx_image_t *img; | |
162 | |
163 // Get decompressed data | |
164 while ((img = dec_iter.Next())) { | |
165 ++out_frames; | |
166 md5.Add(img); | |
167 } | |
168 } while (video.cxdata() != NULL); | |
169 | |
170 EXPECT_EQ(expected_frame_count, out_frames) << | |
171 "Input frame count does not match expected output frame count"; | |
172 | |
173 return string(md5.Get()); | |
174 } | |
175 | |
176 void DecodeInvalidFiles(const InvalidFileList files[]) { | |
177 for (const InvalidFileList *iter = files; iter->name != NULL; ++iter) { | |
178 SCOPED_TRACE(iter->name); | |
179 for (int t = 2; t <= 8; ++t) { | |
180 EXPECT_EQ(iter->expected_md5, | |
181 DecodeInvalidFile(iter->name, t, iter->expected_frame_count)) | |
182 << "threads = " << t; | |
183 } | |
184 } | |
185 } | |
186 | |
187 TEST(VP9MultiThreadedFrameParallel, DISABLED_InvalidFileTest) { | |
188 static const InvalidFileList files[] = { | |
189 // invalid-vp90-2-07-frame_parallel-1.webm is a 40 frame video file with | |
190 // one key frame for every ten frames. The 11th frame has corrupted data. | |
191 { "invalid-vp90-2-07-frame_parallel-1.webm", | |
192 "0549d0f45f60deaef8eb708e6c0eb6cb", 30}, | |
193 // invalid-vp90-2-07-frame_parallel-2.webm is a 40 frame video file with | |
194 // one key frame for every ten frames. The 1st and 31st frames have | |
195 // corrupted data. | |
196 { "invalid-vp90-2-07-frame_parallel-2.webm", | |
197 "6a1f3cf6f9e7a364212fadb9580d525e", 20}, | |
198 // invalid-vp90-2-07-frame_parallel-3.webm is a 40 frame video file with | |
199 // one key frame for every ten frames. The 5th and 13th frames have | |
200 // corrupted data. | |
201 { "invalid-vp90-2-07-frame_parallel-3.webm", | |
202 "8256544308de926b0681e04685b98677", 27}, | |
203 { NULL, NULL, 0}, | |
204 }; | |
205 DecodeInvalidFiles(files); | |
206 } | |
207 | |
208 #endif // CONFIG_WEBM_IO | |
209 } // namespace | |
OLD | NEW |