/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h" #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" #include "vpx/vpx_encoder.h" #include "vpx/vp8cx.h" namespace webrtc { enum { kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF, kTemporalUpdateGoldenWithoutDependency = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateGolden = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateAltrefWithoutDependency = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, kTemporalUpdateNoneNoRefAltRef = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, kTemporalUpdateNoneNoRefGolden = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, kTemporalUpdateGoldenWithoutDependencyRefAltRef = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, kTemporalUpdateLastRefAltRef = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, kTemporalUpdateLastAndGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, }; TEST(TemporalLayersTest, 2Layers) { DefaultTemporalLayers tl(2, 0); vpx_codec_enc_cfg_t cfg; CodecSpecificInfoVP8 vp8_info; tl.ConfigureBitrates(500, 500, 30, &cfg); int expected_flags[16] = { kTemporalUpdateLastAndGoldenRefAltRef, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastAndGoldenRefAltRef, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, }; int expected_temporal_idx[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; bool expected_layer_sync[16] = { false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, false }; uint32_t timestamp = 0; for (int i = 0; i < 16; ++i) { EXPECT_EQ(expected_flags[i], tl.EncodeFlags(timestamp)); tl.PopulateCodecSpecific(false, &vp8_info, 0); EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); timestamp += 3000; } } TEST(TemporalLayersTest, 3Layers) { DefaultTemporalLayers tl(3, 0); vpx_codec_enc_cfg_t cfg; CodecSpecificInfoVP8 vp8_info; tl.ConfigureBitrates(500, 500, 30, &cfg); int expected_flags[16] = { kTemporalUpdateLastAndGoldenRefAltRef, kTemporalUpdateNoneNoRefGolden, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastAndGoldenRefAltRef, kTemporalUpdateNoneNoRefGolden, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateNone, }; int expected_temporal_idx[16] = { 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 1, 2 }; bool expected_layer_sync[16] = { false, true, true, false, false, false, false, false, false, true, true, false, false, false, false, false }; unsigned int timestamp = 0; for (int i = 0; i < 16; ++i) { EXPECT_EQ(expected_flags[i], tl.EncodeFlags(timestamp)); tl.PopulateCodecSpecific(false, &vp8_info, 0); EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); timestamp += 3000; } } TEST(TemporalLayersTest, 4Layers) { DefaultTemporalLayers tl(4, 0); vpx_codec_enc_cfg_t cfg; CodecSpecificInfoVP8 vp8_info; tl.ConfigureBitrates(500, 500, 30, &cfg); int expected_flags[16] = { kTemporalUpdateLast, kTemporalUpdateNone, kTemporalUpdateAltrefWithoutDependency, kTemporalUpdateNone, kTemporalUpdateGoldenWithoutDependency, kTemporalUpdateNone, kTemporalUpdateAltref, kTemporalUpdateNone, kTemporalUpdateLast, kTemporalUpdateNone, kTemporalUpdateAltref, kTemporalUpdateNone, kTemporalUpdateGolden, kTemporalUpdateNone, kTemporalUpdateAltref, kTemporalUpdateNone, }; int expected_temporal_idx[16] = { 0, 3, 2, 3, 1, 3, 2, 3, 0, 3, 2, 3, 1, 3, 2, 3 }; bool expected_layer_sync[16] = { false, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true }; uint32_t timestamp = 0; for (int i = 0; i < 16; ++i) { EXPECT_EQ(expected_flags[i], tl.EncodeFlags(timestamp)); tl.PopulateCodecSpecific(false, &vp8_info, 0); EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); timestamp += 3000; } } TEST(TemporalLayersTest, KeyFrame) { DefaultTemporalLayers tl(3, 0); vpx_codec_enc_cfg_t cfg; CodecSpecificInfoVP8 vp8_info; tl.ConfigureBitrates(500, 500, 30, &cfg); int expected_flags[8] = { kTemporalUpdateLastAndGoldenRefAltRef, kTemporalUpdateNoneNoRefGolden, kTemporalUpdateGoldenWithoutDependencyRefAltRef, kTemporalUpdateNone, kTemporalUpdateLastRefAltRef, kTemporalUpdateNone, kTemporalUpdateGoldenRefAltRef, kTemporalUpdateNone, }; int expected_temporal_idx[8] = { 0, 0, 0, 0, 0, 0, 0, 2}; uint32_t timestamp = 0; for (int i = 0; i < 7; ++i) { EXPECT_EQ(expected_flags[i], tl.EncodeFlags(timestamp)); tl.PopulateCodecSpecific(true, &vp8_info, 0); EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); EXPECT_EQ(true, vp8_info.layerSync); timestamp += 3000; } EXPECT_EQ(expected_flags[7], tl.EncodeFlags(timestamp)); tl.PopulateCodecSpecific(false, &vp8_info, 0); EXPECT_EQ(expected_temporal_idx[7], vp8_info.temporalIdx); EXPECT_EQ(true, vp8_info.layerSync); } } // namespace webrtc