Ignore title parameter for navigator.registerProtocolHandler
[chromium-blink-merge.git] / media / cast / audio_sender / audio_sender.cc
blob0e266c7b764056fff741dbeae9d15700e3c89923
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/cast/audio_sender/audio_sender.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/cast/audio_sender/audio_encoder.h"
11 #include "media/cast/transport/cast_transport_defines.h"
13 namespace media {
14 namespace cast {
16 const int64 kMinSchedulingDelayMs = 1;
18 class LocalRtcpAudioSenderFeedback : public RtcpSenderFeedback {
19 public:
20 explicit LocalRtcpAudioSenderFeedback(AudioSender* audio_sender)
21 : audio_sender_(audio_sender) {}
23 virtual void OnReceivedCastFeedback(const RtcpCastMessage& cast_feedback)
24 OVERRIDE {
25 if (!cast_feedback.missing_frames_and_packets_.empty()) {
26 audio_sender_->ResendPackets(cast_feedback.missing_frames_and_packets_);
28 VLOG(2) << "Received audio ACK "
29 << static_cast<int>(cast_feedback.ack_frame_id_);
32 private:
33 AudioSender* audio_sender_;
35 DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtcpAudioSenderFeedback);
38 // TODO(mikhal): Reduce heap allocation when not needed.
39 AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment,
40 const AudioSenderConfig& audio_config,
41 transport::CastTransportSender* const transport_sender)
42 : cast_environment_(cast_environment),
43 transport_sender_(transport_sender),
44 rtp_stats_(audio_config.frequency),
45 rtcp_feedback_(new LocalRtcpAudioSenderFeedback(this)),
46 rtcp_(cast_environment,
47 rtcp_feedback_.get(),
48 transport_sender_,
49 NULL, // paced sender.
50 NULL,
51 audio_config.rtcp_mode,
52 base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval),
53 audio_config.rtp_config.ssrc,
54 audio_config.incoming_feedback_ssrc,
55 audio_config.rtcp_c_name,
56 true),
57 timers_initialized_(false),
58 cast_initialization_cb_(STATUS_AUDIO_UNINITIALIZED),
59 weak_factory_(this) {
60 rtcp_.SetCastReceiverEventHistorySize(kReceiverRtcpEventHistorySize);
61 if (!audio_config.use_external_encoder) {
62 audio_encoder_.reset(
63 new AudioEncoder(cast_environment,
64 audio_config,
65 base::Bind(&AudioSender::SendEncodedAudioFrame,
66 weak_factory_.GetWeakPtr())));
67 cast_initialization_cb_ = audio_encoder_->InitializationResult();
70 media::cast::transport::CastTransportAudioConfig transport_config;
71 transport_config.codec = audio_config.codec;
72 transport_config.rtp.config = audio_config.rtp_config;
73 transport_config.frequency = audio_config.frequency;
74 transport_config.channels = audio_config.channels;
75 transport_config.rtp.max_outstanding_frames =
76 audio_config.rtp_config.max_delay_ms / 100 + 1;
77 transport_sender_->InitializeAudio(transport_config);
79 transport_sender_->SubscribeAudioRtpStatsCallback(
80 base::Bind(&AudioSender::StoreStatistics, weak_factory_.GetWeakPtr()));
83 AudioSender::~AudioSender() {}
85 void AudioSender::InitializeTimers() {
86 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
87 if (!timers_initialized_) {
88 timers_initialized_ = true;
89 ScheduleNextRtcpReport();
93 void AudioSender::InsertAudio(scoped_ptr<AudioBus> audio_bus,
94 const base::TimeTicks& recorded_time) {
95 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
96 DCHECK(audio_encoder_.get()) << "Invalid internal state";
97 audio_encoder_->InsertAudio(audio_bus.Pass(), recorded_time);
100 void AudioSender::SendEncodedAudioFrame(
101 scoped_ptr<transport::EncodedAudioFrame> audio_frame,
102 const base::TimeTicks& recorded_time) {
103 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
104 InitializeTimers();
105 transport_sender_->InsertCodedAudioFrame(audio_frame.get(), recorded_time);
108 void AudioSender::ResendPackets(
109 const MissingFramesAndPacketsMap& missing_frames_and_packets) {
110 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
111 transport_sender_->ResendPackets(true, missing_frames_and_packets);
114 void AudioSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
115 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
116 rtcp_.IncomingRtcpPacket(&packet->front(), packet->size());
119 void AudioSender::ScheduleNextRtcpReport() {
120 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
121 base::TimeDelta time_to_next =
122 rtcp_.TimeToSendNextRtcpReport() - cast_environment_->Clock()->NowTicks();
124 time_to_next = std::max(
125 time_to_next, base::TimeDelta::FromMilliseconds(kMinSchedulingDelayMs));
127 cast_environment_->PostDelayedTask(
128 CastEnvironment::MAIN,
129 FROM_HERE,
130 base::Bind(&AudioSender::SendRtcpReport, weak_factory_.GetWeakPtr()),
131 time_to_next);
134 void AudioSender::StoreStatistics(
135 const transport::RtcpSenderInfo& sender_info,
136 base::TimeTicks time_sent,
137 uint32 rtp_timestamp) {
138 rtp_stats_.Store(sender_info, time_sent, rtp_timestamp);
141 void AudioSender::SendRtcpReport() {
142 DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
143 // We don't send audio logging messages since all captured audio frames will
144 // be sent.
145 transport::RtcpSenderLogMessage empty_msg;
146 rtp_stats_.UpdateInfo(cast_environment_->Clock()->NowTicks());
147 rtcp_.SendRtcpFromRtpSender(empty_msg, rtp_stats_.sender_info());
148 ScheduleNextRtcpReport();
151 } // namespace cast
152 } // namespace media