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
3 // found in the LICENSE file.
5 #include "media/cast/sender/audio_sender.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "media/cast/cast_defines.h"
11 #include "media/cast/net/cast_transport_config.h"
12 #include "media/cast/sender/audio_encoder.h"
17 AudioSender::AudioSender(scoped_refptr
<CastEnvironment
> cast_environment
,
18 const AudioSenderConfig
& audio_config
,
19 const StatusChangeCallback
& status_change_cb
,
20 CastTransportSender
* const transport_sender
)
21 : FrameSender(cast_environment
,
24 audio_config
.frequency
,
26 0, // |max_frame_rate_| is set after encoder initialization.
27 audio_config
.min_playout_delay
,
28 audio_config
.max_playout_delay
,
29 NewFixedCongestionControl(audio_config
.bitrate
)),
30 samples_in_encoder_(0),
32 if (!audio_config
.use_external_encoder
) {
34 new AudioEncoder(cast_environment
,
35 audio_config
.channels
,
36 audio_config
.frequency
,
39 base::Bind(&AudioSender::OnEncodedAudioFrame
,
40 weak_factory_
.GetWeakPtr(),
41 audio_config
.bitrate
)));
44 // AudioEncoder provides no operational status changes during normal use.
45 // Post a task now with its initialization result status to allow the client
46 // to start sending frames.
47 cast_environment_
->PostTask(
48 CastEnvironment::MAIN
,
50 base::Bind(status_change_cb
,
51 audio_encoder_
? audio_encoder_
->InitializationResult() :
52 STATUS_INVALID_CONFIGURATION
));
54 // The number of samples per encoded audio frame depends on the codec and its
55 // initialization parameters. Now that we have an encoder, we can calculate
56 // the maximum frame rate.
58 audio_config
.frequency
/ audio_encoder_
->GetSamplesPerFrame();
60 media::cast::CastTransportRtpConfig transport_config
;
61 transport_config
.ssrc
= audio_config
.ssrc
;
62 transport_config
.feedback_ssrc
= audio_config
.receiver_ssrc
;
63 transport_config
.rtp_payload_type
= audio_config
.rtp_payload_type
;
64 transport_config
.aes_key
= audio_config
.aes_key
;
65 transport_config
.aes_iv_mask
= audio_config
.aes_iv_mask
;
67 transport_sender
->InitializeAudio(
69 base::Bind(&AudioSender::OnReceivedCastFeedback
,
70 weak_factory_
.GetWeakPtr()),
71 base::Bind(&AudioSender::OnMeasuredRoundTripTime
,
72 weak_factory_
.GetWeakPtr()));
75 AudioSender::~AudioSender() {}
77 void AudioSender::InsertAudio(scoped_ptr
<AudioBus
> audio_bus
,
78 const base::TimeTicks
& recorded_time
) {
79 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
81 if (!audio_encoder_
) {
86 const base::TimeDelta next_frame_duration
=
87 RtpDeltaToTimeDelta(audio_bus
->frames(), rtp_timebase());
88 if (ShouldDropNextFrame(next_frame_duration
))
91 samples_in_encoder_
+= audio_bus
->frames();
93 audio_encoder_
->InsertAudio(audio_bus
.Pass(), recorded_time
);
96 int AudioSender::GetNumberOfFramesInEncoder() const {
97 // Note: It's possible for a partial frame to be in the encoder, but returning
98 // the floor() is good enough for the "design limit" check in FrameSender.
99 return samples_in_encoder_
/ audio_encoder_
->GetSamplesPerFrame();
102 base::TimeDelta
AudioSender::GetInFlightMediaDuration() const {
103 const int samples_in_flight
= samples_in_encoder_
+
104 GetUnacknowledgedFrameCount() * audio_encoder_
->GetSamplesPerFrame();
105 return RtpDeltaToTimeDelta(samples_in_flight
, rtp_timebase());
108 void AudioSender::OnAck(uint32 frame_id
) {
111 void AudioSender::OnEncodedAudioFrame(
113 scoped_ptr
<SenderEncodedFrame
> encoded_frame
,
114 int samples_skipped
) {
115 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
117 samples_in_encoder_
-= audio_encoder_
->GetSamplesPerFrame() + samples_skipped
;
118 DCHECK_GE(samples_in_encoder_
, 0);
120 SendEncodedFrame(encoder_bitrate
, encoded_frame
.Pass());