OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "./vpx_config.h" | 11 #include "./vpx_config.h" |
12 #include "test/codec_factory.h" | 12 #include "test/codec_factory.h" |
13 #include "test/encode_test_driver.h" | 13 #include "test/encode_test_driver.h" |
14 #include "test/decode_test_driver.h" | 14 #include "test/decode_test_driver.h" |
15 #include "test/register_state_check.h" | 15 #include "test/register_state_check.h" |
16 #include "test/video_source.h" | 16 #include "test/video_source.h" |
17 #include "third_party/googletest/src/include/gtest/gtest.h" | 17 #include "third_party/googletest/src/include/gtest/gtest.h" |
18 | 18 |
19 namespace libvpx_test { | 19 namespace libvpx_test { |
| 20 void Encoder::InitEncoder(VideoSource *video) { |
| 21 vpx_codec_err_t res; |
| 22 const vpx_image_t *img = video->img(); |
| 23 |
| 24 if (video->img() && !encoder_.priv) { |
| 25 cfg_.g_w = img->d_w; |
| 26 cfg_.g_h = img->d_h; |
| 27 cfg_.g_timebase = video->timebase(); |
| 28 cfg_.rc_twopass_stats_in = stats_->buf(); |
| 29 res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_, |
| 30 init_flags_); |
| 31 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); |
| 32 } |
| 33 } |
| 34 |
20 void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) { | 35 void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) { |
21 if (video->img()) | 36 if (video->img()) |
22 EncodeFrameInternal(*video, frame_flags); | 37 EncodeFrameInternal(*video, frame_flags); |
23 else | 38 else |
24 Flush(); | 39 Flush(); |
25 | 40 |
26 // Handle twopass stats | 41 // Handle twopass stats |
27 CxDataIterator iter = GetCxData(); | 42 CxDataIterator iter = GetCxData(); |
28 | 43 |
29 while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { | 44 while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { |
30 if (pkt->kind != VPX_CODEC_STATS_PKT) | 45 if (pkt->kind != VPX_CODEC_STATS_PKT) |
31 continue; | 46 continue; |
32 | 47 |
33 stats_->Append(*pkt); | 48 stats_->Append(*pkt); |
34 } | 49 } |
35 } | 50 } |
36 | 51 |
37 void Encoder::EncodeFrameInternal(const VideoSource &video, | 52 void Encoder::EncodeFrameInternal(const VideoSource &video, |
38 const unsigned long frame_flags) { | 53 const unsigned long frame_flags) { |
39 vpx_codec_err_t res; | 54 vpx_codec_err_t res; |
40 const vpx_image_t *img = video.img(); | 55 const vpx_image_t *img = video.img(); |
41 | 56 |
42 // Handle first frame initialization | |
43 if (!encoder_.priv) { | |
44 cfg_.g_w = img->d_w; | |
45 cfg_.g_h = img->d_h; | |
46 cfg_.g_timebase = video.timebase(); | |
47 cfg_.rc_twopass_stats_in = stats_->buf(); | |
48 res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_, | |
49 init_flags_); | |
50 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); | |
51 } | |
52 | |
53 // Handle frame resizing | 57 // Handle frame resizing |
54 if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) { | 58 if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) { |
55 cfg_.g_w = img->d_w; | 59 cfg_.g_w = img->d_w; |
56 cfg_.g_h = img->d_h; | 60 cfg_.g_h = img->d_h; |
57 res = vpx_codec_enc_config_set(&encoder_, &cfg_); | 61 res = vpx_codec_enc_config_set(&encoder_, &cfg_); |
58 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); | 62 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); |
59 } | 63 } |
60 | 64 |
61 // Encode the frame | 65 // Encode the frame |
62 API_REGISTER_STATE_CHECK( | 66 API_REGISTER_STATE_CHECK( |
63 res = vpx_codec_encode(&encoder_, | 67 res = vpx_codec_encode(&encoder_, img, video.pts(), video.duration(), |
64 video.img(), video.pts(), video.duration(), | |
65 frame_flags, deadline_)); | 68 frame_flags, deadline_)); |
66 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); | 69 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); |
67 } | 70 } |
68 | 71 |
69 void Encoder::Flush() { | 72 void Encoder::Flush() { |
70 const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0, | 73 const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0, |
71 deadline_); | 74 deadline_); |
72 if (!encoder_.priv) | 75 if (!encoder_.priv) |
73 ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError(); | 76 ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError(); |
74 else | 77 else |
75 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); | 78 ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); |
76 } | 79 } |
77 | 80 |
78 void EncoderTest::InitializeConfig() { | 81 void EncoderTest::InitializeConfig() { |
79 const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0); | 82 const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0); |
| 83 dec_cfg_ = vpx_codec_dec_cfg_t(); |
80 ASSERT_EQ(VPX_CODEC_OK, res); | 84 ASSERT_EQ(VPX_CODEC_OK, res); |
81 } | 85 } |
82 | 86 |
83 void EncoderTest::SetMode(TestMode mode) { | 87 void EncoderTest::SetMode(TestMode mode) { |
84 switch (mode) { | 88 switch (mode) { |
85 case kRealTime: | 89 case kRealTime: |
86 deadline_ = VPX_DL_REALTIME; | 90 deadline_ = VPX_DL_REALTIME; |
87 break; | 91 break; |
88 | 92 |
89 case kOnePassGood: | 93 case kOnePassGood: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 cfg_.g_pass = VPX_RC_ONE_PASS; | 155 cfg_.g_pass = VPX_RC_ONE_PASS; |
152 else if (pass == 0) | 156 else if (pass == 0) |
153 cfg_.g_pass = VPX_RC_FIRST_PASS; | 157 cfg_.g_pass = VPX_RC_FIRST_PASS; |
154 else | 158 else |
155 cfg_.g_pass = VPX_RC_LAST_PASS; | 159 cfg_.g_pass = VPX_RC_LAST_PASS; |
156 | 160 |
157 BeginPassHook(pass); | 161 BeginPassHook(pass); |
158 Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_, | 162 Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_, |
159 &stats_); | 163 &stats_); |
160 ASSERT_TRUE(encoder != NULL); | 164 ASSERT_TRUE(encoder != NULL); |
161 Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0); | 165 |
| 166 video->Begin(); |
| 167 encoder->InitEncoder(video); |
| 168 |
| 169 unsigned long dec_init_flags = 0; // NOLINT |
| 170 // Use fragment decoder if encoder outputs partitions. |
| 171 // NOTE: fragment decoder and partition encoder are only supported by VP8. |
| 172 if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) |
| 173 dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS; |
| 174 Decoder* const decoder = codec_->CreateDecoder(dec_cfg, dec_init_flags, 0); |
162 bool again; | 175 bool again; |
163 for (again = true, video->Begin(); again; video->Next()) { | 176 for (again = true; again; video->Next()) { |
164 again = (video->img() != NULL); | 177 again = (video->img() != NULL); |
165 | 178 |
166 PreEncodeFrameHook(video); | 179 PreEncodeFrameHook(video); |
167 PreEncodeFrameHook(video, encoder); | 180 PreEncodeFrameHook(video, encoder); |
168 encoder->EncodeFrame(video, frame_flags_); | 181 encoder->EncodeFrame(video, frame_flags_); |
169 | 182 |
170 CxDataIterator iter = encoder->GetCxData(); | 183 CxDataIterator iter = encoder->GetCxData(); |
171 | 184 |
172 bool has_cxdata = false; | 185 bool has_cxdata = false; |
173 bool has_dxdata = false; | 186 bool has_dxdata = false; |
(...skipping 19 matching lines...) Expand all Loading... |
193 | 206 |
194 case VPX_CODEC_PSNR_PKT: | 207 case VPX_CODEC_PSNR_PKT: |
195 PSNRPktHook(pkt); | 208 PSNRPktHook(pkt); |
196 break; | 209 break; |
197 | 210 |
198 default: | 211 default: |
199 break; | 212 break; |
200 } | 213 } |
201 } | 214 } |
202 | 215 |
| 216 // Flush the decoder when there are no more fragments. |
| 217 if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) { |
| 218 const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0); |
| 219 if (!HandleDecodeResult(res_dec, *video, decoder)) |
| 220 break; |
| 221 } |
| 222 |
203 if (has_dxdata && has_cxdata) { | 223 if (has_dxdata && has_cxdata) { |
204 const vpx_image_t *img_enc = encoder->GetPreviewFrame(); | 224 const vpx_image_t *img_enc = encoder->GetPreviewFrame(); |
205 DxDataIterator dec_iter = decoder->GetDxData(); | 225 DxDataIterator dec_iter = decoder->GetDxData(); |
206 const vpx_image_t *img_dec = dec_iter.Next(); | 226 const vpx_image_t *img_dec = dec_iter.Next(); |
207 if (img_enc && img_dec) { | 227 if (img_enc && img_dec) { |
208 const bool res = compare_img(img_enc, img_dec); | 228 const bool res = compare_img(img_enc, img_dec); |
209 if (!res) { // Mismatch | 229 if (!res) { // Mismatch |
210 MismatchHook(img_enc, img_dec); | 230 MismatchHook(img_enc, img_dec); |
211 } | 231 } |
212 } | 232 } |
213 if (img_dec) | 233 if (img_dec) |
214 DecompressedFrameHook(*img_dec, video->pts()); | 234 DecompressedFrameHook(*img_dec, video->pts()); |
215 } | 235 } |
216 if (!Continue()) | 236 if (!Continue()) |
217 break; | 237 break; |
218 } | 238 } |
219 | 239 |
220 EndPassHook(); | 240 EndPassHook(); |
221 | 241 |
222 if (decoder) | 242 if (decoder) |
223 delete decoder; | 243 delete decoder; |
224 delete encoder; | 244 delete encoder; |
225 | 245 |
226 if (!Continue()) | 246 if (!Continue()) |
227 break; | 247 break; |
228 } | 248 } |
229 } | 249 } |
230 | 250 |
231 } // namespace libvpx_test | 251 } // namespace libvpx_test |
OLD | NEW |