Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #ifndef API_AUDIO_AUDIO_FRAME_H_ |
| 12 | #define API_AUDIO_AUDIO_FRAME_H_ |
| 13 | |
Fredrik Solenberg | bbf21a3 | 2018-04-12 22:44:09 +0200 | [diff] [blame] | 14 | #include <stddef.h> |
Niels Möller | a12c42a | 2018-07-25 16:05:48 +0200 | [diff] [blame] | 15 | #include <stdint.h> |
Fredrik Solenberg | bbf21a3 | 2018-04-12 22:44:09 +0200 | [diff] [blame] | 16 | |
henrika | 2250b05 | 2019-07-04 11:27:52 +0200 | [diff] [blame] | 17 | #include "api/audio/channel_layout.h" |
Alessio Bazzica | 8f319a3 | 2019-07-24 16:47:02 +0000 | [diff] [blame] | 18 | #include "api/rtp_packet_infos.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 19 | #include "rtc_base/constructor_magic.h" |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 20 | |
| 21 | namespace webrtc { |
| 22 | |
henrika | 2a49065 | 2018-08-28 15:52:10 +0200 | [diff] [blame] | 23 | /* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 24 | * allows for adding and subtracting frames while keeping track of the resulting |
| 25 | * states. |
| 26 | * |
| 27 | * Notes |
| 28 | * - This is a de-facto api, not designed for external use. The AudioFrame class |
| 29 | * is in need of overhaul or even replacement, and anyone depending on it |
| 30 | * should be prepared for that. |
| 31 | * - The total number of samples is samples_per_channel_ * num_channels_. |
| 32 | * - Stereo data is interleaved starting with the left channel. |
| 33 | */ |
| 34 | class AudioFrame { |
| 35 | public: |
| 36 | // Using constexpr here causes linker errors unless the variable also has an |
| 37 | // out-of-class definition, which is impractical in this header-only class. |
| 38 | // (This makes no sense because it compiles as an enum value, which we most |
| 39 | // certainly cannot take the address of, just fine.) C++17 introduces inline |
| 40 | // variables which should allow us to switch to constexpr and keep this a |
| 41 | // header-only class. |
| 42 | enum : size_t { |
henrika | 2a49065 | 2018-08-28 15:52:10 +0200 | [diff] [blame] | 43 | // Stereo, 32 kHz, 120 ms (2 * 32 * 120) |
| 44 | // Stereo, 192 kHz, 20 ms (2 * 192 * 20) |
| 45 | kMaxDataSizeSamples = 7680, |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 46 | kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t), |
| 47 | }; |
| 48 | |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 49 | enum VADActivity { kVadActive = 0, kVadPassive = 1, kVadUnknown = 2 }; |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 50 | enum SpeechType { |
| 51 | kNormalSpeech = 0, |
| 52 | kPLC = 1, |
| 53 | kCNG = 2, |
| 54 | kPLCCNG = 3, |
Alex Narest | 5b5d97c | 2019-08-07 18:15:08 +0200 | [diff] [blame] | 55 | kCodecPLC = 5, |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 56 | kUndefined = 4 |
| 57 | }; |
| 58 | |
| 59 | AudioFrame(); |
| 60 | |
| 61 | // Resets all members to their default state. |
| 62 | void Reset(); |
| 63 | // Same as Reset(), but leaves mute state unchanged. Muting a frame requires |
| 64 | // the buffer to be zeroed on the next call to mutable_data(). Callers |
| 65 | // intending to write to the buffer immediately after Reset() can instead use |
| 66 | // ResetWithoutMuting() to skip this wasteful zeroing. |
| 67 | void ResetWithoutMuting(); |
| 68 | |
Yves Gerey | 665174f | 2018-06-19 15:03:05 +0200 | [diff] [blame] | 69 | void UpdateFrame(uint32_t timestamp, |
| 70 | const int16_t* data, |
| 71 | size_t samples_per_channel, |
| 72 | int sample_rate_hz, |
| 73 | SpeechType speech_type, |
| 74 | VADActivity vad_activity, |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 75 | size_t num_channels = 1); |
| 76 | |
| 77 | void CopyFrom(const AudioFrame& src); |
| 78 | |
| 79 | // Sets a wall-time clock timestamp in milliseconds to be used for profiling |
| 80 | // of time between two points in the audio chain. |
| 81 | // Example: |
| 82 | // t0: UpdateProfileTimeStamp() |
| 83 | // t1: ElapsedProfileTimeMs() => t1 - t0 [msec] |
| 84 | void UpdateProfileTimeStamp(); |
| 85 | // Returns the time difference between now and when UpdateProfileTimeStamp() |
| 86 | // was last called. Returns -1 if UpdateProfileTimeStamp() has not yet been |
| 87 | // called. |
| 88 | int64_t ElapsedProfileTimeMs() const; |
| 89 | |
| 90 | // data() returns a zeroed static buffer if the frame is muted. |
| 91 | // mutable_frame() always returns a non-static buffer; the first call to |
| 92 | // mutable_frame() zeros the non-static buffer and marks the frame unmuted. |
| 93 | const int16_t* data() const; |
| 94 | int16_t* mutable_data(); |
| 95 | |
| 96 | // Prefer to mute frames using AudioFrameOperations::Mute. |
| 97 | void Mute(); |
| 98 | // Frame is muted by default. |
| 99 | bool muted() const; |
| 100 | |
henrika | 2250b05 | 2019-07-04 11:27:52 +0200 | [diff] [blame] | 101 | size_t max_16bit_samples() const { return kMaxDataSizeSamples; } |
| 102 | size_t samples_per_channel() const { return samples_per_channel_; } |
| 103 | size_t num_channels() const { return num_channels_; } |
| 104 | ChannelLayout channel_layout() const { return channel_layout_; } |
| 105 | int sample_rate_hz() const { return sample_rate_hz_; } |
| 106 | |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 107 | // RTP timestamp of the first sample in the AudioFrame. |
| 108 | uint32_t timestamp_ = 0; |
| 109 | // Time since the first frame in milliseconds. |
| 110 | // -1 represents an uninitialized value. |
| 111 | int64_t elapsed_time_ms_ = -1; |
| 112 | // NTP time of the estimated capture time in local timebase in milliseconds. |
| 113 | // -1 represents an uninitialized value. |
| 114 | int64_t ntp_time_ms_ = -1; |
| 115 | size_t samples_per_channel_ = 0; |
| 116 | int sample_rate_hz_ = 0; |
| 117 | size_t num_channels_ = 0; |
henrika | 2250b05 | 2019-07-04 11:27:52 +0200 | [diff] [blame] | 118 | ChannelLayout channel_layout_ = CHANNEL_LAYOUT_NONE; |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 119 | SpeechType speech_type_ = kUndefined; |
| 120 | VADActivity vad_activity_ = kVadUnknown; |
| 121 | // Monotonically increasing timestamp intended for profiling of audio frames. |
| 122 | // Typically used for measuring elapsed time between two different points in |
| 123 | // the audio path. No lock is used to save resources and we are thread safe |
Danil Chapovalov | 0bc58cf | 2018-06-21 13:32:56 +0200 | [diff] [blame] | 124 | // by design. Also, absl::optional is not used since it will cause a "complex |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 125 | // class/struct needs an explicit out-of-line destructor" build error. |
| 126 | int64_t profile_timestamp_ms_ = 0; |
| 127 | |
Alessio Bazzica | 8f319a3 | 2019-07-24 16:47:02 +0000 | [diff] [blame] | 128 | // Information about packets used to assemble this audio frame. This is needed |
| 129 | // by |SourceTracker| when the frame is delivered to the RTCRtpReceiver's |
| 130 | // MediaStreamTrack, in order to implement getContributingSources(). See: |
| 131 | // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getcontributingsources |
| 132 | // |
| 133 | // TODO(bugs.webrtc.org/10757): |
| 134 | // Note that this information might not be fully accurate since we currently |
| 135 | // don't have a proper way to track it across the audio sync buffer. The |
| 136 | // sync buffer is the small sample-holding buffer located after the audio |
| 137 | // decoder and before where samples are assembled into output frames. |
| 138 | // |
| 139 | // |RtpPacketInfos| may also be empty if the audio samples did not come from |
| 140 | // RTP packets. E.g. if the audio were locally generated by packet loss |
| 141 | // concealment, comfort noise generation, etc. |
| 142 | RtpPacketInfos packet_infos_; |
| 143 | |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 144 | private: |
henrika | 2250b05 | 2019-07-04 11:27:52 +0200 | [diff] [blame] | 145 | // A permanently zeroed out buffer to represent muted frames. This is a |
Niels Möller | d377f04 | 2018-02-13 15:03:43 +0100 | [diff] [blame] | 146 | // header-only class, so the only way to avoid creating a separate empty |
| 147 | // buffer per translation unit is to wrap a static in an inline function. |
| 148 | static const int16_t* empty_data(); |
| 149 | |
| 150 | int16_t data_[kMaxDataSizeSamples]; |
| 151 | bool muted_ = true; |
| 152 | |
| 153 | RTC_DISALLOW_COPY_AND_ASSIGN(AudioFrame); |
| 154 | }; |
| 155 | |
| 156 | } // namespace webrtc |
| 157 | |
| 158 | #endif // API_AUDIO_AUDIO_FRAME_H_ |