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 26namespace { 27 28using std::string; 29 30#if CONFIG_WEBM_IO 31 32struct PauseFileList { 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. 42string DecodeFileWithPause(const string &filename, int num_threads, 43 int pause_num) { 44 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 = vpx_codec_dec_cfg_t(); 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); 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()) 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 95void DecodeFilesWithPause(const PauseFileList files[]) { 96 for (const PauseFileList *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 DecodeFileWithPause(iter->name, t, iter->pause_frame_num)) 101 << "threads = " << t; 102 } 103 } 104} 105 106TEST(DISABLED_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 PauseFileList files[] = { 110 { "vp90-2-07-frame_parallel-1.webm", "6ea7c3875d67252e7caf2bc6e75b36b1", 111 6 }, 112 { "vp90-2-07-frame_parallel-1.webm", "4bb634160c7356a8d7d4299b6dc83a45", 113 12 }, 114 { "vp90-2-07-frame_parallel-1.webm", "89772591e6ef461f9fa754f916c78ed8", 115 26 }, 116 { NULL, NULL, 0 }, 117 }; 118 DecodeFilesWithPause(files); 119} 120 121struct FileList { 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. 131string DecodeFile(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); 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()) decoder.DecodeFrame(NULL, 0); 158 159 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData(); 160 const vpx_image_t *img; 161 162 // Get decompressed data 163 while ((img = dec_iter.Next())) { 164 ++out_frames; 165 md5.Add(img); 166 } 167 } while (video.cxdata() != NULL); 168 169 EXPECT_EQ(expected_frame_count, out_frames) 170 << "Input frame count does not match expected output frame count"; 171 172 return string(md5.Get()); 173} 174 175void DecodeFiles(const FileList files[]) { 176 for (const FileList *iter = files; iter->name != NULL; ++iter) { 177 SCOPED_TRACE(iter->name); 178 for (int t = 2; t <= 8; ++t) { 179 EXPECT_EQ(iter->expected_md5, 180 DecodeFile(iter->name, t, iter->expected_frame_count)) 181 << "threads = " << t; 182 } 183 } 184} 185 186TEST(DISABLED_VP9MultiThreadedFrameParallel, InvalidFileTest) { 187 static const FileList files[] = { 188 // invalid-vp90-2-07-frame_parallel-1.webm is a 40 frame video file with 189 // one key frame for every ten frames. The 11th frame has corrupted data. 190 { "invalid-vp90-2-07-frame_parallel-1.webm", 191 "0549d0f45f60deaef8eb708e6c0eb6cb", 30 }, 192 // invalid-vp90-2-07-frame_parallel-2.webm is a 40 frame video file with 193 // one key frame for every ten frames. The 1st and 31st frames have 194 // corrupted data. 195 { "invalid-vp90-2-07-frame_parallel-2.webm", 196 "6a1f3cf6f9e7a364212fadb9580d525e", 20 }, 197 // invalid-vp90-2-07-frame_parallel-3.webm is a 40 frame video file with 198 // one key frame for every ten frames. The 5th and 13th frames have 199 // corrupted data. 200 { "invalid-vp90-2-07-frame_parallel-3.webm", 201 "8256544308de926b0681e04685b98677", 27 }, 202 { NULL, NULL, 0 }, 203 }; 204 DecodeFiles(files); 205} 206 207TEST(DISABLED_VP9MultiThreadedFrameParallel, ValidFileTest) { 208 static const FileList files[] = { 209#if CONFIG_VP9_HIGHBITDEPTH 210 { "vp92-2-20-10bit-yuv420.webm", "a16b99df180c584e8db2ffeda987d293", 10 }, 211#endif 212 { NULL, NULL, 0 }, 213 }; 214 DecodeFiles(files); 215} 216#endif // CONFIG_WEBM_IO 217} // namespace 218