1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Simulate end to end streaming. 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Input: 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// --source= 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// WebM used as the source of video and audio frames. 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// --output= 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// File path to writing out the raw event log of the simulation session. 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// --sim-id= 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Unique simulation ID. 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// --target-delay-ms= 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Target playout delay to configure (integer number of milliseconds). 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Optional; default is 400. 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Output: 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// - Raw event log of the simulation session tagged with the unique test ID, 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// written out to the specified file path. 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/at_exit.h" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/base_paths.h" 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/command_line.h" 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/file_path.h" 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/memory_mapped_file.h" 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/scoped_file.h" 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/json/json_writer.h" 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h" 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/path_service.h" 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/strings/string_number_conversions.h" 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/test/simple_test_tick_clock.h" 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h" 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/time/tick_clock.h" 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/values.h" 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/base/audio_bus.h" 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/base/media.h" 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/base/video_frame.h" 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/cast_config.h" 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/cast_environment.h" 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/cast_receiver.h" 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/cast_sender.h" 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/encoding_event_subscriber.h" 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/log_serializer.h" 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/logging_defines.h" 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/proto/raw_events.pb.h" 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/raw_event_subscriber_bundle.h" 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/logging/simple_event_subscriber.h" 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_config.h" 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_defines.h" 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_sender.h" 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_sender_impl.h" 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/fake_media_source.h" 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/fake_single_thread_task_runner.h" 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/loopback_transport.h" 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/proto/network_simulation_model.pb.h" 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/skewed_tick_clock.h" 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/utility/audio_utility.h" 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/utility/default_config.h" 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/utility/test_util.h" 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/utility/udp_proxy.h" 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/test/utility/video_utility.h" 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing media::cast::proto::IPPModel; 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing media::cast::proto::NetworkSimulationModel; 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing media::cast::proto::NetworkSimulationModelType; 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace media { 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace cast { 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kSourcePath[] = "source"; 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kModelPath[] = "model"; 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kOutputPath[] = "output"; 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kSimulationId[] = "sim-id"; 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst char kLibDir[] = "lib-dir"; 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst char kTargetDelay[] = "target-delay-ms"; 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibase::TimeDelta GetTargetPlayoutDelay() { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::string delay_str = 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kTargetDelay); 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (delay_str.empty()) 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return base::TimeDelta::FromMilliseconds(400); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int delay_ms; 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(base::StringToInt(delay_str, &delay_ms)); 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_GT(delay_ms, 0); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return base::TimeDelta::FromMilliseconds(delay_ms); 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UpdateCastTransportStatus(CastTransportStatus status) { 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Cast transport status: " << status; 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid AudioInitializationStatus(CastInitializationStatus status) { 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Audio status: " << status; 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid VideoInitializationStatus(CastInitializationStatus status) { 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Video status: " << status; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid LogTransportEvents(const scoped_refptr<CastEnvironment>& env, 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::vector<PacketEvent>& packet_events, 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::vector<FrameEvent>& frame_events) { 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (std::vector<media::cast::PacketEvent>::const_iterator it = 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch packet_events.begin(); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it != packet_events.end(); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch env->Logging()->InsertPacketEvent(it->timestamp, 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->type, 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->media_type, 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->rtp_timestamp, 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->frame_id, 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->packet_id, 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->max_packet_id, 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->size); 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (std::vector<media::cast::FrameEvent>::const_iterator it = 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame_events.begin(); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it != frame_events.end(); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++it) { 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (it->type == FRAME_PLAYOUT) { 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) env->Logging()->InsertFrameEventWithDelay( 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->timestamp, 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->type, 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->media_type, 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->rtp_timestamp, 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->frame_id, 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->delay_delta); 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) env->Logging()->InsertFrameEvent( 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->timestamp, 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->type, 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->media_type, 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->rtp_timestamp, 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->frame_id); 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GotVideoFrame( 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int* counter, 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CastReceiver* cast_receiver, 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const scoped_refptr<media::VideoFrame>& video_frame, 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeTicks& render_time, 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool continuous) { 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++*counter; 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_receiver->RequestDecodedVideoFrame( 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&GotVideoFrame, counter, cast_receiver)); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GotAudioFrame( 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int* counter, 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CastReceiver* cast_receiver, 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<AudioBus> audio_bus, 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeTicks& playout_time, 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool is_continuous) { 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++*counter; 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_receiver->RequestDecodedAudioFrame( 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&GotAudioFrame, counter, cast_receiver)); 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Serialize |frame_events| and |packet_events| and append to the file 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// located at |output_path|. 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AppendLogToFile(media::cast::proto::LogMetadata* metadata, 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const media::cast::FrameEventList& frame_events, 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const media::cast::PacketEventList& packet_events, 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const base::FilePath& output_path) { 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::cast::proto::GeneralDescription* gen_desc = 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) metadata->mutable_general_description(); 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gen_desc->set_product("Cast Simulator"); 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gen_desc->set_product_version("0.1"); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<char[]> serialized_log(new char[media::cast::kMaxSerializedBytes]); 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int output_bytes; 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool success = media::cast::SerializeEvents(*metadata, 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame_events, 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch packet_events, 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true, 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::cast::kMaxSerializedBytes, 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serialized_log.get(), 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &output_bytes); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!success) { 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to serialize log."; 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (AppendToFile(output_path, serialized_log.get(), output_bytes) == -1) { 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to append to log."; 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Run simulation once. 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// |output_path| is the path to write serialized log. 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// |extra_data| is extra tagging information to write to log. 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid RunSimulation(const base::FilePath& source_path, 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::FilePath& output_path, 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& extra_data, 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const NetworkSimulationModel& model) { 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Fake clock. Make sure start time is non zero. 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::SimpleTestTickClock testing_clock; 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch testing_clock.Advance(base::TimeDelta::FromSeconds(1)); 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Task runner. 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner = 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new test::FakeSingleThreadTaskRunner(&testing_clock); 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ThreadTaskRunnerHandle task_runner_handle(task_runner); 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // CastEnvironments. 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<CastEnvironment> sender_env = 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new CastEnvironment( 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<base::TickClock>( 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new test::SkewedTickClock(&testing_clock)).Pass(), 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner, 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner, 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner); 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<CastEnvironment> receiver_env = 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new CastEnvironment( 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<base::TickClock>( 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new test::SkewedTickClock(&testing_clock)).Pass(), 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner, 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner, 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Event subscriber. Store at most 1 hour of events. 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT, 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 100 * 60 * 60); 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 30 * 60 * 60); 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sender_env->Logging()->AddRawEventSubscriber(&audio_event_subscriber); 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sender_env->Logging()->AddRawEventSubscriber(&video_event_subscriber); 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Audio sender config. 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci audio_sender_config.max_playout_delay = GetTargetPlayoutDelay(); 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Audio receiver config. 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FrameReceiverConfig audio_receiver_config = 241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetDefaultAudioReceiverConfig(); 242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch audio_receiver_config.rtp_max_delay_ms = 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci audio_sender_config.max_playout_delay.InMilliseconds(); 244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Video sender config. 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig(); 24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) video_sender_config.max_bitrate = 2500000; 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch video_sender_config.min_bitrate = 2000000; 24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) video_sender_config.start_bitrate = 2000000; 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci video_sender_config.max_playout_delay = GetTargetPlayoutDelay(); 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Video receiver config. 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FrameReceiverConfig video_receiver_config = 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetDefaultVideoReceiverConfig(); 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch video_receiver_config.rtp_max_delay_ms = 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci video_sender_config.max_playout_delay.InMilliseconds(); 257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Loopback transport. 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LoopBackTransport receiver_to_sender(receiver_env); 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LoopBackTransport sender_to_receiver(sender_env); 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Cast receiver. 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<CastReceiver> cast_receiver( 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CastReceiver::Create(receiver_env, 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch audio_receiver_config, 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch video_receiver_config, 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &receiver_to_sender)); 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Cast sender and transport sender. 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<CastTransportSender> transport_sender( 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new CastTransportSenderImpl( 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &testing_clock, 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch net::IPEndPoint(), 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci make_scoped_ptr(new base::DictionaryValue), 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&UpdateCastTransportStatus), 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&LogTransportEvents, sender_env), 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta::FromSeconds(1), 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner, 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &sender_to_receiver)); 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<CastSender> cast_sender( 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CastSender::Create(sender_env, transport_sender.get())); 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Build packet pipe. 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (model.type() != media::cast::proto::INTERRUPTED_POISSON_PROCESS) { 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Unknown model type " << model.type() << "."; 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPPModel& ipp_model = model.ipp(); 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<double> average_rates(ipp_model.average_rate_size()); 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::copy(ipp_model.average_rate().begin(), ipp_model.average_rate().end(), 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch average_rates.begin()); 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch test::InterruptedPoissonProcess ipp(average_rates, 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0); 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Connect sender to receiver. This initializes the pipe. 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch receiver_to_sender.Initialize( 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ipp.NewBuffer(128 * 1024).Pass(), 3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) transport_sender->PacketReceiverForTesting(), 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) task_runner, &testing_clock); 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch sender_to_receiver.Initialize( 3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ipp.NewBuffer(128 * 1024).Pass(), 3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) cast_receiver->packet_receiver(), task_runner, 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &testing_clock); 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Start receiver. 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int audio_frame_count = 0; 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int video_frame_count = 0; 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_receiver->RequestDecodedVideoFrame( 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&GotVideoFrame, &video_frame_count, cast_receiver.get())); 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_receiver->RequestDecodedAudioFrame( 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&GotAudioFrame, &audio_frame_count, cast_receiver.get())); 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FakeMediaSource media_source(task_runner, 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &testing_clock, 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch video_sender_config); 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Initializing audio and video senders. 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_sender->InitializeAudio(audio_sender_config, 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&AudioInitializationStatus)); 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_sender->InitializeVideo(media_source.get_video_config(), 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&VideoInitializationStatus), 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateDefaultVideoEncodeAcceleratorCallback(), 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateDefaultVideoEncodeMemoryCallback()); 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner->RunTasks(); 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Start sending. 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!source_path.empty()) { 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 0 means using the FPS from the file. 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media_source.SetSourceFile(source_path, 0); 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media_source.Start(cast_sender->audio_frame_input(), 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cast_sender->video_frame_input()); 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Run for 3 minutes. 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta elapsed_time; 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch while (elapsed_time.InMinutes() < 3) { 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Each step is 100us. 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta step = base::TimeDelta::FromMicroseconds(100); 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_runner->Sleep(step); 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch elapsed_time += step; 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Get event logs for audio and video. 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media::cast::proto::LogMetadata audio_metadata, video_metadata; 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media::cast::FrameEventList audio_frame_events, video_frame_events; 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) media::cast::PacketEventList audio_packet_events, video_packet_events; 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) audio_metadata.set_extra_data(extra_data); 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_metadata.set_extra_data(extra_data); 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) audio_event_subscriber.GetEventsAndReset( 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &audio_metadata, &audio_frame_events, &audio_packet_events); 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) video_event_subscriber.GetEventsAndReset( 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &video_metadata, &video_frame_events, &video_packet_events); 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Print simulation results. 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Compute and print statistics for video: 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Total video frames captured. 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Total video frames encoded. 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Total video frames dropped. 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Total video frames received late. 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Average target bitrate. 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // * Average encoded bitrate. 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int total_video_frames = 0; 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int encoded_video_frames = 0; 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int dropped_video_frames = 0; 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int late_video_frames = 0; 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int64 total_delay_of_late_frames_ms = 0; 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 encoded_size = 0; 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int64 target_bitrate = 0; 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (size_t i = 0; i < video_frame_events.size(); ++i) { 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const media::cast::proto::AggregatedFrameEvent& event = 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *video_frame_events[i]; 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++total_video_frames; 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (event.has_encoded_frame_size()) { 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++encoded_video_frames; 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoded_size += event.encoded_frame_size(); 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_bitrate += event.target_bitrate(); 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++dropped_video_frames; 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (event.has_delay_millis() && event.delay_millis() < 0) { 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++late_video_frames; 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci total_delay_of_late_frames_ms += -event.delay_millis(); 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) double avg_encoded_bitrate = 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !encoded_video_frames ? 0 : 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8.0 * encoded_size * video_sender_config.max_frame_rate / 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoded_video_frames / 1000; 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) double avg_target_bitrate = 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !encoded_video_frames ? 0 : target_bitrate / encoded_video_frames / 1000; 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOG(INFO) << "Configured target playout delay (ms): " 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << video_receiver_config.rtp_max_delay_ms; 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Audio frame count: " << audio_frame_count; 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(INFO) << "Total video frames: " << total_video_frames; 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(INFO) << "Dropped video frames " << dropped_video_frames; 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOG(INFO) << "Late video frames: " << late_video_frames 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " (average lateness: " 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << (late_video_frames > 0 ? 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<double>(total_delay_of_late_frames_ms) / 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci late_video_frames : 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0) 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " ms)"; 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(INFO) << "Average encoded bitrate (kbps): " << avg_encoded_bitrate; 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(INFO) << "Average target bitrate (kbps): " << avg_target_bitrate; 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Writing log: " << output_path.value(); 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Truncate file and then write serialized log. 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch { 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::ScopedFILE file(base::OpenFile(output_path, "wb")); 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!file.get()) { 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(INFO) << "Cannot write to log."; 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AppendLogToFile(&video_metadata, video_frame_events, video_packet_events, 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) output_path); 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AppendLogToFile(&audio_metadata, audio_frame_events, audio_packet_events, 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) output_path); 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 428116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkSimulationModel DefaultModel() { 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NetworkSimulationModel model; 430116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch model.set_type(cast::proto::INTERRUPTED_POISSON_PROCESS); 431116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IPPModel* ipp = model.mutable_ipp(); 432116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->set_coef_burstiness(0.609); 433116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->set_coef_variance(4.1); 434116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.609); 436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.495); 437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.561); 438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.458); 439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.538); 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.513); 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.585); 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.592); 443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.658); 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.556); 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.371); 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.595); 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.490); 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.980); 449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.781); 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ipp->add_average_rate(0.463); 451116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 452116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return model; 453116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 454116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 455116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool IsModelValid(const NetworkSimulationModel& model) { 456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!model.has_type()) 457116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 458116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NetworkSimulationModelType type = model.type(); 459116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (type == media::cast::proto::INTERRUPTED_POISSON_PROCESS) { 460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!model.has_ipp()) 461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const IPPModel& ipp = model.ipp(); 463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ipp.coef_burstiness() <= 0.0 || ipp.coef_variance() <= 0.0) 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ipp.average_rate_size() == 0) 466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (int i = 0; i < ipp.average_rate_size(); i++) { 468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (ipp.average_rate(i) <= 0.0) 469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 476116680a4aac90f2aa7413d9095a592090648e557Ben MurdochNetworkSimulationModel LoadModel(const base::FilePath& model_path) { 477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (model_path.empty()) { 478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Model path not set."; 479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DefaultModel(); 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string model_str; 482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!base::ReadFileToString(model_path, &model_str)) { 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to read model file."; 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DefaultModel(); 485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NetworkSimulationModel model; 488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!model.ParseFromString(model_str)) { 489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to parse model."; 490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DefaultModel(); 491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!IsModelValid(model)) { 493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Invalid model."; 494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DefaultModel(); 495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return model; 498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace cast 502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace media 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 504116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint main(int argc, char** argv) { 505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::AtExitManager at_exit; 506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CommandLine::Init(argc, argv); 507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch InitLogging(logging::LoggingSettings()); 508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const CommandLine* cmd = CommandLine::ForCurrentProcess(); 510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FilePath media_path = cmd->GetSwitchValuePath(media::cast::kLibDir); 511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (media_path.empty()) { 512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!PathService::Get(base::DIR_MODULE, &media_path)) { 513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to load FFmpeg."; 514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 1; 515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!media::InitializeMediaLibrary(media_path)) { 519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG(ERROR) << "Failed to initialize FFmpeg."; 520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 1; 521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FilePath source_path = cmd->GetSwitchValuePath( 524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::cast::kSourcePath); 525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FilePath output_path = cmd->GetSwitchValuePath( 526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::cast::kOutputPath); 527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (output_path.empty()) { 528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::GetTempDir(&output_path); 529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch output_path = output_path.AppendASCII("sim-events.gz"); 530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string sim_id = cmd->GetSwitchValueASCII(media::cast::kSimulationId); 532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NetworkSimulationModel model = media::cast::LoadModel( 534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch cmd->GetSwitchValuePath(media::cast::kModelPath)); 535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::DictionaryValue values; 537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch values.SetBoolean("sim", true); 538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch values.SetString("sim-id", sim_id); 539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 540116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::string extra_data; 541116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::JSONWriter::Write(&values, &extra_data); 542116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Run. 544116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::cast::RunSimulation(source_path, output_path, extra_data, model); 545116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 0; 546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 547