Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MEDIA_BASE_AUDIO_BUS_H_ | 5 #ifndef MEDIA_BASE_AUDIO_BUS_H_ |
| 6 #define MEDIA_BASE_AUDIO_BUS_H_ | 6 #define MEDIA_BASE_AUDIO_BUS_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/aligned_memory.h" | 14 #include "base/memory/aligned_memory.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "media/base/media_export.h" | 16 #include "media/base/media_export.h" |
| 17 | 17 |
| 18 namespace media { | 18 namespace media { |
| 19 class AudioParameters; | 19 class AudioParameters; |
| 20 | 20 |
| 21 // Scoped container for "busing" audio channel data around. Each channel is | 21 // Represents a sequence of audio frames containing frames() audio samples for |
| 22 // stored in planar format and guaranteed to be aligned by kChannelAlignment. | 22 // each of channels() channels. The data is stored as a set of contiguous |
| 23 // AudioBus objects can be created normally or via wrapping. Normally, AudioBus | 23 // float arrays with one array per channel. The memory for the arrays is either |
| 24 // will dice up a contiguous memory block for channel data. When wrapped, | 24 // allocated and owned by the AudioBus or it is provided to one of the factory |
| 25 // AudioBus instead routes requests for channel data to the wrapped object. | 25 // methods. AudioBus guarantees that it allocates memory such that float array |
| 26 // for each channel is aligned by AudioBus::kChannelAlignment bytes and it | |
| 27 // requires the same for memory passed to its Wrap...() factory methods. | |
| 28 // TODO(chfremer): There are currently no unit tests involving CreateWrapper and | |
| 29 // SetChannelData, so we need to add them. | |
| 26 class MEDIA_EXPORT AudioBus { | 30 class MEDIA_EXPORT AudioBus { |
| 27 public: | 31 public: |
| 28 // Guaranteed alignment of each channel's data; use 16-byte alignment for easy | 32 // Guaranteed alignment of each channel's data; use 16-byte alignment for easy |
| 29 // SSE optimizations. | 33 // SSE optimizations. |
| 30 enum { kChannelAlignment = 16 }; | 34 enum { kChannelAlignment = 16 }; |
| 31 | 35 |
| 32 // Creates a new AudioBus and allocates |channels| of length |frames|. Uses | 36 // Creates a new AudioBus and allocates |channels| of length |frames|. Uses |
| 33 // channels() and frames_per_buffer() from AudioParameters if given. | 37 // channels() and frames_per_buffer() from AudioParameters if given. |
| 34 static std::unique_ptr<AudioBus> Create(int channels, int frames); | 38 static std::unique_ptr<AudioBus> Create(int channels, int frames); |
| 35 static std::unique_ptr<AudioBus> Create(const AudioParameters& params); | 39 static std::unique_ptr<AudioBus> Create(const AudioParameters& params); |
| 36 | 40 |
| 37 // Creates a new AudioBus with the given number of channels, but zero length. | 41 // Creates a new AudioBus with the given number of channels, but zero length. |
| 38 // It's expected to be used with SetChannelData() and set_frames() to | 42 // Clients are expected to subsequently call SetChannelData() and set_frames() |
| 39 // wrap externally allocated memory. | 43 // to wrap externally allocated memory. |
| 40 static std::unique_ptr<AudioBus> CreateWrapper(int channels); | 44 static std::unique_ptr<AudioBus> CreateWrapper(int channels); |
| 41 | 45 |
| 42 // Creates a new AudioBus from an existing channel vector. Does not transfer | 46 // Creates a new AudioBus from an existing channel vector. Does not transfer |
| 43 // ownership of |channel_data| to AudioBus; i.e., |channel_data| must outlive | 47 // ownership of |channel_data| to AudioBus; i.e., |channel_data| must outlive |
| 44 // the returned AudioBus. Each channel must be aligned by kChannelAlignment. | 48 // the returned AudioBus. Each channel must be aligned by kChannelAlignment. |
| 45 static std::unique_ptr<AudioBus> WrapVector( | 49 static std::unique_ptr<AudioBus> WrapVector( |
| 46 int frames, | 50 int frames, |
| 47 const std::vector<float*>& channel_data); | 51 const std::vector<float*>& channel_data); |
| 48 | 52 |
| 49 // Creates a new AudioBus by wrapping an existing block of memory. Block must | 53 // Creates a new AudioBus by wrapping an existing block of memory. Block must |
| 50 // be at least CalculateMemorySize() bytes in size. |data| must outlive the | 54 // be at least CalculateMemorySize() bytes in size. |data| must outlive the |
| 51 // returned AudioBus. |data| must be aligned by kChannelAlignment. | 55 // returned AudioBus. |data| must be aligned by kChannelAlignment. |
| 52 static std::unique_ptr<AudioBus> WrapMemory(int channels, | 56 static std::unique_ptr<AudioBus> WrapMemory(int channels, |
| 53 int frames, | 57 int frames, |
| 54 void* data); | 58 void* data); |
| 55 static std::unique_ptr<AudioBus> WrapMemory(const AudioParameters& params, | 59 static std::unique_ptr<AudioBus> WrapMemory(const AudioParameters& params, |
| 56 void* data); | 60 void* data); |
| 61 | |
| 62 // Based on the given number of channels and frames, calculates the minimum | |
| 63 // required size in bytes of a contiguous block of memory to be passed to | |
| 64 // AudioBus for storage of the audio data. | |
| 65 // Uses channels() and frames_per_buffer() from AudioParameters if given. | |
| 66 static int CalculateMemorySize(int channels, int frames); | |
| 57 static int CalculateMemorySize(const AudioParameters& params); | 67 static int CalculateMemorySize(const AudioParameters& params); |
| 58 | 68 |
| 59 // Calculates the required size for an AudioBus given the number of channels | 69 // Methods that are expected to be called after AudioBus::CreateWrapper() in |
| 60 // and frames. | 70 // order to wrap externally allocated memory. Note: It is illegal to call |
| 61 static int CalculateMemorySize(int channels, int frames); | 71 // these methods when using a factory method other than CreateWrapper(). |
| 72 void SetChannelData(int channel, float* data); | |
| 73 void set_frames(int frames); | |
| 62 | 74 |
| 63 // Helper methods for converting an AudioBus from and to interleaved integer | 75 // Overwrites the sample values stored in this AudioBus instance with values |
| 64 // data. Expects interleaving to be [ch0, ch1, ..., chN, ch0, ch1, ...] with | 76 // from a given interleaved |source_buffer| with expected layout |
| 65 // |bytes_per_sample| per value. Values are scaled and bias corrected during | 77 // [ch0, ch1, ..., chN, ch0, ch1, ...] and sample values in the format |
| 66 // conversion. ToInterleaved() will also clip values to format range. | 78 // corresponding to the given SourceSampleTypeTraits. |
| 67 // Handles uint8_t, int16_t, and int32_t currently. FromInterleaved() will | 79 // The sample values are converted to float values by means of the method |
| 68 // zero out | 80 // convert_to_float32() provided by the SourceSampleTypeTraits. For a list of |
| 69 // any unfilled frames when |frames| is less than frames(). | 81 // ready-to-use SampleTypeTraits, see file audio_sample_types.h. |
| 82 // If |num_frames_to_write| is less than frames(), the remaining frames are | |
| 83 // zeroed out. If |num_frames_to_write| is more than frames(), this results in | |
| 84 // undefined behavior. | |
| 85 template <class SourceSampleTypeTraits> | |
| 86 void FromInterleaved( | |
| 87 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 88 int num_frames_to_write); | |
| 89 | |
| 90 // DEPRECATED | |
| 91 // Please use the version templated with SourceSampleTypeTraits instead. | |
| 70 void FromInterleaved(const void* source, int frames, int bytes_per_sample); | 92 void FromInterleaved(const void* source, int frames, int bytes_per_sample); |
| 71 void ToInterleaved(int frames, int bytes_per_sample, void* dest) const; | |
| 72 void ToInterleavedPartial(int start_frame, int frames, int bytes_per_sample, | |
| 73 void* dest) const; | |
| 74 | 93 |
| 75 // Similar to FromInterleaved() above, but meant for streaming sources. Does | 94 // Similar to FromInterleaved...(), but overwrites the frames starting at a |
| 76 // not zero out remaining frames, the caller is responsible for doing so using | 95 // given offset |write_offset_in_frames| and does not zero out frames that are |
| 77 // ZeroFramesPartial(). Frames are deinterleaved from the start of |source| | 96 // not overwritten. |
| 78 // to channel(x)[start_frame]. | 97 template <class SourceSampleTypeTraits> |
| 98 void FromInterleavedPartial( | |
| 99 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 100 int write_offset_in_frames, | |
| 101 int num_frames_to_write); | |
| 102 | |
| 103 // DEPRECATED | |
| 104 // Please use the version templated with SourceSampleTypeTraits instead. | |
| 79 void FromInterleavedPartial(const void* source, int start_frame, int frames, | 105 void FromInterleavedPartial(const void* source, int start_frame, int frames, |
| 80 int bytes_per_sample); | 106 int bytes_per_sample); |
| 81 | 107 |
| 108 // Reads the sample values stored in this AudioBus instance and places them | |
| 109 // into the given |dest_buffer| in interleaved format using the sample format | |
| 110 // specified by TargetSampleTypeTraits. For a list of ready-to-use | |
| 111 // SampleTypeTraits, see file audio_sample_types.h. If |num_frames_to_read| is | |
| 112 // larger than frames(), this results in undefined behavior. | |
| 113 template <class TargetSampleTypeTraits> | |
| 114 void ToInterleaved( | |
| 115 int num_frames_to_read, | |
| 116 typename TargetSampleTypeTraits::ValueType* dest_buffer) const; | |
| 117 | |
| 118 // DEPRECATED | |
|
mcasas
2016/06/12 09:41:48
nit: mention the bug
// DEPRECATED (https://crbug.
chfremer
2016/06/13 17:44:11
Done.
| |
| 119 // Please use the version templated with TargetSampleTypeTraits instead. | |
| 120 void ToInterleaved(int frames, int bytes_per_sample, void* dest) const; | |
| 121 | |
| 122 // Similar to ToInterleaved(), but reads the frames starting at a given | |
| 123 // offset |read_offset_in_frames|. | |
| 124 template <class TargetSampleTypeTraits> | |
| 125 void ToInterleavedPartial( | |
| 126 int read_offset_in_frames, | |
| 127 int num_frames_to_read, | |
| 128 typename TargetSampleTypeTraits::ValueType* dest_buffer) const; | |
| 129 | |
| 130 // DEPRECATED | |
|
mcasas
2016/06/12 09:41:48
Idem.
chfremer
2016/06/13 17:44:11
Done.
| |
| 131 // Please use the version templated with TargetSampleTypeTraits instead. | |
| 132 void ToInterleavedPartial(int start_frame, | |
| 133 int frames, | |
| 134 int bytes_per_sample, | |
| 135 void* dest) const; | |
| 136 | |
| 82 // Helper method for copying channel data from one AudioBus to another. Both | 137 // Helper method for copying channel data from one AudioBus to another. Both |
| 83 // AudioBus object must have the same frames() and channels(). | 138 // AudioBus object must have the same frames() and channels(). |
| 84 void CopyTo(AudioBus* dest) const; | 139 void CopyTo(AudioBus* dest) const; |
| 85 | 140 |
| 86 // Helper method to copy frames from one AudioBus to another. Both AudioBus | 141 // Helper method to copy frames from one AudioBus to another. Both AudioBus |
| 87 // objects must have the same number of channels(). |source_start_frame| is | 142 // objects must have the same number of channels(). |source_start_frame| is |
| 88 // the starting offset. |dest_start_frame| is the starting offset in |dest|. | 143 // the starting offset. |dest_start_frame| is the starting offset in |dest|. |
| 89 // |frame_count| is the number of frames to copy. | 144 // |frame_count| is the number of frames to copy. |
| 90 void CopyPartialFramesTo(int source_start_frame, | 145 void CopyPartialFramesTo(int source_start_frame, |
| 91 int frame_count, | 146 int frame_count, |
| 92 int dest_start_frame, | 147 int dest_start_frame, |
| 93 AudioBus* dest) const; | 148 AudioBus* dest) const; |
| 94 | 149 |
| 95 // Returns a raw pointer to the requested channel. Pointer is guaranteed to | 150 // Returns a raw pointer to the requested channel. Pointer is guaranteed to |
| 96 // have a 16-byte alignment. Warning: Do not rely on having sane (i.e. not | 151 // have a 16-byte alignment. Warning: Do not rely on having sane (i.e. not |
| 97 // inf, nan, or between [-1.0, 1.0]) values in the channel data. | 152 // inf, nan, or between [-1.0, 1.0]) values in the channel data. |
| 98 float* channel(int channel) { return channel_data_[channel]; } | 153 float* channel(int channel) { return channel_data_[channel]; } |
| 99 const float* channel(int channel) const { return channel_data_[channel]; } | 154 const float* channel(int channel) const { return channel_data_[channel]; } |
| 100 void SetChannelData(int channel, float* data); | |
| 101 | 155 |
| 156 // Returns the number of channels. | |
| 102 int channels() const { return static_cast<int>(channel_data_.size()); } | 157 int channels() const { return static_cast<int>(channel_data_.size()); } |
| 158 // Returns the number of frames. | |
| 103 int frames() const { return frames_; } | 159 int frames() const { return frames_; } |
| 104 void set_frames(int frames); | |
| 105 | 160 |
| 106 // Helper method for zeroing out all channels of audio data. | 161 // Helper method for zeroing out all channels of audio data. |
| 107 void Zero(); | 162 void Zero(); |
| 108 void ZeroFrames(int frames); | 163 void ZeroFrames(int frames); |
| 109 void ZeroFramesPartial(int start_frame, int frames); | 164 void ZeroFramesPartial(int start_frame, int frames); |
| 110 | 165 |
| 111 // Checks if all frames are zero. | 166 // Checks if all frames are zero. |
| 112 bool AreFramesZero() const; | 167 bool AreFramesZero() const; |
| 113 | 168 |
| 114 // Scale internal channel values by |volume| >= 0. If an invalid value | 169 // Scale internal channel values by |volume| >= 0. If an invalid value |
| 115 // is provided, no adjustment is done. | 170 // is provided, no adjustment is done. |
| 116 void Scale(float volume); | 171 void Scale(float volume); |
| 117 | 172 |
| 118 // Swaps channels identified by |a| and |b|. The caller needs to make sure | 173 // Swaps channels identified by |a| and |b|. The caller needs to make sure |
| 119 // the channels are valid. | 174 // the channels are valid. |
| 120 void SwapChannels(int a, int b); | 175 void SwapChannels(int a, int b); |
| 121 | 176 |
| 122 virtual ~AudioBus(); | 177 virtual ~AudioBus(); |
| 123 | 178 |
| 124 protected: | 179 protected: |
| 125 AudioBus(int channels, int frames); | 180 AudioBus(int channels, int frames); |
| 126 AudioBus(int channels, int frames, float* data); | 181 AudioBus(int channels, int frames, float* data); |
| 127 AudioBus(int frames, const std::vector<float*>& channel_data); | 182 AudioBus(int frames, const std::vector<float*>& channel_data); |
| 128 explicit AudioBus(int channels); | 183 explicit AudioBus(int channels); |
| 129 | 184 |
| 130 private: | 185 private: |
| 131 // Helper method for building |channel_data_| from a block of memory. |data| | 186 // Helper method for building |channel_data_| from a block of memory. |data| |
| 132 // must be at least BlockSize() bytes in size. | 187 // must be at least CalculateMemorySize(...) bytes in size. |
| 133 void BuildChannelData(int channels, int aligned_frame, float* data); | 188 void BuildChannelData(int channels, int aligned_frame, float* data); |
| 134 | 189 |
| 190 static void CheckOverflow(int start_frame, int frames, int total_frames); | |
| 191 | |
| 192 template <class SourceSampleTypeTraits> | |
| 193 static void CopyConvertFromInterleavedSourceToAudioBus( | |
| 194 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 195 int write_offset_in_frames, | |
| 196 int num_frames_to_write, | |
| 197 AudioBus* dest); | |
| 198 | |
| 199 template <class TargetSampleTypeTraits> | |
| 200 static void CopyConvertFromAudioBusToInterleavedTarget( | |
| 201 const AudioBus* source, | |
| 202 int read_offset_in_frames, | |
| 203 int num_frames_to_read, | |
| 204 typename TargetSampleTypeTraits::ValueType* dest_buffer); | |
| 205 | |
| 135 // Contiguous block of channel memory. | 206 // Contiguous block of channel memory. |
| 136 std::unique_ptr<float, base::AlignedFreeDeleter> data_; | 207 std::unique_ptr<float, base::AlignedFreeDeleter> data_; |
| 137 | 208 |
| 209 // One float pointer per channel pointing to a contiguous block of memory for | |
| 210 // that channel. If the memory is owned by this instance, this will | |
| 211 // point to the memory in |data_|. Otherwise, it may point to memory provided | |
| 212 // by the client. | |
| 138 std::vector<float*> channel_data_; | 213 std::vector<float*> channel_data_; |
| 139 int frames_; | 214 int frames_; |
| 140 | 215 |
| 141 // Protect SetChannelData() and set_frames() for use by CreateWrapper(). | 216 // Protect SetChannelData() and set_frames() for use by CreateWrapper(). |
| 142 bool can_set_channel_data_; | 217 bool can_set_channel_data_; |
| 143 | 218 |
| 144 DISALLOW_COPY_AND_ASSIGN(AudioBus); | 219 DISALLOW_COPY_AND_ASSIGN(AudioBus); |
| 145 }; | 220 }; |
| 146 | 221 |
| 222 // Delegates to FromInterleavedPartial() | |
| 223 template <class SourceSampleTypeTraits> | |
| 224 void AudioBus::FromInterleaved( | |
| 225 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 226 int num_frames_to_write) { | |
| 227 FromInterleavedPartial<SourceSampleTypeTraits>(source_buffer, 0, | |
| 228 num_frames_to_write); | |
| 229 // Zero any remaining frames. | |
| 230 ZeroFramesPartial(num_frames_to_write, frames_ - num_frames_to_write); | |
| 231 } | |
| 232 | |
| 233 template <class SourceSampleTypeTraits> | |
| 234 void AudioBus::FromInterleavedPartial( | |
| 235 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 236 int write_offset_in_frames, | |
| 237 int num_frames_to_write) { | |
| 238 CheckOverflow(write_offset_in_frames, num_frames_to_write, frames_); | |
| 239 CopyConvertFromInterleavedSourceToAudioBus<SourceSampleTypeTraits>( | |
| 240 source_buffer, write_offset_in_frames, num_frames_to_write, this); | |
| 241 } | |
| 242 | |
| 243 // Delegates to ToInterleavedPartial() | |
| 244 template <class TargetSampleTypeTraits> | |
| 245 void AudioBus::ToInterleaved( | |
| 246 int num_frames_to_read, | |
| 247 typename TargetSampleTypeTraits::ValueType* dest_buffer) const { | |
| 248 ToInterleavedPartial<TargetSampleTypeTraits>(0, num_frames_to_read, | |
| 249 dest_buffer); | |
| 250 } | |
| 251 | |
| 252 // TODO(dalecurtis): See if intrinsic optimizations help any here (for each | |
| 253 // sample type) | |
| 254 template <class TargetSampleTypeTraits> | |
| 255 void AudioBus::ToInterleavedPartial( | |
| 256 int read_offset_in_frames, | |
| 257 int num_frames_to_read, | |
| 258 typename TargetSampleTypeTraits::ValueType* dest) const { | |
| 259 CheckOverflow(read_offset_in_frames, num_frames_to_read, frames_); | |
| 260 CopyConvertFromAudioBusToInterleavedTarget<TargetSampleTypeTraits>( | |
| 261 this, read_offset_in_frames, num_frames_to_read, dest); | |
| 262 } | |
| 263 | |
| 264 template <class SourceSampleTypeTraits> | |
| 265 void AudioBus::CopyConvertFromInterleavedSourceToAudioBus( | |
| 266 const typename SourceSampleTypeTraits::ValueType* source_buffer, | |
| 267 int write_offset_in_frames, | |
| 268 int num_frames_to_write, | |
| 269 AudioBus* dest) { | |
| 270 const int channels = dest->channels(); | |
| 271 for (int ch = 0; ch < channels; ++ch) { | |
| 272 float* channel_data = dest->channel(ch); | |
| 273 for (int target_frame_index = write_offset_in_frames, | |
| 274 read_pos_in_source = ch; | |
| 275 target_frame_index < write_offset_in_frames + num_frames_to_write; | |
| 276 ++target_frame_index, read_pos_in_source += channels) { | |
| 277 auto source_value = source_buffer[read_pos_in_source]; | |
| 278 channel_data[target_frame_index] = | |
| 279 SourceSampleTypeTraits::ConvertToFloat(source_value); | |
| 280 } | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 template <class TargetSampleTypeTraits> | |
| 285 void AudioBus::CopyConvertFromAudioBusToInterleavedTarget( | |
|
mcasas
2016/06/12 09:41:48
I understand that miu@ commented on the
appropriat
chfremer
2016/06/13 17:44:11
Done.
| |
| 286 const AudioBus* source, | |
| 287 int read_offset_in_frames, | |
| 288 int num_frames_to_read, | |
| 289 typename TargetSampleTypeTraits::ValueType* dest_buffer) { | |
| 290 const int channels = source->channels(); | |
| 291 for (int ch = 0; ch < channels; ++ch) { | |
| 292 const float* channel_data = source->channel(ch); | |
| 293 for (int source_frame_index = read_offset_in_frames, write_pos_in_dest = ch; | |
| 294 source_frame_index < read_offset_in_frames + num_frames_to_read; | |
| 295 ++source_frame_index, write_pos_in_dest += channels) { | |
| 296 float sourceSampleValue = channel_data[source_frame_index]; | |
| 297 dest_buffer[write_pos_in_dest] = | |
| 298 TargetSampleTypeTraits::ConvertFromFloat(sourceSampleValue); | |
| 299 } | |
| 300 } | |
| 301 } | |
| 302 | |
| 147 // RefCounted version of AudioBus. This is not meant for general use. Only use | 303 // RefCounted version of AudioBus. This is not meant for general use. Only use |
| 148 // this when your lifetime requirements make it impossible to use an | 304 // this when your lifetime requirements make it impossible to use an |
| 149 // AudioBus scoped_ptr. | 305 // AudioBus scoped_ptr. |
| 150 class MEDIA_EXPORT AudioBusRefCounted | 306 class MEDIA_EXPORT AudioBusRefCounted |
| 151 : public media::AudioBus, | 307 : public media::AudioBus, |
| 152 public base::RefCountedThreadSafe<AudioBusRefCounted> { | 308 public base::RefCountedThreadSafe<AudioBusRefCounted> { |
| 153 public: | 309 public: |
| 154 static scoped_refptr<AudioBusRefCounted> Create(int channels, int frames); | 310 static scoped_refptr<AudioBusRefCounted> Create(int channels, int frames); |
| 155 | 311 |
| 156 private: | 312 private: |
| 157 friend class base::RefCountedThreadSafe<AudioBusRefCounted>; | 313 friend class base::RefCountedThreadSafe<AudioBusRefCounted>; |
| 158 | 314 |
| 159 AudioBusRefCounted(int channels, int frames); | 315 AudioBusRefCounted(int channels, int frames); |
| 160 ~AudioBusRefCounted() override; | 316 ~AudioBusRefCounted() override; |
| 161 | 317 |
| 162 DISALLOW_COPY_AND_ASSIGN(AudioBusRefCounted); | 318 DISALLOW_COPY_AND_ASSIGN(AudioBusRefCounted); |
| 163 }; | 319 }; |
| 164 | 320 |
| 165 } // namespace media | 321 } // namespace media |
| 166 | 322 |
| 167 #endif // MEDIA_BASE_AUDIO_BUS_H_ | 323 #endif // MEDIA_BASE_AUDIO_BUS_H_ |
| OLD | NEW |