OLD | NEW |
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 18 matching lines...) Expand all Loading... |
29 // File path to write YUV decoded frames in YUV4MPEG2 format. | 29 // File path to write YUV decoded frames in YUV4MPEG2 format. |
30 // --no-simulation | 30 // --no-simulation |
31 // Do not run network simulation. | 31 // Do not run network simulation. |
32 // | 32 // |
33 // Output: | 33 // Output: |
34 // - Raw event log of the simulation session tagged with the unique test ID, | 34 // - Raw event log of the simulation session tagged with the unique test ID, |
35 // written out to the specified file path. | 35 // written out to the specified file path. |
36 | 36 |
37 #include <stddef.h> | 37 #include <stddef.h> |
38 #include <stdint.h> | 38 #include <stdint.h> |
| 39 |
39 #include <utility> | 40 #include <utility> |
40 | 41 |
41 #include "base/at_exit.h" | 42 #include "base/at_exit.h" |
42 #include "base/base_paths.h" | 43 #include "base/base_paths.h" |
43 #include "base/command_line.h" | 44 #include "base/command_line.h" |
44 #include "base/files/file_path.h" | 45 #include "base/files/file_path.h" |
45 #include "base/files/file_util.h" | 46 #include "base/files/file_util.h" |
46 #include "base/files/memory_mapped_file.h" | 47 #include "base/files/memory_mapped_file.h" |
47 #include "base/files/scoped_file.h" | 48 #include "base/files/scoped_file.h" |
48 #include "base/json/json_writer.h" | 49 #include "base/json/json_writer.h" |
49 #include "base/logging.h" | 50 #include "base/logging.h" |
50 #include "base/macros.h" | 51 #include "base/macros.h" |
| 52 #include "base/memory/ptr_util.h" |
51 #include "base/path_service.h" | 53 #include "base/path_service.h" |
52 #include "base/strings/string_number_conversions.h" | 54 #include "base/strings/string_number_conversions.h" |
53 #include "base/strings/stringprintf.h" | 55 #include "base/strings/stringprintf.h" |
54 #include "base/test/simple_test_tick_clock.h" | 56 #include "base/test/simple_test_tick_clock.h" |
55 #include "base/thread_task_runner_handle.h" | 57 #include "base/thread_task_runner_handle.h" |
56 #include "base/time/tick_clock.h" | 58 #include "base/time/tick_clock.h" |
57 #include "base/values.h" | 59 #include "base/values.h" |
58 #include "media/base/audio_bus.h" | 60 #include "media/base/audio_bus.h" |
59 #include "media/base/fake_single_thread_task_runner.h" | 61 #include "media/base/fake_single_thread_task_runner.h" |
60 #include "media/base/media.h" | 62 #include "media/base/media.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 void LogAudioOperationalStatus(OperationalStatus status) { | 119 void LogAudioOperationalStatus(OperationalStatus status) { |
118 LOG(INFO) << "Audio status: " << status; | 120 LOG(INFO) << "Audio status: " << status; |
119 } | 121 } |
120 | 122 |
121 void LogVideoOperationalStatus(OperationalStatus status) { | 123 void LogVideoOperationalStatus(OperationalStatus status) { |
122 LOG(INFO) << "Video status: " << status; | 124 LOG(INFO) << "Video status: " << status; |
123 } | 125 } |
124 | 126 |
125 struct PacketProxy { | 127 struct PacketProxy { |
126 PacketProxy() : receiver(NULL) {} | 128 PacketProxy() : receiver(NULL) {} |
127 void ReceivePacket(scoped_ptr<Packet> packet) { | 129 void ReceivePacket(std::unique_ptr<Packet> packet) { |
128 if (receiver) | 130 if (receiver) |
129 receiver->ReceivePacket(std::move(packet)); | 131 receiver->ReceivePacket(std::move(packet)); |
130 } | 132 } |
131 CastReceiver* receiver; | 133 CastReceiver* receiver; |
132 }; | 134 }; |
133 | 135 |
134 class TransportClient : public CastTransport::Client { | 136 class TransportClient : public CastTransport::Client { |
135 public: | 137 public: |
136 TransportClient(LogEventDispatcher* log_event_dispatcher, | 138 TransportClient(LogEventDispatcher* log_event_dispatcher, |
137 PacketProxy* packet_proxy) | 139 PacketProxy* packet_proxy) |
138 : log_event_dispatcher_(log_event_dispatcher), | 140 : log_event_dispatcher_(log_event_dispatcher), |
139 packet_proxy_(packet_proxy) {} | 141 packet_proxy_(packet_proxy) {} |
140 | 142 |
141 void OnStatusChanged(CastTransportStatus status) final { | 143 void OnStatusChanged(CastTransportStatus status) final { |
142 LOG(INFO) << "Cast transport status: " << status; | 144 LOG(INFO) << "Cast transport status: " << status; |
143 }; | 145 }; |
144 void OnLoggingEventsReceived( | 146 void OnLoggingEventsReceived( |
145 scoped_ptr<std::vector<FrameEvent>> frame_events, | 147 std::unique_ptr<std::vector<FrameEvent>> frame_events, |
146 scoped_ptr<std::vector<PacketEvent>> packet_events) final { | 148 std::unique_ptr<std::vector<PacketEvent>> packet_events) final { |
147 DCHECK(log_event_dispatcher_); | 149 DCHECK(log_event_dispatcher_); |
148 log_event_dispatcher_->DispatchBatchOfEvents(std::move(frame_events), | 150 log_event_dispatcher_->DispatchBatchOfEvents(std::move(frame_events), |
149 std::move(packet_events)); | 151 std::move(packet_events)); |
150 }; | 152 }; |
151 void ProcessRtpPacket(scoped_ptr<Packet> packet) final { | 153 void ProcessRtpPacket(std::unique_ptr<Packet> packet) final { |
152 if (packet_proxy_) | 154 if (packet_proxy_) |
153 packet_proxy_->ReceivePacket(std::move(packet)); | 155 packet_proxy_->ReceivePacket(std::move(packet)); |
154 }; | 156 }; |
155 | 157 |
156 private: | 158 private: |
157 LogEventDispatcher* const log_event_dispatcher_; // Not owned by this class. | 159 LogEventDispatcher* const log_event_dispatcher_; // Not owned by this class. |
158 PacketProxy* const packet_proxy_; // Not owned by this class. | 160 PacketProxy* const packet_proxy_; // Not owned by this class. |
159 | 161 |
160 DISALLOW_COPY_AND_ASSIGN(TransportClient); | 162 DISALLOW_COPY_AND_ASSIGN(TransportClient); |
161 }; | 163 }; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 video_frame_tracker->PopOldestEncodedFrame(); | 269 video_frame_tracker->PopOldestEncodedFrame(); |
268 metrics_output->psnr.push_back(I420PSNR(src_frame, video_frame)); | 270 metrics_output->psnr.push_back(I420PSNR(src_frame, video_frame)); |
269 metrics_output->ssim.push_back(I420SSIM(src_frame, video_frame)); | 271 metrics_output->ssim.push_back(I420SSIM(src_frame, video_frame)); |
270 } | 272 } |
271 | 273 |
272 if (!yuv_output.empty()) { | 274 if (!yuv_output.empty()) { |
273 AppendYuvToFile(yuv_output, video_frame); | 275 AppendYuvToFile(yuv_output, video_frame); |
274 } | 276 } |
275 } | 277 } |
276 | 278 |
277 void GotAudioFrame( | 279 void GotAudioFrame(int* counter, |
278 int* counter, | 280 CastReceiver* cast_receiver, |
279 CastReceiver* cast_receiver, | 281 std::unique_ptr<AudioBus> audio_bus, |
280 scoped_ptr<AudioBus> audio_bus, | 282 const base::TimeTicks& playout_time, |
281 const base::TimeTicks& playout_time, | 283 bool is_continuous) { |
282 bool is_continuous) { | |
283 ++*counter; | 284 ++*counter; |
284 cast_receiver->RequestDecodedAudioFrame( | 285 cast_receiver->RequestDecodedAudioFrame( |
285 base::Bind(&GotAudioFrame, counter, cast_receiver)); | 286 base::Bind(&GotAudioFrame, counter, cast_receiver)); |
286 } | 287 } |
287 | 288 |
288 // Serialize |frame_events| and |packet_events| and append to the file | 289 // Serialize |frame_events| and |packet_events| and append to the file |
289 // located at |output_path|. | 290 // located at |output_path|. |
290 void AppendLogToFile(media::cast::proto::LogMetadata* metadata, | 291 void AppendLogToFile(media::cast::proto::LogMetadata* metadata, |
291 const media::cast::FrameEventList& frame_events, | 292 const media::cast::FrameEventList& frame_events, |
292 const media::cast::PacketEventList& packet_events, | 293 const media::cast::PacketEventList& packet_events, |
293 const base::FilePath& output_path) { | 294 const base::FilePath& output_path) { |
294 media::cast::proto::GeneralDescription* gen_desc = | 295 media::cast::proto::GeneralDescription* gen_desc = |
295 metadata->mutable_general_description(); | 296 metadata->mutable_general_description(); |
296 gen_desc->set_product("Cast Simulator"); | 297 gen_desc->set_product("Cast Simulator"); |
297 gen_desc->set_product_version("0.1"); | 298 gen_desc->set_product_version("0.1"); |
298 | 299 |
299 scoped_ptr<char[]> serialized_log(new char[media::cast::kMaxSerializedBytes]); | 300 std::unique_ptr<char[]> serialized_log( |
| 301 new char[media::cast::kMaxSerializedBytes]); |
300 int output_bytes; | 302 int output_bytes; |
301 bool success = media::cast::SerializeEvents(*metadata, | 303 bool success = media::cast::SerializeEvents(*metadata, |
302 frame_events, | 304 frame_events, |
303 packet_events, | 305 packet_events, |
304 true, | 306 true, |
305 media::cast::kMaxSerializedBytes, | 307 media::cast::kMaxSerializedBytes, |
306 serialized_log.get(), | 308 serialized_log.get(), |
307 &output_bytes); | 309 &output_bytes); |
308 | 310 |
309 if (!success) { | 311 if (!success) { |
(...skipping 19 matching lines...) Expand all Loading... |
329 // Fake clock. Make sure start time is non zero. | 331 // Fake clock. Make sure start time is non zero. |
330 base::SimpleTestTickClock testing_clock; | 332 base::SimpleTestTickClock testing_clock; |
331 testing_clock.Advance(base::TimeDelta::FromSeconds(1)); | 333 testing_clock.Advance(base::TimeDelta::FromSeconds(1)); |
332 | 334 |
333 // Task runner. | 335 // Task runner. |
334 scoped_refptr<FakeSingleThreadTaskRunner> task_runner = | 336 scoped_refptr<FakeSingleThreadTaskRunner> task_runner = |
335 new FakeSingleThreadTaskRunner(&testing_clock); | 337 new FakeSingleThreadTaskRunner(&testing_clock); |
336 base::ThreadTaskRunnerHandle task_runner_handle(task_runner); | 338 base::ThreadTaskRunnerHandle task_runner_handle(task_runner); |
337 | 339 |
338 // CastEnvironments. | 340 // CastEnvironments. |
339 scoped_refptr<CastEnvironment> sender_env = new CastEnvironment( | 341 scoped_refptr<CastEnvironment> sender_env = |
340 scoped_ptr<base::TickClock>(new test::SkewedTickClock(&testing_clock)), | 342 new CastEnvironment(std::unique_ptr<base::TickClock>( |
341 task_runner, task_runner, task_runner); | 343 new test::SkewedTickClock(&testing_clock)), |
342 scoped_refptr<CastEnvironment> receiver_env = new CastEnvironment( | 344 task_runner, task_runner, task_runner); |
343 scoped_ptr<base::TickClock>(new test::SkewedTickClock(&testing_clock)), | 345 scoped_refptr<CastEnvironment> receiver_env = |
344 task_runner, task_runner, task_runner); | 346 new CastEnvironment(std::unique_ptr<base::TickClock>( |
| 347 new test::SkewedTickClock(&testing_clock)), |
| 348 task_runner, task_runner, task_runner); |
345 | 349 |
346 // Event subscriber. Store at most 1 hour of events. | 350 // Event subscriber. Store at most 1 hour of events. |
347 EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT, | 351 EncodingEventSubscriber audio_event_subscriber(AUDIO_EVENT, |
348 100 * 60 * 60); | 352 100 * 60 * 60); |
349 EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, | 353 EncodingEventSubscriber video_event_subscriber(VIDEO_EVENT, |
350 30 * 60 * 60); | 354 30 * 60 * 60); |
351 sender_env->logger()->Subscribe(&audio_event_subscriber); | 355 sender_env->logger()->Subscribe(&audio_event_subscriber); |
352 sender_env->logger()->Subscribe(&video_event_subscriber); | 356 sender_env->logger()->Subscribe(&video_event_subscriber); |
353 | 357 |
354 // Audio sender config. | 358 // Audio sender config. |
(...skipping 24 matching lines...) Expand all Loading... |
379 video_receiver_config.rtp_max_delay_ms = | 383 video_receiver_config.rtp_max_delay_ms = |
380 video_sender_config.max_playout_delay.InMilliseconds(); | 384 video_sender_config.max_playout_delay.InMilliseconds(); |
381 | 385 |
382 // Loopback transport. Owned by CastTransport. | 386 // Loopback transport. Owned by CastTransport. |
383 LoopBackTransport* receiver_to_sender = new LoopBackTransport(receiver_env); | 387 LoopBackTransport* receiver_to_sender = new LoopBackTransport(receiver_env); |
384 LoopBackTransport* sender_to_receiver = new LoopBackTransport(sender_env); | 388 LoopBackTransport* sender_to_receiver = new LoopBackTransport(sender_env); |
385 | 389 |
386 PacketProxy packet_proxy; | 390 PacketProxy packet_proxy; |
387 | 391 |
388 // Cast receiver. | 392 // Cast receiver. |
389 scoped_ptr<CastTransport> transport_receiver( | 393 std::unique_ptr<CastTransport> transport_receiver( |
390 new CastTransportImpl(&testing_clock, base::TimeDelta::FromSeconds(1), | 394 new CastTransportImpl(&testing_clock, base::TimeDelta::FromSeconds(1), |
391 make_scoped_ptr(new TransportClient( | 395 base::WrapUnique(new TransportClient( |
392 receiver_env->logger(), &packet_proxy)), | 396 receiver_env->logger(), &packet_proxy)), |
393 make_scoped_ptr(receiver_to_sender), task_runner)); | 397 base::WrapUnique(receiver_to_sender), task_runner)); |
394 scoped_ptr<CastReceiver> cast_receiver( | 398 std::unique_ptr<CastReceiver> cast_receiver( |
395 CastReceiver::Create(receiver_env, | 399 CastReceiver::Create(receiver_env, audio_receiver_config, |
396 audio_receiver_config, | 400 video_receiver_config, transport_receiver.get())); |
397 video_receiver_config, | |
398 transport_receiver.get())); | |
399 | 401 |
400 packet_proxy.receiver = cast_receiver.get(); | 402 packet_proxy.receiver = cast_receiver.get(); |
401 | 403 |
402 // Cast sender and transport sender. | 404 // Cast sender and transport sender. |
403 scoped_ptr<CastTransport> transport_sender(new CastTransportImpl( | 405 std::unique_ptr<CastTransport> transport_sender(new CastTransportImpl( |
404 &testing_clock, base::TimeDelta::FromSeconds(1), | 406 &testing_clock, base::TimeDelta::FromSeconds(1), |
405 make_scoped_ptr(new TransportClient(sender_env->logger(), nullptr)), | 407 base::WrapUnique(new TransportClient(sender_env->logger(), nullptr)), |
406 make_scoped_ptr(sender_to_receiver), task_runner)); | 408 base::WrapUnique(sender_to_receiver), task_runner)); |
407 scoped_ptr<CastSender> cast_sender( | 409 std::unique_ptr<CastSender> cast_sender( |
408 CastSender::Create(sender_env, transport_sender.get())); | 410 CastSender::Create(sender_env, transport_sender.get())); |
409 | 411 |
410 // Initialize network simulation model. | 412 // Initialize network simulation model. |
411 const bool use_network_simulation = | 413 const bool use_network_simulation = |
412 model.type() == media::cast::proto::INTERRUPTED_POISSON_PROCESS; | 414 model.type() == media::cast::proto::INTERRUPTED_POISSON_PROCESS; |
413 scoped_ptr<test::InterruptedPoissonProcess> ipp; | 415 std::unique_ptr<test::InterruptedPoissonProcess> ipp; |
414 if (use_network_simulation) { | 416 if (use_network_simulation) { |
415 LOG(INFO) << "Running Poisson based network simulation."; | 417 LOG(INFO) << "Running Poisson based network simulation."; |
416 const IPPModel& ipp_model = model.ipp(); | 418 const IPPModel& ipp_model = model.ipp(); |
417 std::vector<double> average_rates(ipp_model.average_rate_size()); | 419 std::vector<double> average_rates(ipp_model.average_rate_size()); |
418 std::copy(ipp_model.average_rate().begin(), | 420 std::copy(ipp_model.average_rate().begin(), |
419 ipp_model.average_rate().end(), | 421 ipp_model.average_rate().end(), |
420 average_rates.begin()); | 422 average_rates.begin()); |
421 ipp.reset(new test::InterruptedPoissonProcess( | 423 ipp.reset(new test::InterruptedPoissonProcess( |
422 average_rates, | 424 average_rates, |
423 ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0)); | 425 ipp_model.coef_burstiness(), ipp_model.coef_variance(), 0)); |
424 receiver_to_sender->Initialize(ipp->NewBuffer(128 * 1024), | 426 receiver_to_sender->Initialize(ipp->NewBuffer(128 * 1024), |
425 transport_sender->PacketReceiverForTesting(), | 427 transport_sender->PacketReceiverForTesting(), |
426 task_runner, &testing_clock); | 428 task_runner, &testing_clock); |
427 sender_to_receiver->Initialize( | 429 sender_to_receiver->Initialize( |
428 ipp->NewBuffer(128 * 1024), | 430 ipp->NewBuffer(128 * 1024), |
429 transport_receiver->PacketReceiverForTesting(), task_runner, | 431 transport_receiver->PacketReceiverForTesting(), task_runner, |
430 &testing_clock); | 432 &testing_clock); |
431 } else { | 433 } else { |
432 LOG(INFO) << "No network simulation."; | 434 LOG(INFO) << "No network simulation."; |
433 receiver_to_sender->Initialize(scoped_ptr<test::PacketPipe>(), | 435 receiver_to_sender->Initialize(std::unique_ptr<test::PacketPipe>(), |
434 transport_sender->PacketReceiverForTesting(), | 436 transport_sender->PacketReceiverForTesting(), |
435 task_runner, &testing_clock); | 437 task_runner, &testing_clock); |
436 sender_to_receiver->Initialize( | 438 sender_to_receiver->Initialize( |
437 scoped_ptr<test::PacketPipe>(), | 439 std::unique_ptr<test::PacketPipe>(), |
438 transport_receiver->PacketReceiverForTesting(), task_runner, | 440 transport_receiver->PacketReceiverForTesting(), task_runner, |
439 &testing_clock); | 441 &testing_clock); |
440 } | 442 } |
441 | 443 |
442 // Initialize a fake media source and a tracker to encoded video frames. | 444 // Initialize a fake media source and a tracker to encoded video frames. |
443 const bool quality_test = !metrics_output_path.empty(); | 445 const bool quality_test = !metrics_output_path.empty(); |
444 FakeMediaSource media_source(task_runner, | 446 FakeMediaSource media_source(task_runner, |
445 &testing_clock, | 447 &testing_clock, |
446 audio_sender_config, | 448 audio_sender_config, |
447 video_sender_config, | 449 video_sender_config, |
448 quality_test); | 450 quality_test); |
449 scoped_ptr<EncodedVideoFrameTracker> video_frame_tracker; | 451 std::unique_ptr<EncodedVideoFrameTracker> video_frame_tracker; |
450 if (quality_test) { | 452 if (quality_test) { |
451 video_frame_tracker.reset(new EncodedVideoFrameTracker(&media_source)); | 453 video_frame_tracker.reset(new EncodedVideoFrameTracker(&media_source)); |
452 sender_env->logger()->Subscribe(video_frame_tracker.get()); | 454 sender_env->logger()->Subscribe(video_frame_tracker.get()); |
453 } | 455 } |
454 | 456 |
455 // Quality metrics computed for each frame decoded. | 457 // Quality metrics computed for each frame decoded. |
456 GotVideoFrameOutput metrics_output; | 458 GotVideoFrameOutput metrics_output; |
457 | 459 |
458 // Start receiver. | 460 // Start receiver. |
459 int audio_frame_count = 0; | 461 int audio_frame_count = 0; |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 values.SetString("sim-id", sim_id); | 734 values.SetString("sim-id", sim_id); |
733 | 735 |
734 std::string extra_data; | 736 std::string extra_data; |
735 base::JSONWriter::Write(values, &extra_data); | 737 base::JSONWriter::Write(values, &extra_data); |
736 | 738 |
737 // Run. | 739 // Run. |
738 media::cast::RunSimulation(source_path, log_output_path, metrics_output_path, | 740 media::cast::RunSimulation(source_path, log_output_path, metrics_output_path, |
739 yuv_output_path, extra_data, model); | 741 yuv_output_path, extra_data, model); |
740 return 0; | 742 return 0; |
741 } | 743 } |
OLD | NEW |