15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/client/audio_player.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of channels in the audio stream (only supporting stereo audio
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for now).
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kChannels = 2;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSampleSizeBytes = 2;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If queue grows bigger than 150ms we start dropping packets.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxQueueLatencyMs = 150;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioPlayer::AudioPlayer()
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_failed_(false),
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      queued_bytes_(0),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_consumed_(0) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioPlayer::~AudioPlayer() {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetQueue();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPlayer::ProcessAudioPacket(scoped_ptr<AudioPacket> packet) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(1, packet->data_size());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(AudioPacket::ENCODING_RAW, packet->encoding());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(AudioPacket::SAMPLING_RATE_INVALID, packet->sampling_rate());
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(kSampleSizeBytes, packet->bytes_per_sample());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(static_cast<int>(kChannels), packet->channels());
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(packet->data(0).size() % (kChannels * kSampleSizeBytes), 0u);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No-op if the Pepper player won't start.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (start_failed_) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the Pepper audio player if this is the first packet.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sampling_rate_ != packet->sampling_rate()) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Drop all packets currently in the queue, since they are sampled at the
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // wrong rate.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AutoLock auto_lock(lock_);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResetQueue();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sampling_rate_ = packet->sampling_rate();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = ResetAudioPlayer(sampling_rate_);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!success) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_failed_ = true;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  queued_bytes_ += packet->data(0).size();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queued_packets_.push_back(packet.release());
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int max_buffer_size_ =
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kMaxQueueLatencyMs * sampling_rate_ * kSampleSizeBytes * kChannels /
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMillisecondsPerSecond;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (queued_bytes_ > max_buffer_size_) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_bytes_ -= queued_packets_.front()->data(0).size() - bytes_consumed_;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_GE(queued_bytes_, 0);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete queued_packets_.front();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_packets_.pop_front();
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bytes_consumed_ = 0;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPlayer::AudioPlayerCallback(void* samples,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint32 buffer_size,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      void* data) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioPlayer* audio_player = static_cast<AudioPlayer*>(data);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_player->FillWithSamples(samples, buffer_size);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPlayer::ResetQueue() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock_.AssertAcquired();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&queued_packets_);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  queued_bytes_ = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bytes_consumed_ = 0;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AudioPlayer::FillWithSamples(void* samples, uint32 buffer_size) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AutoLock auto_lock(lock_);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t bytes_needed = kChannels * kSampleSizeBytes *
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetSamplesPerFrame();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure we don't overrun the buffer.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(buffer_size, bytes_needed);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* next_sample = static_cast<char*>(samples);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_extracted = 0;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (bytes_extracted < bytes_needed) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if we've run out of samples for this packet.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (queued_packets_.empty()) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memset(next_sample, 0, bytes_needed - bytes_extracted);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Pop off the packet if we've already consumed all its bytes.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (queued_packets_.front()->data(0).size() == bytes_consumed_) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete queued_packets_.front();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      queued_packets_.pop_front();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_consumed_ = 0;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& packet_data = queued_packets_.front()->data(0);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_to_copy = std::min(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        packet_data.size() - bytes_consumed_,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_needed - bytes_extracted);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(next_sample, packet_data.data() + bytes_consumed_, bytes_to_copy);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_sample += bytes_to_copy;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_consumed_ += bytes_to_copy;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_extracted += bytes_to_copy;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    queued_bytes_ -= bytes_to_copy;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_GE(queued_bytes_, 0);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
138