1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168

media / fuchsia / audio / fake_audio_consumer.h [blame]

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

#ifndef MEDIA_FUCHSIA_AUDIO_FAKE_AUDIO_CONSUMER_H_
#define MEDIA_FUCHSIA_AUDIO_FAKE_AUDIO_CONSUMER_H_

#include <fuchsia/media/audio/cpp/fidl.h>
#include <fuchsia/media/audio/cpp/fidl_test_base.h>
#include <fuchsia/media/cpp/fidl.h>
#include <fuchsia/media/cpp/fidl_test_base.h>
#include <lib/fidl/cpp/binding.h>

#include <list>
#include <vector>

#include "base/fuchsia/scoped_service_binding.h"
#include "base/time/time.h"
#include "base/timer/timer.h"

namespace vfs {
class PseudoDir;
}  // namespace vfs

namespace media {

// Fake implementation of fuchsia::media::AudioConsumer interface. Used for
// tests.
class FakeAudioConsumer final
    : public fuchsia::media::testing::AudioConsumer_TestBase,
      public fuchsia::media::testing::StreamSink_TestBase,
      public fuchsia::media::audio::testing::VolumeControl_TestBase {
 public:
  // Lead time range returned from WatchStatus().
  static const base::TimeDelta kMinLeadTime;
  static const base::TimeDelta kMaxLeadTime;

  FakeAudioConsumer(
      uint64_t session_id,
      fidl::InterfaceRequest<fuchsia::media::AudioConsumer> request);
  ~FakeAudioConsumer() override;

  FakeAudioConsumer(const FakeAudioConsumer&) = delete;
  FakeAudioConsumer& operator=(const FakeAudioConsumer&) = delete;

  uint64_t session_id() { return session_id_; }
  float volume() const { return volume_; }
  bool is_muted() const { return is_muted_; }

  base::TimeDelta GetMediaPosition();

 private:
  enum class State {
    kStopped,
    kPlaying,
    kEndOfStream,
  };

  struct Packet {
    base::TimeDelta pts;
    bool is_eos = false;
  };

  // fuchsia::media::AudioConsumer interface;
  void CreateStreamSink(
      std::vector<zx::vmo> buffers,
      fuchsia::media::AudioStreamType stream_type,
      std::unique_ptr<fuchsia::media::Compression> compression,
      fidl::InterfaceRequest<fuchsia::media::StreamSink> stream_sink_request)
      final;
  void Start(fuchsia::media::AudioConsumerStartFlags flags,
             int64_t reference_time,
             int64_t media_time) override;
  void Stop() override;
  void WatchStatus(WatchStatusCallback callback) override;
  void SetRate(float rate) override;
  void BindVolumeControl(
      fidl::InterfaceRequest<fuchsia::media::audio::VolumeControl>
          volume_control_request) override;

  // fuchsia::media::StreamSink interface.
  void SendPacket(fuchsia::media::StreamPacket packet,
                  SendPacketCallback callback) override;
  void SendPacketNoReply(fuchsia::media::StreamPacket packet) override;
  void EndOfStream() override;
  void DiscardAllPackets(DiscardAllPacketsCallback callback) override;
  void DiscardAllPacketsNoReply() override;

  // fuchsia::media::audio::VolumeControl interface.
  void SetVolume(float volume) override;
  void SetMute(bool mute) override;

  // Not-implemented handler for _TestBase parents.
  void NotImplemented_(const std::string& name) override;

  void ScheduleNextStreamPosUpdate();

  // Updates stream position and drops old packets from the stream.
  void UpdateStreamPos();

  void OnStatusUpdate();
  void CallStatusCallback();

  const uint64_t session_id_;

  fidl::Binding<fuchsia::media::AudioConsumer> audio_consumer_binding_;
  fidl::Binding<fuchsia::media::StreamSink> stream_sink_binding_;
  fidl::Binding<fuchsia::media::audio::VolumeControl> volume_control_binding_;

  size_t num_buffers_ = 0;

  State state_ = State::kStopped;

  bool have_status_update_ = true;
  WatchStatusCallback status_callback_;

  base::TimeTicks reference_time_;

  // Numerator and denumerator for current playback rate.
  uint32_t media_delta_ = 1;
  uint32_t reference_delta_ = 1;

  // Last known media position. Min value indicates that the stream position
  // hasn't been set. If stream is playing then value corresponds to
  // |reference_time_|.
  base::TimeDelta media_pos_ = base::TimeDelta::Min();

  std::list<Packet> pending_packets_;

  // Timer to call UpdateStreamPos() for the next packet.
  base::OneShotTimer update_timer_;

  float volume_ = 1.0;
  bool is_muted_ = false;
};

class FakeAudioConsumerService final
    : public fuchsia::media::testing::SessionAudioConsumerFactory_TestBase {
 public:
  explicit FakeAudioConsumerService(vfs::PseudoDir* pseudo_dir);
  ~FakeAudioConsumerService() override;

  FakeAudioConsumerService(const FakeAudioConsumerService&) = delete;
  FakeAudioConsumerService& operator=(const FakeAudioConsumerService&) = delete;

  size_t num_instances() { return audio_consumers_.size(); }
  FakeAudioConsumer* instance(size_t index) {
    return audio_consumers_[index].get();
  }

 private:
  // fuchsia::media::SessionAudioConsumerFactory implementation.
  void CreateAudioConsumer(uint64_t session_id,
                           fidl::InterfaceRequest<fuchsia::media::AudioConsumer>
                               audio_consumer_request) override;

  // Not-implemented handler for SessionAudioConsumerFactory_TestBase.
  void NotImplemented_(const std::string& name) override;

  base::ScopedServiceBinding<fuchsia::media::SessionAudioConsumerFactory>
      binding_;

  std::vector<std::unique_ptr<FakeAudioConsumer>> audio_consumers_;
};

}  // namespace media

#endif  // MEDIA_FUCHSIA_AUDIO_FAKE_AUDIO_CONSUMER_H_