| 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 |