Commit 20164ce4 authored by imcheng@chromium.org's avatar imcheng@chromium.org

Cast: Update simulator tool with more inputs.

Inputs:
- directory to libffmpegsumo.so.
- network simulation parameters given as a proto.

BUG=none

Review URL: https://codereview.chromium.org/362123005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282496 0039d316-1c4b-4281-b951-d872f2087c98
parent dfdde4a9
...@@ -240,6 +240,7 @@ ...@@ -240,6 +240,7 @@
], ],
'dependencies': [ 'dependencies': [
'cast_base', 'cast_base',
'cast_network_model_proto',
'cast_sender', 'cast_sender',
'cast_test_utility', 'cast_test_utility',
'cast_transport', 'cast_transport',
...@@ -254,6 +255,22 @@ ...@@ -254,6 +255,22 @@
'<(DEPTH)/media/cast/test/simulator.cc', '<(DEPTH)/media/cast/test/simulator.cc',
], ],
}, },
{
# 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', 'target_name': 'generate_barcode_video',
'type': 'executable', 'type': 'executable',
......
# 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",
]
}
// 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;
}
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "media/cast/test/fake_media_source.h" #include "media/cast/test/fake_media_source.h"
#include "media/cast/test/fake_single_thread_task_runner.h" #include "media/cast/test/fake_single_thread_task_runner.h"
#include "media/cast/test/loopback_transport.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/skewed_tick_clock.h"
#include "media/cast/test/utility/audio_utility.h" #include "media/cast/test/utility/audio_utility.h"
#include "media/cast/test/utility/default_config.h" #include "media/cast/test/utility/default_config.h"
...@@ -57,14 +58,19 @@ ...@@ -57,14 +58,19 @@
#include "media/cast/transport/cast_transport_sender.h" #include "media/cast/transport/cast_transport_sender.h"
#include "media/cast/transport/cast_transport_sender_impl.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 media {
namespace cast { namespace cast {
namespace { namespace {
const int kTargetDelay = 300; const int kTargetDelay = 300;
const char kSourcePath[] = "source"; const char kSourcePath[] = "source";
const char kModelPath[] = "model";
const char kOutputPath[] = "output"; const char kOutputPath[] = "output";
const char kSimulationId[] = "sim-id"; const char kSimulationId[] = "sim-id";
const char kLibDir[] = "lib-dir";
void UpdateCastTransportStatus(transport::CastTransportStatus status) { void UpdateCastTransportStatus(transport::CastTransportStatus status) {
LOG(INFO) << "Cast transport status: " << status; LOG(INFO) << "Cast transport status: " << status;
...@@ -158,7 +164,8 @@ void AppendLog(EncodingEventSubscriber* subscriber, ...@@ -158,7 +164,8 @@ void AppendLog(EncodingEventSubscriber* subscriber,
// |extra_data| is extra tagging information to write to log. // |extra_data| is extra tagging information to write to log.
void RunSimulation(const base::FilePath& source_path, void RunSimulation(const base::FilePath& source_path,
const base::FilePath& output_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. // Fake clock. Make sure start time is non zero.
base::SimpleTestTickClock testing_clock; base::SimpleTestTickClock testing_clock;
testing_clock.Advance(base::TimeDelta::FromSeconds(1)); testing_clock.Advance(base::TimeDelta::FromSeconds(1));
...@@ -243,27 +250,18 @@ void RunSimulation(const base::FilePath& source_path, ...@@ -243,27 +250,18 @@ void RunSimulation(const base::FilePath& source_path,
CastSender::Create(sender_env, transport_sender.get())); CastSender::Create(sender_env, transport_sender.get()));
// Build packet pipe. // Build packet pipe.
// TODO(hclam): Allow user to input these parameters. Following if (model.type() != media::cast::proto::INTERRUPTED_POISSON_PROCESS) {
// parameters are taken from a session from real-world data. It is LOG(ERROR) << "Unknown model type " << model.type() << ".";
// chosen here because it gives a difficult environment. return;
std::vector<double> average_rates; }
average_rates.push_back(0.609);
average_rates.push_back(0.495); const IPPModel& ipp_model = model.ipp();
average_rates.push_back(0.561);
average_rates.push_back(0.458); std::vector<double> average_rates(ipp_model.average_rate_size());
average_rates.push_back(0.538); std::copy(ipp_model.average_rate().begin(), ipp_model.average_rate().end(),
average_rates.push_back(0.513); average_rates.begin());
average_rates.push_back(0.585); test::InterruptedPoissonProcess ipp(average_rates,
average_rates.push_back(0.592); ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0);
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);
// Connect sender to receiver. This initializes the pipe. // Connect sender to receiver. This initializes the pipe.
receiver_to_sender.Initialize( receiver_to_sender.Initialize(
...@@ -301,9 +299,9 @@ void RunSimulation(const base::FilePath& source_path, ...@@ -301,9 +299,9 @@ void RunSimulation(const base::FilePath& source_path,
media_source.Start(cast_sender->audio_frame_input(), media_source.Start(cast_sender->audio_frame_input(),
cast_sender->video_frame_input()); cast_sender->video_frame_input());
// Run for 5 minutes. // Run for 3 minutes.
base::TimeDelta elapsed_time; base::TimeDelta elapsed_time;
while (elapsed_time.InMinutes() < 5) { while (elapsed_time.InMinutes() < 3) {
// Each step is 100us. // Each step is 100us.
base::TimeDelta step = base::TimeDelta::FromMicroseconds(100); base::TimeDelta step = base::TimeDelta::FromMicroseconds(100);
task_runner->Sleep(step); task_runner->Sleep(step);
...@@ -326,6 +324,78 @@ void RunSimulation(const base::FilePath& source_path, ...@@ -326,6 +324,78 @@ void RunSimulation(const base::FilePath& source_path,
AppendLog(&audio_event_subscriber, extra_data, output_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
} // namespace cast } // namespace cast
} // namespace media } // namespace media
...@@ -335,14 +405,20 @@ int main(int argc, char** argv) { ...@@ -335,14 +405,20 @@ int main(int argc, char** argv) {
CommandLine::Init(argc, argv); CommandLine::Init(argc, argv);
InitLogging(logging::LoggingSettings()); InitLogging(logging::LoggingSettings());
base::FilePath media_path; const CommandLine* cmd = CommandLine::ForCurrentProcess();
if (!PathService::Get(base::DIR_MODULE, &media_path)) { base::FilePath media_path = cmd->GetSwitchValuePath(media::cast::kLibDir);
LOG(ERROR) << "Failed to load FFmpeg."; 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; return 1;
} }
media::InitializeMediaLibrary(media_path);
const CommandLine* cmd = CommandLine::ForCurrentProcess();
base::FilePath source_path = cmd->GetSwitchValuePath( base::FilePath source_path = cmd->GetSwitchValuePath(
media::cast::kSourcePath); media::cast::kSourcePath);
base::FilePath output_path = cmd->GetSwitchValuePath( base::FilePath output_path = cmd->GetSwitchValuePath(
...@@ -353,6 +429,9 @@ int main(int argc, char** argv) { ...@@ -353,6 +429,9 @@ int main(int argc, char** argv) {
} }
std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId); std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId);
NetworkSimulationModel model = media::cast::LoadModel(
cmd->GetSwitchValuePath(media::cast::kModelPath));
base::DictionaryValue values; base::DictionaryValue values;
values.SetBoolean("sim", true); values.SetBoolean("sim", true);
values.SetString("sim-id", sim_id); values.SetString("sim-id", sim_id);
...@@ -361,6 +440,6 @@ int main(int argc, char** argv) { ...@@ -361,6 +440,6 @@ int main(int argc, char** argv) {
base::JSONWriter::Write(&values, &extra_data); base::JSONWriter::Write(&values, &extra_data);
// Run. // Run.
media::cast::RunSimulation(source_path, output_path, extra_data); media::cast::RunSimulation(source_path, output_path, extra_data, model);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment