• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/logging.h"
6 #include "media/cast/audio_receiver/audio_decoder.h"
7 
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"
10 
11 namespace media {
12 namespace cast {
13 
AudioDecoder(scoped_refptr<CastEnvironment> cast_environment,const AudioReceiverConfig & audio_config,RtpPayloadFeedback * incoming_payload_feedback)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, &frame_id_map_, audio_config.incoming_ssrc,
21           true, 0),
22       have_received_packets_(false),
23       last_played_out_timestamp_(0) {
24   audio_decoder_->InitializeReceiver();
25 
26   webrtc::CodecInst receive_codec;
27   switch (audio_config.codec) {
28     case kPcm16:
29       receive_codec.pltype = audio_config.rtp_payload_type;
30       strncpy(receive_codec.plname, "L16", 4);
31       receive_codec.plfreq = audio_config.frequency;
32       receive_codec.pacsize = -1;
33       receive_codec.channels = audio_config.channels;
34       receive_codec.rate = -1;
35       break;
36     case kOpus:
37       receive_codec.pltype = audio_config.rtp_payload_type;
38       strncpy(receive_codec.plname, "opus", 5);
39       receive_codec.plfreq = audio_config.frequency;
40       receive_codec.pacsize = -1;
41       receive_codec.channels = audio_config.channels;
42       receive_codec.rate = -1;
43       break;
44     case kExternalAudio:
45       NOTREACHED() << "Codec must be specified for audio decoder";
46       break;
47   }
48   if (audio_decoder_->RegisterReceiveCodec(receive_codec) != 0) {
49     NOTREACHED() << "Failed to register receive codec";
50   }
51 
52   audio_decoder_->SetMaximumPlayoutDelay(audio_config.rtp_max_delay_ms);
53   audio_decoder_->SetPlayoutMode(webrtc::streaming);
54 }
55 
~AudioDecoder()56 AudioDecoder::~AudioDecoder() {}
57 
GetRawAudioFrame(int number_of_10ms_blocks,int desired_frequency,PcmAudioFrame * audio_frame,uint32 * rtp_timestamp)58 bool AudioDecoder::GetRawAudioFrame(int number_of_10ms_blocks,
59                                     int desired_frequency,
60                                     PcmAudioFrame* audio_frame,
61                                     uint32* rtp_timestamp) {
62   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_DECODER));
63   // We don't care about the race case where a packet arrives at the same time
64   // as this function in called. The data will be there the next time this
65   // function is called.
66   lock_.Acquire();
67   // Get a local copy under lock.
68   bool have_received_packets = have_received_packets_;
69   lock_.Release();
70 
71   if (!have_received_packets) return false;
72 
73   audio_frame->samples.clear();
74 
75   for (int i = 0; i < number_of_10ms_blocks; ++i) {
76     webrtc::AudioFrame webrtc_audio_frame;
77     if (0 != audio_decoder_->PlayoutData10Ms(desired_frequency,
78                                              &webrtc_audio_frame)) {
79       return false;
80     }
81     if (webrtc_audio_frame.speech_type_ == webrtc::AudioFrame::kPLCCNG ||
82         webrtc_audio_frame.speech_type_ == webrtc::AudioFrame::kUndefined) {
83       // We are only interested in real decoded audio.
84       return false;
85     }
86     audio_frame->frequency = webrtc_audio_frame.sample_rate_hz_;
87     audio_frame->channels = webrtc_audio_frame.num_channels_;
88 
89     if (i == 0) {
90       // Use the timestamp from the first 10ms block.
91       if (0 != audio_decoder_->PlayoutTimestamp(rtp_timestamp)) {
92         return false;
93       }
94       lock_.Acquire();
95       last_played_out_timestamp_ = *rtp_timestamp;
96       lock_.Release();
97     }
98     int samples_per_10ms = webrtc_audio_frame.samples_per_channel_;
99 
100     audio_frame->samples.insert(
101         audio_frame->samples.end(),
102         &webrtc_audio_frame.data_[0],
103         &webrtc_audio_frame.data_[samples_per_10ms * audio_frame->channels]);
104   }
105   return true;
106 }
107 
IncomingParsedRtpPacket(const uint8 * payload_data,size_t payload_size,const RtpCastHeader & rtp_header)108 void AudioDecoder::IncomingParsedRtpPacket(const uint8* payload_data,
109                                            size_t payload_size,
110                                            const RtpCastHeader& rtp_header) {
111   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
112   DCHECK_LE(payload_size, kIpPacketSize);
113   audio_decoder_->IncomingPacket(payload_data, static_cast<int32>(payload_size),
114                                  rtp_header.webrtc);
115   lock_.Acquire();
116   have_received_packets_ = true;
117   uint32 last_played_out_timestamp = last_played_out_timestamp_;
118   lock_.Release();
119 
120   bool complete = false;
121   if (!frame_id_map_.InsertPacket(rtp_header, &complete)) return;
122   if (!complete) return;
123 
124   cast_message_builder_.CompleteFrameReceived(rtp_header.frame_id,
125                                               rtp_header.is_key_frame);
126 
127   frame_id_rtp_timestamp_map_[rtp_header.frame_id] =
128       rtp_header.webrtc.header.timestamp;
129 
130   if (last_played_out_timestamp == 0) return;  // Nothing is played out yet.
131 
132   uint32 latest_frame_id_to_remove = 0;
133   bool frame_to_remove = false;
134 
135   FrameIdRtpTimestampMap::iterator it = frame_id_rtp_timestamp_map_.begin();
136   while (it != frame_id_rtp_timestamp_map_.end()) {
137     if (IsNewerRtpTimestamp(it->second, last_played_out_timestamp)) {
138       break;
139     }
140     frame_to_remove = true;
141     latest_frame_id_to_remove = it->first;
142     frame_id_rtp_timestamp_map_.erase(it);
143     it = frame_id_rtp_timestamp_map_.begin();
144   }
145   if (!frame_to_remove) return;
146 
147   frame_id_map_.RemoveOldFrames(latest_frame_id_to_remove);
148 }
149 
TimeToSendNextCastMessage(base::TimeTicks * time_to_send)150 bool AudioDecoder::TimeToSendNextCastMessage(base::TimeTicks* time_to_send) {
151   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
152   return cast_message_builder_.TimeToSendNextCastMessage(time_to_send);
153 }
154 
SendCastMessage()155 void AudioDecoder::SendCastMessage() {
156   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
157   cast_message_builder_.UpdateCastMessage();
158 }
159 
160 }  // namespace cast
161 }  // namespace media
162