1 // Copyright 2019 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 #ifndef CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_STREAM_H_
6 #define CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_STREAM_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread_checker.h"
17 #include "base/time/time.h"
18 #include "base/timer/timer.h"
19 #include "chromecast/common/mojom/multiroom.mojom.h"
20 #include "chromecast/media/api/cma_backend.h"
21 #include "media/audio/audio_io.h"
22 #include "media/base/audio_parameters.h"
23 
24 namespace base {
25 class WaitableEvent;
26 }  // namespace base
27 
28 namespace media {
29 class AudioBus;
30 }  // namespace media
31 
32 namespace chromecast {
33 
34 class TaskRunnerImpl;
35 
36 namespace media {
37 
38 class CmaAudioOutput;
39 class CmaBackendFactory;
40 
41 class CmaAudioOutputStream : public CmaBackend::Decoder::Delegate {
42  public:
43   CmaAudioOutputStream(const ::media::AudioParameters& audio_params,
44                        base::TimeDelta buffer_duration,
45                        const std::string& device_id,
46                        CmaBackendFactory* cma_backend_factory);
47   ~CmaAudioOutputStream() override;
48 
49   void SetRunning(bool running);
50   void Initialize(const std::string& application_session_id,
51                   chromecast::mojom::MultiroomInfoPtr multiroom_info);
52   void Start(::media::AudioOutputStream::AudioSourceCallback* source_callback);
53   void Stop(base::WaitableEvent* finished);
54   void Flush(base::WaitableEvent* finished);
55   void Close(base::OnceClosure closure);
56   void SetVolume(double volume);
57 
58  private:
59   enum class CmaBackendState {
60     kUninitialized,
61     kStopped,
62     kPaused,
63     kStarted,
64     kPendingClose,
65   };
66 
67   void PushBuffer();
68 
69   // CmaBackend::Decoder::Delegate implementation:
OnEndOfStream()70   void OnEndOfStream() override {}
71   void OnDecoderError() override;
OnKeyStatusChanged(const std::string & key_id,CastKeyStatus key_status,uint32_t system_code)72   void OnKeyStatusChanged(const std::string& key_id,
73                           CastKeyStatus key_status,
74                           uint32_t system_code) override {}
OnVideoResolutionChanged(const Size & size)75   void OnVideoResolutionChanged(const Size& size) override {}
76   void OnPushBufferComplete(BufferStatus status) override;
77 
78   const bool is_audio_prefetch_;
79 
80   const ::media::AudioParameters audio_params_;
81   const std::string device_id_;
82   CmaBackendFactory* const cma_backend_factory_;
83   std::unique_ptr<CmaAudioOutput> output_;
84 
85   base::Lock running_lock_;
86   bool running_ = true;
87   CmaBackendState cma_backend_state_ = CmaBackendState::kUninitialized;
88   const base::TimeDelta buffer_duration_;
89   std::unique_ptr<::media::AudioBus> audio_bus_;
90   base::OneShotTimer push_timer_;
91   bool push_in_progress_ = false;
92   bool encountered_error_ = false;
93   base::TimeTicks next_push_time_;
94   base::TimeTicks last_push_complete_time_;
95   base::TimeDelta last_rendering_delay_;
96   base::TimeDelta render_buffer_size_estimate_;
97   ::media::AudioOutputStream::AudioSourceCallback* source_callback_ = nullptr;
98 
99   THREAD_CHECKER(media_thread_checker_);
100 
101   DISALLOW_COPY_AND_ASSIGN(CmaAudioOutputStream);
102 };
103 
104 }  // namespace media
105 }  // namespace chromecast
106 
107 #endif  // CHROMECAST_MEDIA_AUDIO_CMA_AUDIO_OUTPUT_STREAM_H_
108