diff options
-rw-r--r-- | media/cast/cast_testing.gypi | 17 | ||||
-rw-r--r-- | media/cast/test/proto/BUILD.gn | 14 | ||||
-rw-r--r-- | media/cast/test/proto/network_simulation_model.proto | 27 | ||||
-rw-r--r-- | media/cast/test/simulator.cc | 141 |
4 files changed, 168 insertions, 31 deletions
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi index 41d3965..e6c7c56 100644 --- a/media/cast/cast_testing.gypi +++ b/media/cast/cast_testing.gypi @@ -240,6 +240,7 @@ ], 'dependencies': [ 'cast_base', + 'cast_network_model_proto', 'cast_sender', 'cast_test_utility', 'cast_transport', @@ -255,6 +256,22 @@ ], }, { + # GN version: //media/cast/test/proto + 'target_name': 'cast_network_model_proto', + 'type': 'static_library', + 'include_dirs': [ + '<(DEPTH)/', + ], + 'sources': [ + 'test/proto/network_simulation_model.proto', + ], + 'variables': { + 'proto_in_dir': 'test/proto', + 'proto_out_dir': 'media/cast/test/proto', + }, + 'includes': ['../../build/protoc.gypi'], + }, + { 'target_name': 'generate_barcode_video', 'type': 'executable', 'include_dirs': [ diff --git a/media/cast/test/proto/BUILD.gn b/media/cast/test/proto/BUILD.gn new file mode 100644 index 0000000..7ac71d2 --- /dev/null +++ b/media/cast/test/proto/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/protobuf/proto_library.gni") + +# GYP version: media/cast/cast.gyp:cast_logging_proto +proto_library("cast_network_simulation_proto") { + visibility = ":proto" + sources = [ + "network_simulation_model.proto", + ] +} + diff --git a/media/cast/test/proto/network_simulation_model.proto b/media/cast/test/proto/network_simulation_model.proto new file mode 100644 index 0000000..902712f --- /dev/null +++ b/media/cast/test/proto/network_simulation_model.proto @@ -0,0 +1,27 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Contains parameters for a network simulation model. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package media.cast.proto; + +message NetworkSimulationModel { + optional NetworkSimulationModelType type = 1; + optional IPPModel ipp = 2; +} + +enum NetworkSimulationModelType { + INTERRUPTED_POISSON_PROCESS = 1; +} + +message IPPModel { + optional double coef_burstiness = 1; + optional double coef_variance = 2; + repeated double average_rate = 3; +} + diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc index b96f479..c9a750b 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc @@ -46,6 +46,7 @@ #include "media/cast/test/fake_media_source.h" #include "media/cast/test/fake_single_thread_task_runner.h" #include "media/cast/test/loopback_transport.h" +#include "media/cast/test/proto/network_simulation_model.pb.h" #include "media/cast/test/skewed_tick_clock.h" #include "media/cast/test/utility/audio_utility.h" #include "media/cast/test/utility/default_config.h" @@ -57,14 +58,19 @@ #include "media/cast/transport/cast_transport_sender.h" #include "media/cast/transport/cast_transport_sender_impl.h" +using media::cast::proto::IPPModel; +using media::cast::proto::NetworkSimulationModel; +using media::cast::proto::NetworkSimulationModelType; + namespace media { namespace cast { namespace { - const int kTargetDelay = 300; const char kSourcePath[] = "source"; +const char kModelPath[] = "model"; const char kOutputPath[] = "output"; const char kSimulationId[] = "sim-id"; +const char kLibDir[] = "lib-dir"; void UpdateCastTransportStatus(transport::CastTransportStatus status) { LOG(INFO) << "Cast transport status: " << status; @@ -158,7 +164,8 @@ void AppendLog(EncodingEventSubscriber* subscriber, // |extra_data| is extra tagging information to write to log. void RunSimulation(const base::FilePath& source_path, const base::FilePath& output_path, - const std::string& extra_data) { + const std::string& extra_data, + const NetworkSimulationModel& model) { // Fake clock. Make sure start time is non zero. base::SimpleTestTickClock testing_clock; testing_clock.Advance(base::TimeDelta::FromSeconds(1)); @@ -243,27 +250,18 @@ void RunSimulation(const base::FilePath& source_path, CastSender::Create(sender_env, transport_sender.get())); // Build packet pipe. - // TODO(hclam): Allow user to input these parameters. Following - // parameters are taken from a session from real-world data. It is - // chosen here because it gives a difficult environment. - std::vector<double> average_rates; - average_rates.push_back(0.609); - average_rates.push_back(0.495); - average_rates.push_back(0.561); - average_rates.push_back(0.458); - average_rates.push_back(0.538); - average_rates.push_back(0.513); - average_rates.push_back(0.585); - average_rates.push_back(0.592); - average_rates.push_back(0.658); - average_rates.push_back(0.556); - average_rates.push_back(0.371); - average_rates.push_back(0.595); - average_rates.push_back(0.490); - average_rates.push_back(0.980); - average_rates.push_back(0.781); - average_rates.push_back(0.463); - test::InterruptedPoissonProcess ipp(average_rates, 0.3, 4.1, 0); + if (model.type() != media::cast::proto::INTERRUPTED_POISSON_PROCESS) { + LOG(ERROR) << "Unknown model type " << model.type() << "."; + return; + } + + const IPPModel& ipp_model = model.ipp(); + + std::vector<double> average_rates(ipp_model.average_rate_size()); + std::copy(ipp_model.average_rate().begin(), ipp_model.average_rate().end(), + average_rates.begin()); + test::InterruptedPoissonProcess ipp(average_rates, + ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0); // Connect sender to receiver. This initializes the pipe. receiver_to_sender.Initialize( @@ -301,9 +299,9 @@ void RunSimulation(const base::FilePath& source_path, media_source.Start(cast_sender->audio_frame_input(), cast_sender->video_frame_input()); - // Run for 5 minutes. + // Run for 3 minutes. base::TimeDelta elapsed_time; - while (elapsed_time.InMinutes() < 5) { + while (elapsed_time.InMinutes() < 3) { // Each step is 100us. base::TimeDelta step = base::TimeDelta::FromMicroseconds(100); task_runner->Sleep(step); @@ -326,6 +324,78 @@ void RunSimulation(const base::FilePath& source_path, AppendLog(&audio_event_subscriber, extra_data, output_path); } +NetworkSimulationModel DefaultModel() { + NetworkSimulationModel model; + model.set_type(cast::proto::INTERRUPTED_POISSON_PROCESS); + IPPModel* ipp = model.mutable_ipp(); + ipp->set_coef_burstiness(0.609); + ipp->set_coef_variance(4.1); + + ipp->add_average_rate(0.609); + ipp->add_average_rate(0.495); + ipp->add_average_rate(0.561); + ipp->add_average_rate(0.458); + ipp->add_average_rate(0.538); + ipp->add_average_rate(0.513); + ipp->add_average_rate(0.585); + ipp->add_average_rate(0.592); + ipp->add_average_rate(0.658); + ipp->add_average_rate(0.556); + ipp->add_average_rate(0.371); + ipp->add_average_rate(0.595); + ipp->add_average_rate(0.490); + ipp->add_average_rate(0.980); + ipp->add_average_rate(0.781); + ipp->add_average_rate(0.463); + + return model; +} + +bool IsModelValid(const NetworkSimulationModel& model) { + if (!model.has_type()) + return false; + NetworkSimulationModelType type = model.type(); + if (type == media::cast::proto::INTERRUPTED_POISSON_PROCESS) { + if (!model.has_ipp()) + return false; + const IPPModel& ipp = model.ipp(); + if (ipp.coef_burstiness() <= 0.0 || ipp.coef_variance() <= 0.0) + return false; + if (ipp.average_rate_size() == 0) + return false; + for (int i = 0; i < ipp.average_rate_size(); i++) { + if (ipp.average_rate(i) <= 0.0) + return false; + } + } + + return true; +} + +NetworkSimulationModel LoadModel(const base::FilePath& model_path) { + if (model_path.empty()) { + LOG(ERROR) << "Model path not set."; + return DefaultModel(); + } + std::string model_str; + if (!base::ReadFileToString(model_path, &model_str)) { + LOG(ERROR) << "Failed to read model file."; + return DefaultModel(); + } + + NetworkSimulationModel model; + if (!model.ParseFromString(model_str)) { + LOG(ERROR) << "Failed to parse model."; + return DefaultModel(); + } + if (!IsModelValid(model)) { + LOG(ERROR) << "Invalid model."; + return DefaultModel(); + } + + return model; +} + } // namespace } // namespace cast } // namespace media @@ -335,14 +405,20 @@ int main(int argc, char** argv) { CommandLine::Init(argc, argv); InitLogging(logging::LoggingSettings()); - base::FilePath media_path; - if (!PathService::Get(base::DIR_MODULE, &media_path)) { - LOG(ERROR) << "Failed to load FFmpeg."; + const CommandLine* cmd = CommandLine::ForCurrentProcess(); + base::FilePath media_path = cmd->GetSwitchValuePath(media::cast::kLibDir); + if (media_path.empty()) { + if (!PathService::Get(base::DIR_MODULE, &media_path)) { + LOG(ERROR) << "Failed to load FFmpeg."; + return 1; + } + } + + if (!media::InitializeMediaLibrary(media_path)) { + LOG(ERROR) << "Failed to initialize FFmpeg."; return 1; } - media::InitializeMediaLibrary(media_path); - const CommandLine* cmd = CommandLine::ForCurrentProcess(); base::FilePath source_path = cmd->GetSwitchValuePath( media::cast::kSourcePath); base::FilePath output_path = cmd->GetSwitchValuePath( @@ -353,6 +429,9 @@ int main(int argc, char** argv) { } std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId); + NetworkSimulationModel model = media::cast::LoadModel( + cmd->GetSwitchValuePath(media::cast::kModelPath)); + base::DictionaryValue values; values.SetBoolean("sim", true); values.SetString("sim-id", sim_id); @@ -361,6 +440,6 @@ int main(int argc, char** argv) { base::JSONWriter::Write(&values, &extra_data); // Run. - media::cast::RunSimulation(source_path, output_path, extra_data); + media::cast::RunSimulation(source_path, output_path, extra_data, model); return 0; } |