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 "base/logging.h"
6 #include "media/cast/audio_receiver/audio_decoder.h"
8 #include "third_party/webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
9 #include "third_party/webrtc/modules/interface/module_common_types.h"
14 AudioDecoder::AudioDecoder(scoped_refptr
<CastEnvironment
> cast_environment
,
15 const AudioReceiverConfig
& audio_config
,
16 RtpPayloadFeedback
* incoming_payload_feedback
)
17 : cast_environment_(cast_environment
),
18 audio_decoder_(webrtc::AudioCodingModule::Create(0)),
19 cast_message_builder_(cast_environment
->Clock(),
20 incoming_payload_feedback
,
22 audio_config
.incoming_ssrc
,
25 have_received_packets_(false),
26 last_played_out_timestamp_(0) {
27 audio_decoder_
->InitializeReceiver();
29 webrtc::CodecInst receive_codec
;
30 switch (audio_config
.codec
) {
31 case transport::kPcm16
:
32 receive_codec
.pltype
= audio_config
.rtp_payload_type
;
33 strncpy(receive_codec
.plname
, "L16", 4);
34 receive_codec
.plfreq
= audio_config
.frequency
;
35 receive_codec
.pacsize
= -1;
36 receive_codec
.channels
= audio_config
.channels
;
37 receive_codec
.rate
= -1;
39 case transport::kOpus
:
40 receive_codec
.pltype
= audio_config
.rtp_payload_type
;
41 strncpy(receive_codec
.plname
, "opus", 5);
42 receive_codec
.plfreq
= audio_config
.frequency
;
43 receive_codec
.pacsize
= -1;
44 receive_codec
.channels
= audio_config
.channels
;
45 receive_codec
.rate
= -1;
47 case transport::kExternalAudio
:
48 NOTREACHED() << "Codec must be specified for audio decoder";
51 if (audio_decoder_
->RegisterReceiveCodec(receive_codec
) != 0) {
52 NOTREACHED() << "Failed to register receive codec";
55 audio_decoder_
->SetMaximumPlayoutDelay(audio_config
.rtp_max_delay_ms
);
56 audio_decoder_
->SetPlayoutMode(webrtc::streaming
);
59 AudioDecoder::~AudioDecoder() {}
61 bool AudioDecoder::GetRawAudioFrame(int number_of_10ms_blocks
,
62 int desired_frequency
,
63 PcmAudioFrame
* audio_frame
,
64 uint32
* rtp_timestamp
) {
65 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::AUDIO_DECODER
));
66 // We don't care about the race case where a packet arrives at the same time
67 // as this function in called. The data will be there the next time this
68 // function is called.
70 // Get a local copy under lock.
71 bool have_received_packets
= have_received_packets_
;
74 if (!have_received_packets
)
77 audio_frame
->samples
.clear();
79 for (int i
= 0; i
< number_of_10ms_blocks
; ++i
) {
80 webrtc::AudioFrame webrtc_audio_frame
;
81 if (0 != audio_decoder_
->PlayoutData10Ms(desired_frequency
,
82 &webrtc_audio_frame
)) {
85 if (webrtc_audio_frame
.speech_type_
== webrtc::AudioFrame::kPLCCNG
||
86 webrtc_audio_frame
.speech_type_
== webrtc::AudioFrame::kUndefined
) {
87 // We are only interested in real decoded audio.
90 audio_frame
->frequency
= webrtc_audio_frame
.sample_rate_hz_
;
91 audio_frame
->channels
= webrtc_audio_frame
.num_channels_
;
94 // Use the timestamp from the first 10ms block.
95 if (0 != audio_decoder_
->PlayoutTimestamp(rtp_timestamp
)) {
99 last_played_out_timestamp_
= *rtp_timestamp
;
102 int samples_per_10ms
= webrtc_audio_frame
.samples_per_channel_
;
104 audio_frame
->samples
.insert(
105 audio_frame
->samples
.end(),
106 &webrtc_audio_frame
.data_
[0],
107 &webrtc_audio_frame
.data_
[samples_per_10ms
* audio_frame
->channels
]);
112 void AudioDecoder::IncomingParsedRtpPacket(const uint8
* payload_data
,
114 const RtpCastHeader
& rtp_header
) {
115 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
116 DCHECK_LE(payload_size
, kMaxIpPacketSize
);
117 audio_decoder_
->IncomingPacket(
118 payload_data
, static_cast<int32
>(payload_size
), rtp_header
.webrtc
);
120 have_received_packets_
= true;
121 uint32 last_played_out_timestamp
= last_played_out_timestamp_
;
124 PacketType packet_type
= frame_id_map_
.InsertPacket(rtp_header
);
125 if (packet_type
!= kNewPacketCompletingFrame
)
128 cast_message_builder_
.CompleteFrameReceived(rtp_header
.frame_id
,
129 rtp_header
.is_key_frame
);
131 frame_id_rtp_timestamp_map_
[rtp_header
.frame_id
] =
132 rtp_header
.webrtc
.header
.timestamp
;
134 if (last_played_out_timestamp
== 0)
135 return; // Nothing is played out yet.
137 uint32 latest_frame_id_to_remove
= 0;
138 bool frame_to_remove
= false;
140 FrameIdRtpTimestampMap::iterator it
= frame_id_rtp_timestamp_map_
.begin();
141 while (it
!= frame_id_rtp_timestamp_map_
.end()) {
142 if (IsNewerRtpTimestamp(it
->second
, last_played_out_timestamp
)) {
145 frame_to_remove
= true;
146 latest_frame_id_to_remove
= it
->first
;
147 frame_id_rtp_timestamp_map_
.erase(it
);
148 it
= frame_id_rtp_timestamp_map_
.begin();
150 if (!frame_to_remove
)
153 frame_id_map_
.RemoveOldFrames(latest_frame_id_to_remove
);
156 bool AudioDecoder::TimeToSendNextCastMessage(base::TimeTicks
* time_to_send
) {
157 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
158 return cast_message_builder_
.TimeToSendNextCastMessage(time_to_send
);
161 void AudioDecoder::SendCastMessage() {
162 DCHECK(cast_environment_
->CurrentlyOn(CastEnvironment::MAIN
));
163 cast_message_builder_
.UpdateCastMessage();