1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* 2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3233d2500723e5594f3e7c70896ffeeef32b9c950ywan * 4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Use of this source code is governed by a BSD-style license 5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * that can be found in the LICENSE file in the root of the source 6233d2500723e5594f3e7c70896ffeeef32b9c950ywan * tree. An additional intellectual property rights grant can be found 7233d2500723e5594f3e7c70896ffeeef32b9c950ywan * in the file PATENTS. All contributing project authors may 8233d2500723e5594f3e7c70896ffeeef32b9c950ywan * be found in the AUTHORS file in the root of the source tree. 9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */ 10233d2500723e5594f3e7c70896ffeeef32b9c950ywan 11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h" 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/codec_factory.h" 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/encode_test_driver.h" 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/decode_test_driver.h" 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/register_state_check.h" 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "test/video_source.h" 17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/googletest/src/include/gtest/gtest.h" 18233d2500723e5594f3e7c70896ffeeef32b9c950ywan 19233d2500723e5594f3e7c70896ffeeef32b9c950ywannamespace libvpx_test { 20233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) { 21233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (video->img()) 22233d2500723e5594f3e7c70896ffeeef32b9c950ywan EncodeFrameInternal(*video, frame_flags); 23233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 24233d2500723e5594f3e7c70896ffeeef32b9c950ywan Flush(); 25233d2500723e5594f3e7c70896ffeeef32b9c950ywan 26233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Handle twopass stats 27233d2500723e5594f3e7c70896ffeeef32b9c950ywan CxDataIterator iter = GetCxData(); 28233d2500723e5594f3e7c70896ffeeef32b9c950ywan 29233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { 30233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (pkt->kind != VPX_CODEC_STATS_PKT) 31233d2500723e5594f3e7c70896ffeeef32b9c950ywan continue; 32233d2500723e5594f3e7c70896ffeeef32b9c950ywan 33233d2500723e5594f3e7c70896ffeeef32b9c950ywan stats_->Append(*pkt); 34233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 35233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 36233d2500723e5594f3e7c70896ffeeef32b9c950ywan 37233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Encoder::EncodeFrameInternal(const VideoSource &video, 38233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned long frame_flags) { 39233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_err_t res; 40233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img = video.img(); 41233d2500723e5594f3e7c70896ffeeef32b9c950ywan 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Handle first frame initialization 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!encoder_.priv) { 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_w = img->d_w; 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_h = img->d_h; 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_timebase = video.timebase(); 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.rc_twopass_stats_in = stats_->buf(); 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_, 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan init_flags_); 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Handle frame resizing 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) { 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_w = img->d_w; 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_h = img->d_h; 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan res = vpx_codec_enc_config_set(&encoder_, &cfg_); 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan // Encode the frame 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan REGISTER_STATE_CHECK( 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan res = vpx_codec_encode(&encoder_, 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan video.img(), video.pts(), video.duration(), 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_flags, deadline_)); 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan 69233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid Encoder::Flush() { 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0, 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan deadline_); 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid EncoderTest::InitializeConfig() { 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0); 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res); 78233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan 80233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid EncoderTest::SetMode(TestMode mode) { 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan switch (mode) { 82233d2500723e5594f3e7c70896ffeeef32b9c950ywan case kRealTime: 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan deadline_ = VPX_DL_REALTIME; 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan case kOnePassGood: 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan case kTwoPassGood: 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan deadline_ = VPX_DL_GOOD_QUALITY; 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan case kOnePassBest: 92233d2500723e5594f3e7c70896ffeeef32b9c950ywan case kTwoPassBest: 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan deadline_ = VPX_DL_BEST_QUALITY; 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan default: 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_TRUE(false) << "Unexpected mode " << mode; 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (mode == kTwoPassGood || mode == kTwoPassBest) 101233d2500723e5594f3e7c70896ffeeef32b9c950ywan passes_ = 2; 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan passes_ = 1; 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan// The function should return "true" most of the time, therefore no early 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan// break-out is implemented within the match checking process. 107233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic bool compare_img(const vpx_image_t *img1, 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img2) { 109233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool match = (img1->fmt == img2->fmt) && 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_w == img2->d_w) && 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan (img1->d_h == img2->d_h); 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned int width_y = img1->d_w; 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned int height_y = img1->d_h; 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int i; 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < height_y; ++i) 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y], 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y], 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan width_y) == 0) && match; 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned int width_uv = (img1->d_w + 1) >> 1; 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan const unsigned int height_uv = (img1->d_h + 1) >> 1; 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < height_uv; ++i) 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U], 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U], 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan width_uv) == 0) && match; 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i = 0; i < height_uv; ++i) 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan match = (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V], 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V], 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan width_uv) == 0) && match; 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan return match; 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan 133233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid EncoderTest::MismatchHook(const vpx_image_t *img1, 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img2) { 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_TRUE(0) << "Encode/Decode mismatch found"; 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan 138233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid EncoderTest::RunLoop(VideoSource *video) { 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_dec_cfg_t dec_cfg = {0}; 140233d2500723e5594f3e7c70896ffeeef32b9c950ywan 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan stats_.Reset(); 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_TRUE(passes_ == 1 || passes_ == 2); 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (unsigned int pass = 0; pass < passes_; pass++) { 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan last_pts_ = 0; 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (passes_ == 1) 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_pass = VPX_RC_ONE_PASS; 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan else if (pass == 0) 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_pass = VPX_RC_FIRST_PASS; 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan cfg_.g_pass = VPX_RC_LAST_PASS; 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan BeginPassHook(pass); 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_, 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan &stats_); 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_TRUE(encoder != NULL); 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan Decoder* const decoder = codec_->CreateDecoder(dec_cfg, 0); 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool again; 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (again = true, video->Begin(); again; video->Next()) { 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan again = (video->img() != NULL); 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan PreEncodeFrameHook(video); 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan PreEncodeFrameHook(video, encoder); 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan encoder->EncodeFrame(video, frame_flags_); 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan CxDataIterator iter = encoder->GetCxData(); 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool has_cxdata = false; 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan bool has_dxdata = false; 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) { 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan pkt = MutateEncoderOutputHook(pkt); 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan again = true; 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan switch (pkt->kind) { 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan case VPX_CODEC_CX_FRAME_PKT: 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan has_cxdata = true; 177233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (decoder && DoDecode()) { 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_err_t res_dec = decoder->DecodeFrame( 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan (const uint8_t*)pkt->data.frame.buf, pkt->data.frame.sz); 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError(); 181233d2500723e5594f3e7c70896ffeeef32b9c950ywan has_dxdata = true; 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan ASSERT_GE(pkt->data.frame.pts, last_pts_); 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan last_pts_ = pkt->data.frame.pts; 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan FramePktHook(pkt); 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan case VPX_CODEC_PSNR_PKT: 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan PSNRPktHook(pkt); 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan default: 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 195233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan 197233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (has_dxdata && has_cxdata) { 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img_enc = encoder->GetPreviewFrame(); 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan DxDataIterator dec_iter = decoder->GetDxData(); 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan const vpx_image_t *img_dec = dec_iter.Next(); 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (img_enc && img_dec) { 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan const bool res = compare_img(img_enc, img_dec); 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!res) { // Mismatch 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan MismatchHook(img_enc, img_dec); 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (img_dec) 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan DecompressedFrameHook(*img_dec, video->pts()); 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 210233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!Continue()) 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan EndPassHook(); 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (decoder) 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan delete decoder; 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan delete encoder; 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (!Continue()) 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan} // namespace libvpx_test 226