| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 The WebRTC 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 "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" | 11 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" |
| 12 #include "vpx/vp8cx.h" | 12 #include "vpx/vp8cx.h" |
| 13 #include "vpx/vpx_encoder.h" | 13 #include "vpx/vpx_encoder.h" |
| 14 #include "webrtc/modules/video_coding/codecs/vp8/vp8_impl.h" | 14 #include "webrtc/modules/video_coding/codecs/vp8/vp8_impl.h" |
| 15 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 15 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
| 16 #include "webrtc/test/field_trial.h" |
| 16 #include "webrtc/test/gtest.h" | 17 #include "webrtc/test/gtest.h" |
| 17 | 18 |
| 18 namespace webrtc { | 19 namespace webrtc { |
| 20 namespace test { |
| 19 | 21 |
| 20 enum { | 22 enum { |
| 21 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | | 23 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 22 VP8_EFLAG_NO_REF_GF | | 24 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF, |
| 23 VP8_EFLAG_NO_REF_ARF, | |
| 24 kTemporalUpdateGoldenWithoutDependency = | 25 kTemporalUpdateGoldenWithoutDependency = |
| 25 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | | 26 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | |
| 26 VP8_EFLAG_NO_UPD_LAST, | 27 VP8_EFLAG_NO_UPD_LAST, |
| 27 kTemporalUpdateGolden = | 28 kTemporalUpdateGolden = |
| 28 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 29 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 29 kTemporalUpdateAltrefWithoutDependency = | 30 kTemporalUpdateAltrefWithoutDependency = |
| 30 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | | 31 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | |
| 31 VP8_EFLAG_NO_UPD_LAST, | 32 VP8_EFLAG_NO_UPD_LAST, |
| 32 kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, | 33 kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, |
| 33 kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | | 34 kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 34 VP8_EFLAG_NO_UPD_LAST | | 35 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 35 VP8_EFLAG_NO_UPD_ENTROPY, | 36 kTemporalUpdateNoneNoRefAltRef = |
| 36 kTemporalUpdateNoneNoRefAltRef = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | | 37 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 37 VP8_EFLAG_NO_UPD_ARF | | 38 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 38 VP8_EFLAG_NO_UPD_LAST | | 39 kTemporalUpdateNoneNoRefGolden = |
| 39 VP8_EFLAG_NO_UPD_ENTROPY, | 40 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 40 kTemporalUpdateNoneNoRefGolden = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | | 41 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 41 VP8_EFLAG_NO_UPD_ARF | | 42 kTemporalUpdateNoneNoRefGoldenAltRef = |
| 42 VP8_EFLAG_NO_UPD_LAST | | 43 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_REF_ARF | |
| 43 VP8_EFLAG_NO_UPD_ENTROPY, | 44 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 44 kTemporalUpdateGoldenWithoutDependencyRefAltRef = | 45 kTemporalUpdateGoldenWithoutDependencyRefAltRef = |
| 45 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 46 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 46 kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 47 kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 47 kTemporalUpdateLastRefAltRef = | 48 kTemporalUpdateLastRefAltRef = |
| 48 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, | 49 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
| 49 kTemporalUpdateLastAndGoldenRefAltRef = | 50 kTemporalUpdateLastAndGoldenRefAltRef = |
| 50 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, | 51 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
| 51 }; | 52 }; |
| 52 | 53 |
| 53 TEST(TemporalLayersTest, 2Layers) { | 54 TEST(TemporalLayersTest, 2Layers) { |
| 54 DefaultTemporalLayers tl(2, 0); | 55 DefaultTemporalLayers tl(2, 0); |
| 55 vpx_codec_enc_cfg_t cfg; | 56 vpx_codec_enc_cfg_t cfg; |
| 56 CodecSpecificInfoVP8 vp8_info; | 57 CodecSpecificInfoVP8 vp8_info; |
| 57 tl.OnRatesUpdated(500, 500, 30); | 58 tl.OnRatesUpdated(500, 500, 30); |
| 58 tl.UpdateConfiguration(&cfg); | 59 tl.UpdateConfiguration(&cfg); |
| 59 | 60 |
| 60 int expected_flags[16] = { | 61 int expected_flags[16] = { |
| 61 kTemporalUpdateLastAndGoldenRefAltRef, | 62 kTemporalUpdateLastRefAltRef, |
| 62 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 63 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 63 kTemporalUpdateLastRefAltRef, | 64 kTemporalUpdateLastRefAltRef, |
| 64 kTemporalUpdateGoldenRefAltRef, | 65 kTemporalUpdateGoldenRefAltRef, |
| 65 kTemporalUpdateLastRefAltRef, | 66 kTemporalUpdateLastRefAltRef, |
| 66 kTemporalUpdateGoldenRefAltRef, | 67 kTemporalUpdateGoldenRefAltRef, |
| 67 kTemporalUpdateLastRefAltRef, | 68 kTemporalUpdateLastRefAltRef, |
| 68 kTemporalUpdateNone, | 69 kTemporalUpdateNone, |
| 69 kTemporalUpdateLastAndGoldenRefAltRef, | 70 kTemporalUpdateLastRefAltRef, |
| 70 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 71 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 71 kTemporalUpdateLastRefAltRef, | 72 kTemporalUpdateLastRefAltRef, |
| 72 kTemporalUpdateGoldenRefAltRef, | 73 kTemporalUpdateGoldenRefAltRef, |
| 73 kTemporalUpdateLastRefAltRef, | 74 kTemporalUpdateLastRefAltRef, |
| 74 kTemporalUpdateGoldenRefAltRef, | 75 kTemporalUpdateGoldenRefAltRef, |
| 75 kTemporalUpdateLastRefAltRef, | 76 kTemporalUpdateLastRefAltRef, |
| 76 kTemporalUpdateNone, | 77 kTemporalUpdateNone, |
| 77 }; | 78 }; |
| 78 int expected_temporal_idx[16] = {0, 1, 0, 1, 0, 1, 0, 1, | 79 int expected_temporal_idx[16] = {0, 1, 0, 1, 0, 1, 0, 1, |
| 79 0, 1, 0, 1, 0, 1, 0, 1}; | 80 0, 1, 0, 1, 0, 1, 0, 1}; |
| 80 | 81 |
| 81 bool expected_layer_sync[16] = {false, true, false, false, false, false, | 82 bool expected_layer_sync[16] = {false, true, false, false, false, false, |
| 82 false, false, false, true, false, false, | 83 false, false, false, true, false, false, |
| 83 false, false, false, false}; | 84 false, false, false, false}; |
| 84 | 85 |
| 85 uint32_t timestamp = 0; | 86 uint32_t timestamp = 0; |
| 86 for (int i = 0; i < 16; ++i) { | 87 for (int i = 0; i < 16; ++i) { |
| 87 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 88 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 88 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 89 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 89 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 90 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 90 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 91 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
| 91 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 92 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 92 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 93 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 93 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 94 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
| 94 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 95 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 95 timestamp += 3000; | 96 timestamp += 3000; |
| 96 } | 97 } |
| 97 } | 98 } |
| 98 | 99 |
| 99 TEST(TemporalLayersTest, 3Layers) { | 100 TEST(TemporalLayersTest, 3Layers) { |
| 100 DefaultTemporalLayers tl(3, 0); | 101 DefaultTemporalLayers tl(3, 0); |
| 101 vpx_codec_enc_cfg_t cfg; | 102 vpx_codec_enc_cfg_t cfg; |
| 102 CodecSpecificInfoVP8 vp8_info; | 103 CodecSpecificInfoVP8 vp8_info; |
| 103 tl.OnRatesUpdated(500, 500, 30); | 104 tl.OnRatesUpdated(500, 500, 30); |
| 104 tl.UpdateConfiguration(&cfg); | 105 tl.UpdateConfiguration(&cfg); |
| 105 | 106 |
| 106 int expected_flags[16] = { | 107 int expected_flags[16] = { |
| 107 kTemporalUpdateLastAndGoldenRefAltRef, | 108 kTemporalUpdateLastRefAltRef, |
| 108 kTemporalUpdateNoneNoRefGolden, | 109 kTemporalUpdateNoneNoRefGolden, |
| 109 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 110 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 110 kTemporalUpdateNone, | 111 kTemporalUpdateNone, |
| 111 kTemporalUpdateLastRefAltRef, | 112 kTemporalUpdateLastRefAltRef, |
| 112 kTemporalUpdateNone, | 113 kTemporalUpdateNone, |
| 113 kTemporalUpdateGoldenRefAltRef, | 114 kTemporalUpdateGoldenRefAltRef, |
| 114 kTemporalUpdateNone, | 115 kTemporalUpdateNone, |
| 115 kTemporalUpdateLastAndGoldenRefAltRef, | 116 kTemporalUpdateLastRefAltRef, |
| 116 kTemporalUpdateNoneNoRefGolden, | 117 kTemporalUpdateNoneNoRefGolden, |
| 117 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 118 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 118 kTemporalUpdateNone, | 119 kTemporalUpdateNone, |
| 119 kTemporalUpdateLastRefAltRef, | 120 kTemporalUpdateLastRefAltRef, |
| 120 kTemporalUpdateNone, | 121 kTemporalUpdateNone, |
| 121 kTemporalUpdateGoldenRefAltRef, | 122 kTemporalUpdateGoldenRefAltRef, |
| 122 kTemporalUpdateNone, | 123 kTemporalUpdateNone, |
| 123 }; | 124 }; |
| 124 int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2, | 125 int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2, |
| 125 0, 2, 1, 2, 0, 2, 1, 2}; | 126 0, 2, 1, 2, 0, 2, 1, 2}; |
| 126 | 127 |
| 127 bool expected_layer_sync[16] = {false, true, true, false, false, false, | 128 bool expected_layer_sync[16] = {false, true, true, false, false, false, |
| 128 false, false, false, true, true, false, | 129 false, false, false, true, true, false, |
| 129 false, false, false, false}; | 130 false, false, false, false}; |
| 130 | 131 |
| 131 unsigned int timestamp = 0; | 132 unsigned int timestamp = 0; |
| 132 for (int i = 0; i < 16; ++i) { | 133 for (int i = 0; i < 16; ++i) { |
| 133 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 134 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 134 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 135 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 135 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 136 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 136 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 137 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
| 137 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 138 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 139 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 140 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
| 141 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 142 timestamp += 3000; |
| 143 } |
| 144 } |
| 145 |
| 146 TEST(TemporalLayersTest, Alternative3Layers) { |
| 147 ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 148 DefaultTemporalLayers tl(3, 0); |
| 149 vpx_codec_enc_cfg_t cfg; |
| 150 CodecSpecificInfoVP8 vp8_info; |
| 151 tl.OnRatesUpdated(500, 500, 30); |
| 152 tl.UpdateConfiguration(&cfg); |
| 153 |
| 154 int expected_flags[8] = {kTemporalUpdateLast, |
| 155 kTemporalUpdateAltrefWithoutDependency, |
| 156 kTemporalUpdateGoldenWithoutDependency, |
| 157 kTemporalUpdateNone, |
| 158 kTemporalUpdateLast, |
| 159 kTemporalUpdateAltrefWithoutDependency, |
| 160 kTemporalUpdateGoldenWithoutDependency, |
| 161 kTemporalUpdateNone}; |
| 162 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
| 163 |
| 164 bool expected_layer_sync[8] = {false, true, true, false, |
| 165 false, true, true, false}; |
| 166 |
| 167 unsigned int timestamp = 0; |
| 168 for (int i = 0; i < 8; ++i) { |
| 169 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 170 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 171 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 172 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
| 173 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 138 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 174 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 139 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 175 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
| 140 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 176 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 141 timestamp += 3000; | 177 timestamp += 3000; |
| 142 } | 178 } |
| 143 } | 179 } |
| 144 | 180 |
| 145 TEST(TemporalLayersTest, 4Layers) { | 181 TEST(TemporalLayersTest, 4Layers) { |
| 146 DefaultTemporalLayers tl(4, 0); | 182 DefaultTemporalLayers tl(4, 0); |
| 147 vpx_codec_enc_cfg_t cfg; | 183 vpx_codec_enc_cfg_t cfg; |
| 148 CodecSpecificInfoVP8 vp8_info; | 184 CodecSpecificInfoVP8 vp8_info; |
| 149 tl.OnRatesUpdated(500, 500, 30); | 185 tl.OnRatesUpdated(500, 500, 30); |
| 150 tl.UpdateConfiguration(&cfg); | 186 tl.UpdateConfiguration(&cfg); |
| 151 int expected_flags[16] = { | 187 int expected_flags[16] = { |
| 152 kTemporalUpdateLast, | 188 kTemporalUpdateLast, |
| 153 kTemporalUpdateNone, | 189 kTemporalUpdateNoneNoRefGoldenAltRef, |
| 154 kTemporalUpdateAltrefWithoutDependency, | 190 kTemporalUpdateAltrefWithoutDependency, |
| 155 kTemporalUpdateNone, | 191 kTemporalUpdateNoneNoRefGolden, |
| 156 kTemporalUpdateGoldenWithoutDependency, | 192 kTemporalUpdateGoldenWithoutDependency, |
| 157 kTemporalUpdateNone, | 193 kTemporalUpdateNone, |
| 158 kTemporalUpdateAltref, | 194 kTemporalUpdateAltref, |
| 159 kTemporalUpdateNone, | 195 kTemporalUpdateNone, |
| 160 kTemporalUpdateLast, | 196 kTemporalUpdateLast, |
| 161 kTemporalUpdateNone, | 197 kTemporalUpdateNone, |
| 162 kTemporalUpdateAltref, | 198 kTemporalUpdateAltref, |
| 163 kTemporalUpdateNone, | 199 kTemporalUpdateNone, |
| 164 kTemporalUpdateGolden, | 200 kTemporalUpdateGolden, |
| 165 kTemporalUpdateNone, | 201 kTemporalUpdateNone, |
| 166 kTemporalUpdateAltref, | 202 kTemporalUpdateAltref, |
| 167 kTemporalUpdateNone, | 203 kTemporalUpdateNone, |
| 168 }; | 204 }; |
| 169 int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3, | 205 int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3, |
| 170 0, 3, 2, 3, 1, 3, 2, 3}; | 206 0, 3, 2, 3, 1, 3, 2, 3}; |
| 171 | 207 |
| 172 bool expected_layer_sync[16] = {false, true, true, true, true, true, | 208 bool expected_layer_sync[16] = {false, true, true, false, true, false, |
| 173 false, true, false, true, false, true, | 209 false, false, false, false, false, false, |
| 174 false, true, false, true}; | 210 false, false, false, false}; |
| 175 | 211 |
| 176 uint32_t timestamp = 0; | 212 uint32_t timestamp = 0; |
| 177 for (int i = 0; i < 16; ++i) { | 213 for (int i = 0; i < 16; ++i) { |
| 178 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 214 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 179 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 215 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 180 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 216 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 181 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 217 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
| 182 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 218 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 183 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 219 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 184 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 220 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
| 185 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 221 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 186 timestamp += 3000; | 222 timestamp += 3000; |
| 187 } | 223 } |
| 188 } | 224 } |
| 189 | 225 |
| 190 TEST(TemporalLayersTest, KeyFrame) { | 226 TEST(TemporalLayersTest, KeyFrame) { |
| 191 DefaultTemporalLayers tl(3, 0); | 227 DefaultTemporalLayers tl(3, 0); |
| 192 vpx_codec_enc_cfg_t cfg; | 228 vpx_codec_enc_cfg_t cfg; |
| 193 CodecSpecificInfoVP8 vp8_info; | 229 CodecSpecificInfoVP8 vp8_info; |
| 194 tl.OnRatesUpdated(500, 500, 30); | 230 tl.OnRatesUpdated(500, 500, 30); |
| 195 tl.UpdateConfiguration(&cfg); | 231 tl.UpdateConfiguration(&cfg); |
| 196 | 232 |
| 197 int expected_flags[8] = { | 233 int expected_flags[8] = { |
| 198 kTemporalUpdateLastAndGoldenRefAltRef, | 234 kTemporalUpdateLastRefAltRef, |
| 199 kTemporalUpdateNoneNoRefGolden, | 235 kTemporalUpdateNoneNoRefGolden, |
| 200 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 236 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 201 kTemporalUpdateNone, | 237 kTemporalUpdateNone, |
| 202 kTemporalUpdateLastRefAltRef, | 238 kTemporalUpdateLastRefAltRef, |
| 203 kTemporalUpdateNone, | 239 kTemporalUpdateNone, |
| 204 kTemporalUpdateGoldenRefAltRef, | 240 kTemporalUpdateGoldenRefAltRef, |
| 205 kTemporalUpdateNone, | 241 kTemporalUpdateNone, |
| 206 }; | 242 }; |
| 207 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; | 243 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
| 208 bool expected_layer_sync[8] = {false, true, true, false, | 244 bool expected_layer_sync[8] = {false, true, true, false, |
| 209 false, false, false, false}; | 245 false, false, false, false}; |
| 210 | 246 |
| 211 uint32_t timestamp = 0; | 247 uint32_t timestamp = 0; |
| 212 for (int i = 0; i < 7; ++i) { | 248 for (int i = 0; i < 7; ++i) { |
| 213 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 249 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 214 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 250 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 215 tl.PopulateCodecSpecific(true, tl_config, &vp8_info, 0); | 251 tl.PopulateCodecSpecific(true, tl_config, &vp8_info, 0); |
| 216 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 252 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 217 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 253 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 218 EXPECT_EQ(0, vp8_info.temporalIdx) | 254 EXPECT_EQ(0, vp8_info.temporalIdx) |
| 219 << "Key frame should always be packetized as layer 0"; | 255 << "Key frame should always be packetized as layer 0"; |
| 220 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 256 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 221 EXPECT_TRUE(vp8_info.layerSync) << "Key frame should be marked layer sync."; | 257 EXPECT_TRUE(vp8_info.layerSync) << "Key frame should be marked layer sync."; |
| 222 timestamp += 3000; | 258 timestamp += 3000; |
| 223 } | 259 } |
| 224 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 260 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 225 EXPECT_EQ(expected_flags[7], VP8EncoderImpl::EncodeFlags(tl_config)); | 261 EXPECT_EQ(expected_flags[7], VP8EncoderImpl::EncodeFlags(tl_config)); |
| 226 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 262 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 227 EXPECT_NE(0, vp8_info.temporalIdx) | 263 EXPECT_NE(0, vp8_info.temporalIdx) |
| 228 << "To test something useful, this frame should not use layer 0."; | 264 << "To test something useful, this frame should not use layer 0."; |
| 229 EXPECT_EQ(expected_temporal_idx[7], vp8_info.temporalIdx) | 265 EXPECT_EQ(expected_temporal_idx[7], vp8_info.temporalIdx) |
| 230 << "Non-keyframe, should use frame temporal index."; | 266 << "Non-keyframe, should use frame temporal index."; |
| 231 EXPECT_EQ(expected_temporal_idx[7], tl_config.packetizer_temporal_idx); | 267 EXPECT_EQ(expected_temporal_idx[7], tl_config.packetizer_temporal_idx); |
| 232 EXPECT_EQ(expected_temporal_idx[7], tl_config.encoder_layer_id); | 268 EXPECT_EQ(expected_temporal_idx[7], tl_config.encoder_layer_id); |
| 233 EXPECT_FALSE(tl_config.layer_sync); | 269 EXPECT_FALSE(tl_config.layer_sync); |
| 234 EXPECT_TRUE(vp8_info.layerSync) << "Frame after keyframe should always be " | 270 EXPECT_TRUE(vp8_info.layerSync) << "Frame after keyframe should always be " |
| 235 "marked layer sync since it only depends " | 271 "marked layer sync since it only depends " |
| 236 "on the base layer."; | 272 "on the base layer."; |
| 237 } | 273 } |
| 274 |
| 275 class TemporalLayersReferenceTest : public ::testing::TestWithParam<int> { |
| 276 public: |
| 277 TemporalLayersReferenceTest() |
| 278 : timestamp_(1), |
| 279 last_sync_timestamp_(timestamp_), |
| 280 tl0_reference_(nullptr) {} |
| 281 virtual ~TemporalLayersReferenceTest() {} |
| 282 |
| 283 protected: |
| 284 static const int kMaxPatternLength = 32; |
| 285 |
| 286 struct BufferState { |
| 287 BufferState() : BufferState(-1, 0, false) {} |
| 288 BufferState(int temporal_idx, uint32_t timestamp, bool sync) |
| 289 : temporal_idx(temporal_idx), timestamp(timestamp), sync(sync) {} |
| 290 int temporal_idx; |
| 291 uint32_t timestamp; |
| 292 bool sync; |
| 293 }; |
| 294 |
| 295 bool UpdateSyncRefState(const TemporalLayers::BufferFlags& flags, |
| 296 BufferState* buffer_state) { |
| 297 if (flags & TemporalLayers::kReference) { |
| 298 if (buffer_state->temporal_idx == -1) |
| 299 return true; // References key-frame. |
| 300 if (buffer_state->temporal_idx == 0) { |
| 301 // No more than one reference to TL0 frame. |
| 302 EXPECT_EQ(nullptr, tl0_reference_); |
| 303 tl0_reference_ = buffer_state; |
| 304 return true; |
| 305 } |
| 306 return false; // References higher layer. |
| 307 } |
| 308 return true; // No reference, does not affect sync frame status. |
| 309 } |
| 310 |
| 311 void ValidateReference(const TemporalLayers::BufferFlags& flags, |
| 312 const BufferState& buffer_state, |
| 313 int temporal_layer) { |
| 314 if (flags & TemporalLayers::kReference) { |
| 315 if (temporal_layer > 0 && buffer_state.timestamp > 0) { |
| 316 // Check that high layer reference does not go past last sync frame. |
| 317 EXPECT_GE(buffer_state.timestamp, last_sync_timestamp_); |
| 318 } |
| 319 // No reference to buffer in higher layer. |
| 320 EXPECT_LE(buffer_state.temporal_idx, temporal_layer); |
| 321 } |
| 322 } |
| 323 |
| 324 uint32_t timestamp_ = 1; |
| 325 uint32_t last_sync_timestamp_ = timestamp_; |
| 326 BufferState* tl0_reference_; |
| 327 |
| 328 BufferState last_state; |
| 329 BufferState golden_state; |
| 330 BufferState altref_state; |
| 331 }; |
| 332 |
| 333 INSTANTIATE_TEST_CASE_P(DefaultTemporalLayersTest, |
| 334 TemporalLayersReferenceTest, |
| 335 ::testing::Range(1, kMaxTemporalStreams + 1)); |
| 336 |
| 337 TEST_P(TemporalLayersReferenceTest, ValidFrameConfigs) { |
| 338 const int num_layers = GetParam(); |
| 339 DefaultTemporalLayers tl(num_layers, 0); |
| 340 vpx_codec_enc_cfg_t cfg; |
| 341 tl.OnRatesUpdated(500, 500, 30); |
| 342 tl.UpdateConfiguration(&cfg); |
| 343 |
| 344 // Run through the pattern and store the frame dependencies, plus keep track |
| 345 // of the buffer state; which buffers references which temporal layers (if |
| 346 // (any). If a given buffer is never updated, it is legal to reference it |
| 347 // even for sync frames. In order to be general, don't assume TL0 always |
| 348 // updates |last|. |
| 349 std::vector<TemporalLayers::FrameConfig> tl_configs(kMaxPatternLength); |
| 350 for (int i = 0; i < kMaxPatternLength; ++i) { |
| 351 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp_++); |
| 352 EXPECT_FALSE(tl_config.drop_frame); |
| 353 tl_configs.push_back(tl_config); |
| 354 int temporal_idx = tl_config.encoder_layer_id; |
| 355 // For the default layers, always keep encoder and rtp layers in sync. |
| 356 EXPECT_EQ(tl_config.packetizer_temporal_idx, temporal_idx); |
| 357 |
| 358 // Determine if this frame is in a higher layer but references only TL0 |
| 359 // or untouched buffers, if so verify it is marked as a layer sync. |
| 360 bool is_sync_frame = true; |
| 361 tl0_reference_ = nullptr; |
| 362 if (temporal_idx <= 0) { |
| 363 is_sync_frame = false; // TL0 by definition not a sync frame. |
| 364 } else if (!UpdateSyncRefState(tl_config.last_buffer_flags, &last_state)) { |
| 365 is_sync_frame = false; |
| 366 } else if (!UpdateSyncRefState(tl_config.golden_buffer_flags, |
| 367 &golden_state)) { |
| 368 is_sync_frame = false; |
| 369 } else if (!UpdateSyncRefState(tl_config.arf_buffer_flags, &altref_state)) { |
| 370 is_sync_frame = false; |
| 371 } |
| 372 if (is_sync_frame) { |
| 373 // Cache timestamp for last found sync frame, so that we can verify no |
| 374 // references back past this frame. |
| 375 ASSERT_TRUE(tl0_reference_); |
| 376 last_sync_timestamp_ = tl0_reference_->timestamp; |
| 377 } |
| 378 EXPECT_EQ(tl_config.layer_sync, is_sync_frame); |
| 379 |
| 380 // Validate no reference from lower to high temporal layer, or backwards |
| 381 // past last reference frame. |
| 382 ValidateReference(tl_config.last_buffer_flags, last_state, temporal_idx); |
| 383 ValidateReference(tl_config.golden_buffer_flags, golden_state, |
| 384 temporal_idx); |
| 385 ValidateReference(tl_config.arf_buffer_flags, altref_state, temporal_idx); |
| 386 |
| 387 // Update the current layer state. |
| 388 BufferState state = {temporal_idx, timestamp_, is_sync_frame}; |
| 389 if (tl_config.last_buffer_flags & TemporalLayers::kUpdate) |
| 390 last_state = state; |
| 391 if (tl_config.golden_buffer_flags & TemporalLayers::kUpdate) |
| 392 golden_state = state; |
| 393 if (tl_config.arf_buffer_flags & TemporalLayers::kUpdate) |
| 394 altref_state = state; |
| 395 } |
| 396 } |
| 397 } // namespace test |
| 238 } // namespace webrtc | 398 } // namespace webrtc |
| OLD | NEW |