blob: 8a3e3a26f9c33e6636fbb4548b9a3a1b161640fd [file] [log] [blame]
#include <string>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "test/i420_video_source.h"
#include "test/decode_test_driver.h"
#include "vpx/vpx_encoder.h"
#include "vpx/vp8cx.h"
#include "test/codec_factory.h"
extern "C" {
#include "vpx/svc_context.h"
}
namespace {
using libvpx_test::CodecFactory;
using libvpx_test::VP9CodecFactory;
using libvpx_test::Decoder;
class SvcTest : public ::testing::Test {
protected:
SvcTest()
: codec_iface_(0),
test_file_name("hantro_collage_w352h288.yuv"),
decoder_(0) {}
virtual void SetUp() {
memset(&svc_, 0, sizeof(svc_));
svc_.first_frame_full_size = 1;
svc_.encoding_mode = INTER_LAYER_PREDICTION_IP;
svc_.log_level = SVC_LOG_DEBUG;
svc_.log_print = 1;
svc_.gop_size = 100;
codec_iface_ = vpx_codec_vp9_cx();
vpx_codec_err_t res =
vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
EXPECT_EQ(res, VPX_CODEC_OK);
codec_enc_.g_w = kWidth;
codec_enc_.g_h = kHeight;
codec_enc_.g_timebase.num = 1;
codec_enc_.g_timebase.den = 60;
vpx_codec_dec_cfg_t dec_cfg = {0};
VP9CodecFactory codec_factory;
decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
}
SvcContext svc_;
vpx_codec_ctx_t codec_;
struct vpx_codec_enc_cfg codec_enc_;
vpx_codec_iface_t* codec_iface_;
std::string test_file_name;
enum {
kWidth = 352,
kHeight = 288,
};
Decoder* decoder_;
};
TEST_F(SvcTest, SvcInit) {
svc_.spatial_layers = 0; // not enough layers
vpx_codec_err_t res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
svc_.spatial_layers = 6; // too many layers
res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
svc_.spatial_layers = 2;
svc_.scale_factors = "4/16,16*16"; // invalid scale values
res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
svc_.scale_factors = "4/16,16/16"; // valid scale values
res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_OK);
}
// test that decoder can handle an svc frame as the first frame in a sequence
// this test is disabled since it with the deco
TEST_F(SvcTest, DISABLED_FirstFrameHasLayers) {
svc_.first_frame_full_size = 0;
svc_.spatial_layers = 2;
svc_.scale_factors = "4/16,16/16";
svc_.quantizer_values = "40,30";
vpx_codec_err_t res =
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_OK);
libvpx_test::I420VideoSource video(test_file_name, kWidth, kHeight,
codec_enc_.g_timebase.den,
codec_enc_.g_timebase.num, 0, 30);
video.Begin();
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
EXPECT_EQ(res, VPX_CODEC_OK);
vpx_codec_err_t res_dec = decoder_->DecodeFrame(
(const uint8_t*)svc_get_buffer(&svc_), svc_get_frame_size(&svc_));
// this test fails with a decoder error
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
}
TEST_F(SvcTest, EncodeThreeFrames) {
svc_.first_frame_full_size = 1;
svc_.spatial_layers = 2;
svc_.scale_factors = "4/16,16/16";
svc_.quantizer_values = "40,30";
vpx_codec_err_t res =
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
ASSERT_EQ(res, VPX_CODEC_OK);
libvpx_test::I420VideoSource video(test_file_name, kWidth, kHeight,
codec_enc_.g_timebase.den,
codec_enc_.g_timebase.num, 0, 30);
// FRAME 1
video.Begin();
// this frame is full size, with only one layer
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
ASSERT_EQ(res, VPX_CODEC_OK);
EXPECT_EQ(1, svc_is_keyframe(&svc_));
vpx_codec_err_t res_dec = decoder_->DecodeFrame(
(const uint8_t*)svc_get_buffer(&svc_), svc_get_frame_size(&svc_));
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
// FRAME 2
video.Next();
// this is an I-frame
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
ASSERT_EQ(res, VPX_CODEC_OK);
EXPECT_EQ(1, svc_is_keyframe(&svc_));
res_dec = decoder_->DecodeFrame((const uint8_t*)svc_get_buffer(&svc_),
svc_get_frame_size(&svc_));
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
// FRAME 2
video.Next();
// this is a P-frame
res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
video.duration(), VPX_DL_REALTIME);
ASSERT_EQ(res, VPX_CODEC_OK);
EXPECT_EQ(0, svc_is_keyframe(&svc_));
res_dec = decoder_->DecodeFrame((const uint8_t*)svc_get_buffer(&svc_),
svc_get_frame_size(&svc_));
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
}
TEST_F(SvcTest, GetLayerResolution) {
unsigned int layer_width, layer_height;
svc_.first_frame_full_size = 0;
svc_.spatial_layers = 2;
svc_.scale_factors = "4/16,8/16";
svc_.quantizer_values = "40,30";
vpx_codec_err_t res =
vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
EXPECT_EQ(res, VPX_CODEC_OK);
// ensure that requested layer is a valid layer
res = svc_get_layer_resolution(&svc_, svc_.spatial_layers, &layer_width,
&layer_height);
EXPECT_EQ(res, VPX_CODEC_INVALID_PARAM);
res = svc_get_layer_resolution(&svc_, 0, &layer_width,
&layer_height);
EXPECT_EQ(res, VPX_CODEC_OK);
EXPECT_EQ((unsigned int)(kWidth * 4 / 16), layer_width);
EXPECT_EQ((unsigned int)(kHeight * 4 / 16), layer_height);
res = svc_get_layer_resolution(&svc_, 1, &layer_width,
&layer_height);
EXPECT_EQ(res, VPX_CODEC_OK);
EXPECT_EQ((unsigned int)(kWidth * 8 / 16), layer_width);
EXPECT_EQ((unsigned int)(kHeight * 8 / 16), layer_height);
}
} // namespace