// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_PEER_CONNECTION_REMOTE_AUDIO_SOURCE_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_PEER_CONNECTION_REMOTE_AUDIO_SOURCE_H_

#include <memory>

#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_audio_track.h"
#include "third_party/webrtc/api/mediastreaminterface.h"

namespace media {
class AudioBus;
}

namespace content {

// PeerConnectionRemoteAudioTrack is a WebRTC specific implementation of an
// audio track whose data is sourced from a PeerConnection.
class PeerConnectionRemoteAudioTrack final
    : NON_EXPORTED_BASE(public MediaStreamAudioTrack) {
 public:
  explicit PeerConnectionRemoteAudioTrack(
      scoped_refptr<webrtc::AudioTrackInterface> track_interface);
  ~PeerConnectionRemoteAudioTrack() final;

  // If |track| is an instance of PeerConnectionRemoteAudioTrack, return a
  // type-casted pointer to it. Otherwise, return null.
  static PeerConnectionRemoteAudioTrack* From(MediaStreamAudioTrack* track);

  webrtc::AudioTrackInterface* track_interface() const {
    return track_interface_.get();
  }

  // MediaStreamAudioTrack override.
  void SetEnabled(bool enabled) override;

 private:
  // MediaStreamAudioTrack overrides.
  void* GetClassIdentifier() const final;

  const scoped_refptr<webrtc::AudioTrackInterface> track_interface_;

  // In debug builds, check that all methods that could cause object graph
  // or data flow changes are being called on the main thread.
  base::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN(PeerConnectionRemoteAudioTrack);
};

// Represents the audio provided by the receiving end of a PeerConnection.
class PeerConnectionRemoteAudioSource final
    : NON_EXPORTED_BASE(public MediaStreamAudioSource),
      NON_EXPORTED_BASE(protected webrtc::AudioTrackSinkInterface) {
 public:
  explicit PeerConnectionRemoteAudioSource(
      scoped_refptr<webrtc::AudioTrackInterface> track_interface);
  ~PeerConnectionRemoteAudioSource() final;

 protected:
  // MediaStreamAudioSource implementation.
  std::unique_ptr<MediaStreamAudioTrack> CreateMediaStreamAudioTrack(
      const std::string& id) final;
  bool EnsureSourceIsStarted() final;
  void EnsureSourceIsStopped() final;

  // webrtc::AudioTrackSinkInterface implementation.
  void OnData(const void* audio_data, int bits_per_sample, int sample_rate,
              size_t number_of_channels, size_t number_of_frames) final;

 private:
  // Interface to the implementation that calls OnData().
  const scoped_refptr<webrtc::AudioTrackInterface> track_interface_;

  // In debug builds, check that all methods that could cause object graph
  // or data flow changes are being called on the main thread.
  base::ThreadChecker thread_checker_;

  // True if |this| is receiving an audio flow as a sink of the remote
  // PeerConnection via |track_interface_|.
  bool is_sink_of_peer_connection_;

  // Buffer for converting from interleaved signed-integer PCM samples to the
  // planar float format. Only used on the thread that calls OnData().
  std::unique_ptr<media::AudioBus> audio_bus_;

  // In debug builds, use a "try lock" to sanity-check that there are no
  // concurrent calls to OnData(). See notes in OnData() implementation.
#ifndef NDEBUG
  base::Lock single_audio_thread_guard_;
#endif

  DISALLOW_COPY_AND_ASSIGN(PeerConnectionRemoteAudioSource);
};

}  // namespace content

#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_PEER_CONNECTION_REMOTE_AUDIO_SOURCE_H_
