summaryrefslogtreecommitdiff
path: root/chromium/media/audio/android/opensles_output.h
blob: a932da99c347a40cbc8f02ef384cbd1c9c655aed (plain)
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
// Copyright (c) 2012 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 MEDIA_AUDIO_ANDROID_OPENSLES_OUTPUT_H_
#define MEDIA_AUDIO_ANDROID_OPENSLES_OUTPUT_H_

#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <stddef.h>
#include <stdint.h>

#include <memory>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "media/audio/android/muteable_audio_output_stream.h"
#include "media/audio/android/opensles_util.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_timestamp_helper.h"

namespace media {

class AudioManagerAndroid;

// Implements PCM audio output support for Android using the OpenSLES API.
// This class is created and lives on the Audio Manager thread but recorded
// audio buffers are given to us from an internal OpenSLES audio thread.
// All public methods should be called on the Audio Manager thread.
class OpenSLESOutputStream : public MuteableAudioOutputStream {
 public:
  static const int kMaxNumOfBuffersInQueue = 2;

  OpenSLESOutputStream(AudioManagerAndroid* manager,
                       const AudioParameters& params,
                       SLint32 stream_type);

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

  ~OpenSLESOutputStream() override;

  // Implementation of MuteableAudioOutputStream.
  bool Open() override;
  void Close() override;
  void Flush() override;
  void Start(AudioSourceCallback* callback) override;
  void Stop() override;
  void SetVolume(double volume) override;
  void GetVolume(double* volume) override;

  // Set the value of |muted_|. It does not affect |volume_| which can be
  // got by calling GetVolume(). See comments for |muted_| below.
  void SetMute(bool muted) override;

 private:
  bool CreatePlayer();

  // Called from OpenSLES specific audio worker thread.
  static void SimpleBufferQueueCallback(
      SLAndroidSimpleBufferQueueItf buffer_queue,
      void* instance);

  // Fills up one buffer by asking the registered source for data.
  // Called from OpenSLES specific audio worker thread.
  void FillBufferQueue();

  // Called from the audio manager thread.
  void FillBufferQueueNoLock();

  // Called in Open();
  void SetupAudioBuffer();

  // Called in Close();
  void ReleaseAudioBuffer();

  // If OpenSLES reports an error this function handles it and passes it to
  // the attached AudioOutputCallback::OnError().
  void HandleError(SLresult error);

  // Cache |hardware_latency_in_ms_| by asking |audio_manager_| for it, if the
  // kUseAudioLatencyFromHAL is enabled.
  void CacheHardwareLatencyIfNeeded();

  // Adjust |position_in_ms| for hardware latency, and return the result.
  base::TimeDelta AdjustPositionForHardwareLatency(uint32_t position_in_ms);

  base::ThreadChecker thread_checker_;

  // Protects |callback_|, |active_buffer_index_|, |audio_data_|,
  // |buffer_size_bytes_| and |simple_buffer_queue_|.
  base::Lock lock_;

  AudioManagerAndroid* audio_manager_;

  // Audio playback stream type.
  // See SLES/OpenSLES_Android.h for details.
  SLint32 stream_type_;

  AudioSourceCallback* callback_;

  // Shared engine interfaces for the app.
  media::ScopedSLObjectItf engine_object_;
  media::ScopedSLObjectItf player_object_;
  media::ScopedSLObjectItf output_mixer_;

  SLPlayItf player_;

  // Buffer queue recorder interface.
  SLAndroidSimpleBufferQueueItf simple_buffer_queue_;

  SLDataFormat_PCM format_;
  SLAndroidDataFormat_PCM_EX float_format_;

  // Audio buffers that are allocated during Open() based on parameters given
  // during construction.
  uint8_t* audio_data_[kMaxNumOfBuffersInQueue];

  int active_buffer_index_;

  bool started_;

  // Volume control coming from hardware. It overrides |volume_| when it's
  // true. Otherwise, use |volume_| for scaling.
  // This is needed because platform voice volume never goes to zero in
  // COMMUNICATION mode on Android.
  bool muted_;

  // Volume level from 0 to 1.
  float volume_;

  int samples_per_second_;

  // On Android 5.0+ we can output directly to float instead of in integer, so
  // there we'll use kSampleFormatF32. If not, this will be kSampleFormatS16.
  SampleFormat sample_format_;

  int bytes_per_frame_;
  size_t buffer_size_bytes_;

  // On API level 25+ we can provide hints to OpenSLES about what type of
  // content the stream is being used for.
  SLuint32 performance_mode_;

  // Used to calculate the delay value for each OnMoreData() call.
  AudioTimestampHelper delay_calculator_;

  // Container for retrieving data from AudioSourceCallback::OnMoreData().
  std::unique_ptr<AudioBus> audio_bus_;

  // Adjustment for hardware latency.  Needed for some cast targets, since
  // OpenSLES's GetPosition doesn't properly account for HAL latency.
  base::TimeDelta hardware_latency_;
};

}  // namespace media

#endif  // MEDIA_AUDIO_ANDROID_OPENSLES_OUTPUT_H_