Home | History | Annotate | Download | only in audio_receiver
      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 
     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 
     56 AudioDecoder::~AudioDecoder() {}
     57 
     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 
    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 
    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 
    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