Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: media/cast/test/simulator.cc

Issue 362123005: Cast: Update simulator tool with more inputs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: namespace Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/cast/test/proto/network_simulation_model.proto ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Simulate end to end streaming. 5 // Simulate end to end streaming.
6 // 6 //
7 // Input: 7 // Input:
8 // --source= 8 // --source=
9 // WebM used as the source of video and audio frames. 9 // WebM used as the source of video and audio frames.
10 // --output= 10 // --output=
(...skipping 28 matching lines...) Expand all
39 #include "media/cast/cast_sender.h" 39 #include "media/cast/cast_sender.h"
40 #include "media/cast/logging/encoding_event_subscriber.h" 40 #include "media/cast/logging/encoding_event_subscriber.h"
41 #include "media/cast/logging/log_serializer.h" 41 #include "media/cast/logging/log_serializer.h"
42 #include "media/cast/logging/logging_defines.h" 42 #include "media/cast/logging/logging_defines.h"
43 #include "media/cast/logging/proto/raw_events.pb.h" 43 #include "media/cast/logging/proto/raw_events.pb.h"
44 #include "media/cast/logging/raw_event_subscriber_bundle.h" 44 #include "media/cast/logging/raw_event_subscriber_bundle.h"
45 #include "media/cast/logging/simple_event_subscriber.h" 45 #include "media/cast/logging/simple_event_subscriber.h"
46 #include "media/cast/test/fake_media_source.h" 46 #include "media/cast/test/fake_media_source.h"
47 #include "media/cast/test/fake_single_thread_task_runner.h" 47 #include "media/cast/test/fake_single_thread_task_runner.h"
48 #include "media/cast/test/loopback_transport.h" 48 #include "media/cast/test/loopback_transport.h"
49 #include "media/cast/test/proto/network_simulation_model.pb.h"
49 #include "media/cast/test/skewed_tick_clock.h" 50 #include "media/cast/test/skewed_tick_clock.h"
50 #include "media/cast/test/utility/audio_utility.h" 51 #include "media/cast/test/utility/audio_utility.h"
51 #include "media/cast/test/utility/default_config.h" 52 #include "media/cast/test/utility/default_config.h"
52 #include "media/cast/test/utility/test_util.h" 53 #include "media/cast/test/utility/test_util.h"
53 #include "media/cast/test/utility/udp_proxy.h" 54 #include "media/cast/test/utility/udp_proxy.h"
54 #include "media/cast/test/utility/video_utility.h" 55 #include "media/cast/test/utility/video_utility.h"
55 #include "media/cast/transport/cast_transport_config.h" 56 #include "media/cast/transport/cast_transport_config.h"
56 #include "media/cast/transport/cast_transport_defines.h" 57 #include "media/cast/transport/cast_transport_defines.h"
57 #include "media/cast/transport/cast_transport_sender.h" 58 #include "media/cast/transport/cast_transport_sender.h"
58 #include "media/cast/transport/cast_transport_sender_impl.h" 59 #include "media/cast/transport/cast_transport_sender_impl.h"
59 60
61 using media::cast::proto::IPPModel;
62 using media::cast::proto::NetworkSimulationModel;
63 using media::cast::proto::NetworkSimulationModelType;
64
60 namespace media { 65 namespace media {
61 namespace cast { 66 namespace cast {
62 namespace { 67 namespace {
63
64 const int kTargetDelay = 300; 68 const int kTargetDelay = 300;
65 const char kSourcePath[] = "source"; 69 const char kSourcePath[] = "source";
70 const char kModelPath[] = "model";
66 const char kOutputPath[] = "output"; 71 const char kOutputPath[] = "output";
67 const char kSimulationId[] = "sim-id"; 72 const char kSimulationId[] = "sim-id";
73 const char kLibDir[] = "lib-dir";
68 74
69 void UpdateCastTransportStatus(transport::CastTransportStatus status) { 75 void UpdateCastTransportStatus(transport::CastTransportStatus status) {
70 LOG(INFO) << "Cast transport status: " << status; 76 LOG(INFO) << "Cast transport status: " << status;
71 } 77 }
72 78
73 void AudioInitializationStatus(CastInitializationStatus status) { 79 void AudioInitializationStatus(CastInitializationStatus status) {
74 LOG(INFO) << "Audio status: " << status; 80 LOG(INFO) << "Audio status: " << status;
75 } 81 }
76 82
77 void VideoInitializationStatus(CastInitializationStatus status) { 83 void VideoInitializationStatus(CastInitializationStatus status) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 LOG(ERROR) << "Failed to append to log."; 157 LOG(ERROR) << "Failed to append to log.";
152 } 158 }
153 } 159 }
154 160
155 // Run simulation once. 161 // Run simulation once.
156 // 162 //
157 // |output_path| is the path to write serialized log. 163 // |output_path| is the path to write serialized log.
158 // |extra_data| is extra tagging information to write to log. 164 // |extra_data| is extra tagging information to write to log.
159 void RunSimulation(const base::FilePath& source_path, 165 void RunSimulation(const base::FilePath& source_path,
160 const base::FilePath& output_path, 166 const base::FilePath& output_path,
161 const std::string& extra_data) { 167 const std::string& extra_data,
168 const NetworkSimulationModel& model) {
162 // Fake clock. Make sure start time is non zero. 169 // Fake clock. Make sure start time is non zero.
163 base::SimpleTestTickClock testing_clock; 170 base::SimpleTestTickClock testing_clock;
164 testing_clock.Advance(base::TimeDelta::FromSeconds(1)); 171 testing_clock.Advance(base::TimeDelta::FromSeconds(1));
165 172
166 // Task runner. 173 // Task runner.
167 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner = 174 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner =
168 new test::FakeSingleThreadTaskRunner(&testing_clock); 175 new test::FakeSingleThreadTaskRunner(&testing_clock);
169 base::ThreadTaskRunnerHandle task_runner_handle(task_runner); 176 base::ThreadTaskRunnerHandle task_runner_handle(task_runner);
170 177
171 // CastEnvironments. 178 // CastEnvironments.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 net::IPEndPoint(), 243 net::IPEndPoint(),
237 base::Bind(&UpdateCastTransportStatus), 244 base::Bind(&UpdateCastTransportStatus),
238 base::Bind(&LogTransportEvents, sender_env), 245 base::Bind(&LogTransportEvents, sender_env),
239 base::TimeDelta::FromSeconds(1), 246 base::TimeDelta::FromSeconds(1),
240 task_runner, 247 task_runner,
241 &sender_to_receiver)); 248 &sender_to_receiver));
242 scoped_ptr<CastSender> cast_sender( 249 scoped_ptr<CastSender> cast_sender(
243 CastSender::Create(sender_env, transport_sender.get())); 250 CastSender::Create(sender_env, transport_sender.get()));
244 251
245 // Build packet pipe. 252 // Build packet pipe.
246 // TODO(hclam): Allow user to input these parameters. Following 253 if (model.type() != media::cast::proto::INTERRUPTED_POISSON_PROCESS) {
247 // parameters are taken from a session from real-world data. It is 254 LOG(ERROR) << "Unknown model type " << model.type() << ".";
248 // chosen here because it gives a difficult environment. 255 return;
249 std::vector<double> average_rates; 256 }
250 average_rates.push_back(0.609); 257
251 average_rates.push_back(0.495); 258 const IPPModel& ipp_model = model.ipp();
252 average_rates.push_back(0.561); 259
253 average_rates.push_back(0.458); 260 std::vector<double> average_rates(ipp_model.average_rate_size());
254 average_rates.push_back(0.538); 261 std::copy(ipp_model.average_rate().begin(), ipp_model.average_rate().end(),
255 average_rates.push_back(0.513); 262 average_rates.begin());
256 average_rates.push_back(0.585); 263 test::InterruptedPoissonProcess ipp(average_rates,
257 average_rates.push_back(0.592); 264 ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0);
258 average_rates.push_back(0.658);
259 average_rates.push_back(0.556);
260 average_rates.push_back(0.371);
261 average_rates.push_back(0.595);
262 average_rates.push_back(0.490);
263 average_rates.push_back(0.980);
264 average_rates.push_back(0.781);
265 average_rates.push_back(0.463);
266 test::InterruptedPoissonProcess ipp(average_rates, 0.3, 4.1, 0);
267 265
268 // Connect sender to receiver. This initializes the pipe. 266 // Connect sender to receiver. This initializes the pipe.
269 receiver_to_sender.Initialize( 267 receiver_to_sender.Initialize(
270 ipp.NewBuffer(128 * 1024), cast_sender->packet_receiver(), task_runner, 268 ipp.NewBuffer(128 * 1024), cast_sender->packet_receiver(), task_runner,
271 &testing_clock); 269 &testing_clock);
272 sender_to_receiver.Initialize( 270 sender_to_receiver.Initialize(
273 ipp.NewBuffer(128 * 1024), cast_receiver->packet_receiver(), task_runner, 271 ipp.NewBuffer(128 * 1024), cast_receiver->packet_receiver(), task_runner,
274 &testing_clock); 272 &testing_clock);
275 273
276 // Start receiver. 274 // Start receiver.
(...skipping 17 matching lines...) Expand all
294 CreateDefaultVideoEncodeMemoryCallback()); 292 CreateDefaultVideoEncodeMemoryCallback());
295 293
296 // Start sending. 294 // Start sending.
297 if (!source_path.empty()) { 295 if (!source_path.empty()) {
298 // 0 means using the FPS from the file. 296 // 0 means using the FPS from the file.
299 media_source.SetSourceFile(source_path, 0); 297 media_source.SetSourceFile(source_path, 0);
300 } 298 }
301 media_source.Start(cast_sender->audio_frame_input(), 299 media_source.Start(cast_sender->audio_frame_input(),
302 cast_sender->video_frame_input()); 300 cast_sender->video_frame_input());
303 301
304 // Run for 5 minutes. 302 // Run for 3 minutes.
305 base::TimeDelta elapsed_time; 303 base::TimeDelta elapsed_time;
306 while (elapsed_time.InMinutes() < 5) { 304 while (elapsed_time.InMinutes() < 3) {
307 // Each step is 100us. 305 // Each step is 100us.
308 base::TimeDelta step = base::TimeDelta::FromMicroseconds(100); 306 base::TimeDelta step = base::TimeDelta::FromMicroseconds(100);
309 task_runner->Sleep(step); 307 task_runner->Sleep(step);
310 elapsed_time += step; 308 elapsed_time += step;
311 } 309 }
312 310
313 LOG(INFO) << "Audio frame count: " << audio_frame_count; 311 LOG(INFO) << "Audio frame count: " << audio_frame_count;
314 LOG(INFO) << "Video frame count: " << video_frame_count; 312 LOG(INFO) << "Video frame count: " << video_frame_count;
315 LOG(INFO) << "Writing log: " << output_path.value(); 313 LOG(INFO) << "Writing log: " << output_path.value();
316 314
317 // Truncate file and then write serialized log. 315 // Truncate file and then write serialized log.
318 { 316 {
319 base::ScopedFILE file(base::OpenFile(output_path, "wb")); 317 base::ScopedFILE file(base::OpenFile(output_path, "wb"));
320 if (!file.get()) { 318 if (!file.get()) {
321 LOG(INFO) << "Cannot write to log."; 319 LOG(INFO) << "Cannot write to log.";
322 return; 320 return;
323 } 321 }
324 } 322 }
325 AppendLog(&video_event_subscriber, extra_data, output_path); 323 AppendLog(&video_event_subscriber, extra_data, output_path);
326 AppendLog(&audio_event_subscriber, extra_data, output_path); 324 AppendLog(&audio_event_subscriber, extra_data, output_path);
327 } 325 }
328 326
327 NetworkSimulationModel DefaultModel() {
328 NetworkSimulationModel model;
329 model.set_type(cast::proto::INTERRUPTED_POISSON_PROCESS);
330 IPPModel* ipp = model.mutable_ipp();
331 ipp->set_coef_burstiness(0.609);
332 ipp->set_coef_variance(4.1);
333
334 ipp->add_average_rate(0.609);
335 ipp->add_average_rate(0.495);
336 ipp->add_average_rate(0.561);
337 ipp->add_average_rate(0.458);
338 ipp->add_average_rate(0.538);
339 ipp->add_average_rate(0.513);
340 ipp->add_average_rate(0.585);
341 ipp->add_average_rate(0.592);
342 ipp->add_average_rate(0.658);
343 ipp->add_average_rate(0.556);
344 ipp->add_average_rate(0.371);
345 ipp->add_average_rate(0.595);
346 ipp->add_average_rate(0.490);
347 ipp->add_average_rate(0.980);
348 ipp->add_average_rate(0.781);
349 ipp->add_average_rate(0.463);
350
351 return model;
352 }
353
354 bool IsModelValid(const NetworkSimulationModel& model) {
355 if (!model.has_type())
356 return false;
357 NetworkSimulationModelType type = model.type();
358 if (type == media::cast::proto::INTERRUPTED_POISSON_PROCESS) {
359 if (!model.has_ipp())
360 return false;
361 const IPPModel& ipp = model.ipp();
362 if (ipp.coef_burstiness() <= 0.0 || ipp.coef_variance() <= 0.0)
363 return false;
364 if (ipp.average_rate_size() == 0)
365 return false;
366 for (int i = 0; i < ipp.average_rate_size(); i++) {
367 if (ipp.average_rate(i) <= 0.0)
368 return false;
369 }
370 }
371
372 return true;
373 }
374
375 NetworkSimulationModel LoadModel(const base::FilePath& model_path) {
376 if (model_path.empty()) {
377 LOG(ERROR) << "Model path not set.";
378 return DefaultModel();
379 }
380 std::string model_str;
381 if (!base::ReadFileToString(model_path, &model_str)) {
382 LOG(ERROR) << "Failed to read model file.";
383 return DefaultModel();
384 }
385
386 NetworkSimulationModel model;
387 if (!model.ParseFromString(model_str)) {
388 LOG(ERROR) << "Failed to parse model.";
389 return DefaultModel();
390 }
391 if (!IsModelValid(model)) {
392 LOG(ERROR) << "Invalid model.";
393 return DefaultModel();
394 }
395
396 return model;
397 }
398
329 } // namespace 399 } // namespace
330 } // namespace cast 400 } // namespace cast
331 } // namespace media 401 } // namespace media
332 402
333 int main(int argc, char** argv) { 403 int main(int argc, char** argv) {
334 base::AtExitManager at_exit; 404 base::AtExitManager at_exit;
335 CommandLine::Init(argc, argv); 405 CommandLine::Init(argc, argv);
336 InitLogging(logging::LoggingSettings()); 406 InitLogging(logging::LoggingSettings());
337 407
338 base::FilePath media_path; 408 const CommandLine* cmd = CommandLine::ForCurrentProcess();
339 if (!PathService::Get(base::DIR_MODULE, &media_path)) { 409 base::FilePath media_path = cmd->GetSwitchValuePath(media::cast::kLibDir);
340 LOG(ERROR) << "Failed to load FFmpeg."; 410 if (media_path.empty()) {
411 if (!PathService::Get(base::DIR_MODULE, &media_path)) {
412 LOG(ERROR) << "Failed to load FFmpeg.";
413 return 1;
414 }
415 }
416
417 if (!media::InitializeMediaLibrary(media_path)) {
418 LOG(ERROR) << "Failed to initialize FFmpeg.";
341 return 1; 419 return 1;
342 } 420 }
343 media::InitializeMediaLibrary(media_path);
344 421
345 const CommandLine* cmd = CommandLine::ForCurrentProcess();
346 base::FilePath source_path = cmd->GetSwitchValuePath( 422 base::FilePath source_path = cmd->GetSwitchValuePath(
347 media::cast::kSourcePath); 423 media::cast::kSourcePath);
348 base::FilePath output_path = cmd->GetSwitchValuePath( 424 base::FilePath output_path = cmd->GetSwitchValuePath(
349 media::cast::kOutputPath); 425 media::cast::kOutputPath);
350 if (output_path.empty()) { 426 if (output_path.empty()) {
351 base::GetTempDir(&output_path); 427 base::GetTempDir(&output_path);
352 output_path = output_path.AppendASCII("sim-events.gz"); 428 output_path = output_path.AppendASCII("sim-events.gz");
353 } 429 }
354 std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId); 430 std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId);
355 431
432 NetworkSimulationModel model = media::cast::LoadModel(
433 cmd->GetSwitchValuePath(media::cast::kModelPath));
434
356 base::DictionaryValue values; 435 base::DictionaryValue values;
357 values.SetBoolean("sim", true); 436 values.SetBoolean("sim", true);
358 values.SetString("sim-id", sim_id); 437 values.SetString("sim-id", sim_id);
359 438
360 std::string extra_data; 439 std::string extra_data;
361 base::JSONWriter::Write(&values, &extra_data); 440 base::JSONWriter::Write(&values, &extra_data);
362 441
363 // Run. 442 // Run.
364 media::cast::RunSimulation(source_path, output_path, extra_data); 443 media::cast::RunSimulation(source_path, output_path, extra_data, model);
365 return 0; 444 return 0;
366 } 445 }
OLDNEW
« no previous file with comments | « media/cast/test/proto/network_simulation_model.proto ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698