blob: f0df88afa980e9b2feecb1ff7b30e3e1b11951c2 [file] [log] [blame]
hkuangbe6aead2015-01-27 12:26:28 -08001/*
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
26namespace {
27
28using std::string;
29
30#if CONFIG_WEBM_IO
31
hkuang1582ac82015-03-26 17:37:17 -070032struct PauseFileList {
hkuangbe6aead2015-01-27 12:26:28 -080033 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.
hkuang1582ac82015-03-26 17:37:17 -070042string DecodeFileWithPause(const string &filename, int num_threads,
43 int pause_num) {
hkuangbe6aead2015-01-27 12:26:28 -080044 libvpx_test::WebMVideoSource video(filename);
45 video.Init();
46 int in_frames = 0;
47 int out_frames = 0;
48
49 vpx_codec_dec_cfg_t cfg = {0};
50 cfg.threads = num_threads;
51 vpx_codec_flags_t flags = 0;
52 flags |= VPX_CODEC_USE_FRAME_THREADING;
53 libvpx_test::VP9Decoder decoder(cfg, flags, 0);
54
55 libvpx_test::MD5 md5;
56 video.Begin();
57
58 do {
59 ++in_frames;
60 const vpx_codec_err_t res =
61 decoder.DecodeFrame(video.cxdata(), video.frame_size());
62 if (res != VPX_CODEC_OK) {
63 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
64 break;
65 }
66
67 // Pause at specified frame number.
68 if (in_frames == pause_num) {
69 // Flush the decoder and then seek to next key frame.
70 decoder.DecodeFrame(NULL, 0);
71 video.SeekToNextKeyFrame();
72 } else {
73 video.Next();
74 }
75
76 // Flush the decoder at the end of the video.
77 if (!video.cxdata())
78 decoder.DecodeFrame(NULL, 0);
79
80 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
81 const vpx_image_t *img;
82
83 // Get decompressed data
84 while ((img = dec_iter.Next())) {
85 ++out_frames;
86 md5.Add(img);
87 }
88 } while (video.cxdata() != NULL);
89
90 EXPECT_EQ(in_frames, out_frames) <<
91 "Input frame count does not match output frame count";
92
93 return string(md5.Get());
94}
95
hkuang1582ac82015-03-26 17:37:17 -070096void DecodeFilesWithPause(const PauseFileList files[]) {
97 for (const PauseFileList *iter = files; iter->name != NULL; ++iter) {
hkuangbe6aead2015-01-27 12:26:28 -080098 SCOPED_TRACE(iter->name);
99 for (int t = 2; t <= 8; ++t) {
100 EXPECT_EQ(iter->expected_md5,
hkuang1582ac82015-03-26 17:37:17 -0700101 DecodeFileWithPause(iter->name, t, iter->pause_frame_num))
hkuangbe6aead2015-01-27 12:26:28 -0800102 << "threads = " << t;
103 }
104 }
105}
106
107TEST(VP9MultiThreadedFrameParallel, PauseSeekResume) {
108 // vp90-2-07-frame_parallel-1.webm is a 40 frame video file with
109 // one key frame for every ten frames.
hkuang1582ac82015-03-26 17:37:17 -0700110 static const PauseFileList files[] = {
hkuangbe6aead2015-01-27 12:26:28 -0800111 { "vp90-2-07-frame_parallel-1.webm",
hkuang1582ac82015-03-26 17:37:17 -0700112 "6ea7c3875d67252e7caf2bc6e75b36b1", 6 },
hkuangbe6aead2015-01-27 12:26:28 -0800113 { "vp90-2-07-frame_parallel-1.webm",
hkuang1582ac82015-03-26 17:37:17 -0700114 "4bb634160c7356a8d7d4299b6dc83a45", 12 },
hkuangbe6aead2015-01-27 12:26:28 -0800115 { "vp90-2-07-frame_parallel-1.webm",
hkuang1582ac82015-03-26 17:37:17 -0700116 "89772591e6ef461f9fa754f916c78ed8", 26 },
117 { NULL, NULL, 0 },
hkuangbe6aead2015-01-27 12:26:28 -0800118 };
hkuang1582ac82015-03-26 17:37:17 -0700119 DecodeFilesWithPause(files);
hkuangbe6aead2015-01-27 12:26:28 -0800120}
121
hkuang1582ac82015-03-26 17:37:17 -0700122struct FileList {
hkuangbe6aead2015-01-27 12:26:28 -0800123 const char *name;
124 // md5 sum for decoded frames which does not include corrupted frames.
125 const char *expected_md5;
126 // Expected number of decoded frames which does not include corrupted frames.
127 const int expected_frame_count;
128};
129
130// Decodes |filename| with |num_threads|. Return the md5 of the decoded
131// frames which does not include corrupted frames.
hkuang1582ac82015-03-26 17:37:17 -0700132string DecodeFile(const string &filename, int num_threads,
133 int expected_frame_count) {
hkuangbe6aead2015-01-27 12:26:28 -0800134 libvpx_test::WebMVideoSource video(filename);
135 video.Init();
136
137 vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
138 cfg.threads = num_threads;
139 const vpx_codec_flags_t flags = VPX_CODEC_USE_FRAME_THREADING;
140 libvpx_test::VP9Decoder decoder(cfg, flags, 0);
141
142 libvpx_test::MD5 md5;
143 video.Begin();
144
145 int out_frames = 0;
146 do {
147 const vpx_codec_err_t res =
148 decoder.DecodeFrame(video.cxdata(), video.frame_size());
149 // TODO(hkuang): frame parallel mode should return an error on corruption.
150 if (res != VPX_CODEC_OK) {
151 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
152 break;
153 }
154
155 video.Next();
156
157 // Flush the decoder at the end of the video.
158 if (!video.cxdata())
159 decoder.DecodeFrame(NULL, 0);
160
161 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
162 const vpx_image_t *img;
163
164 // Get decompressed data
165 while ((img = dec_iter.Next())) {
166 ++out_frames;
167 md5.Add(img);
168 }
169 } while (video.cxdata() != NULL);
170
171 EXPECT_EQ(expected_frame_count, out_frames) <<
172 "Input frame count does not match expected output frame count";
173
174 return string(md5.Get());
175}
176
hkuang1582ac82015-03-26 17:37:17 -0700177void DecodeFiles(const FileList files[]) {
178 for (const FileList *iter = files; iter->name != NULL; ++iter) {
hkuangbe6aead2015-01-27 12:26:28 -0800179 SCOPED_TRACE(iter->name);
180 for (int t = 2; t <= 8; ++t) {
181 EXPECT_EQ(iter->expected_md5,
hkuang1582ac82015-03-26 17:37:17 -0700182 DecodeFile(iter->name, t, iter->expected_frame_count))
hkuangbe6aead2015-01-27 12:26:28 -0800183 << "threads = " << t;
184 }
185 }
186}
187
hkuang2fa9e9e2015-02-09 12:14:00 -0800188TEST(VP9MultiThreadedFrameParallel, InvalidFileTest) {
hkuang1582ac82015-03-26 17:37:17 -0700189 static const FileList files[] = {
hkuangbe6aead2015-01-27 12:26:28 -0800190 // invalid-vp90-2-07-frame_parallel-1.webm is a 40 frame video file with
191 // one key frame for every ten frames. The 11th frame has corrupted data.
192 { "invalid-vp90-2-07-frame_parallel-1.webm",
hkuang1582ac82015-03-26 17:37:17 -0700193 "0549d0f45f60deaef8eb708e6c0eb6cb", 30 },
hkuangbe6aead2015-01-27 12:26:28 -0800194 // invalid-vp90-2-07-frame_parallel-2.webm is a 40 frame video file with
195 // one key frame for every ten frames. The 1st and 31st frames have
196 // corrupted data.
197 { "invalid-vp90-2-07-frame_parallel-2.webm",
hkuang1582ac82015-03-26 17:37:17 -0700198 "6a1f3cf6f9e7a364212fadb9580d525e", 20 },
hkuangbe6aead2015-01-27 12:26:28 -0800199 // invalid-vp90-2-07-frame_parallel-3.webm is a 40 frame video file with
200 // one key frame for every ten frames. The 5th and 13th frames have
201 // corrupted data.
202 { "invalid-vp90-2-07-frame_parallel-3.webm",
hkuang1582ac82015-03-26 17:37:17 -0700203 "8256544308de926b0681e04685b98677", 27 },
204 { NULL, NULL, 0 },
hkuangbe6aead2015-01-27 12:26:28 -0800205 };
hkuang1582ac82015-03-26 17:37:17 -0700206 DecodeFiles(files);
hkuangbe6aead2015-01-27 12:26:28 -0800207}
208
hkuang1582ac82015-03-26 17:37:17 -0700209TEST(VP9MultiThreadedFrameParallel, ValidFileTest) {
210 static const FileList files[] = {
211#if CONFIG_VP9_HIGHBITDEPTH
212 { "vp92-2-20-10bit-yuv420.webm",
213 "a16b99df180c584e8db2ffeda987d293", 10 },
214#endif
215 { NULL, NULL, 0 },
216 };
217 DecodeFiles(files);
218}
hkuangbe6aead2015-01-27 12:26:28 -0800219#endif // CONFIG_WEBM_IO
220} // namespace