• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
6 #define CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 
12 #include "cast/streaming/encoded_frame.h"
13 #include "cast/streaming/sender.h"
14 #include "platform/api/time.h"
15 
16 extern "C" {
17 struct OpusEncoder;
18 }
19 
20 namespace openscreen {
21 namespace cast {
22 
23 // Wraps the libopus encoder so that the application can stream
24 // interleaved-floats audio samples to a Sender. Either mono or stereo sound is
25 // supported.
26 class StreamingOpusEncoder {
27  public:
28   // Constructs the encoder for mono or stereo sound, dividing the stream of
29   // audio samples up into chunks as determined by the given
30   // |cast_frames_per_second|, and for EncodedFrame output to the given
31   // |sender|. The sample rate of the audio is assumed to be the Sender's fixed
32   // |rtp_timebase()|.
33   StreamingOpusEncoder(int num_channels,
34                        int cast_frames_per_second,
35                        Sender* sender);
36 
37   ~StreamingOpusEncoder();
38 
num_channels()39   int num_channels() const { return num_channels_; }
sample_rate()40   int sample_rate() const { return sender_->rtp_timebase(); }
41 
42   int GetBitrate() const;
43 
44   // Sets the encoder back to its "AUTO" bitrate setting, for standard quality.
45   // This and UseHighQuality() may be called as often as needed as conditions
46   // change.
47   //
48   // Note: As of 2020-01-21, the encoder in "auto bitrate" mode would use a
49   // bitrate of 102kbps for 2-channel, 48 kHz audio and a 10 ms frame size.
50   void UseStandardQuality();
51 
52   // Sets the encoder to use a high bitrate (virtually no artifacts), when
53   // plenty of network bandwidth is available. This and UseStandardQuality() may
54   // be called as often as needed as conditions change.
55   void UseHighQuality();
56 
57   // Encode and send the given |interleaved_samples|, which contains
58   // |num_samples| tuples (i.e., multiply by the number of channels to determine
59   // the number of array elements). The audio is assumed to have been captured
60   // at the required |sample_rate()|. |reference_time| refers to the first
61   // sample.
62   void EncodeAndSend(const float* interleaved_samples,
63                      int num_samples,
64                      Clock::time_point reference_time);
65 
66   static constexpr int kDefaultCastAudioFramesPerSecond =
67       100;  // 10 ms frame duration.
68 
69  private:
encoder()70   OpusEncoder* encoder() const {
71     return reinterpret_cast<OpusEncoder*>(encoder_storage_.get());
72   }
73 
74   // Updates the |codec_delay_| based on the current encoder settings.
75   void UpdateCodecDelay();
76 
77   // Sets the next frame's reference time, accounting for codec buffering delay.
78   // Also, checks whether the reference time has drifted too far forwards, and
79   // skips if necessary.
80   void ResolveTimestampsAndMaybeSkip(Clock::time_point reference_time);
81 
82   // Fills the input buffer as much as possible from the given source data, and
83   // returns the number of samples copied into the buffer.
84   int FillInputBuffer(const float* interleaved_samples, int num_samples);
85 
86   const int num_channels_;
87   Sender* const sender_;
88   const int samples_per_cast_frame_;
89   const Clock::duration approximate_cast_frame_duration_;
90   const std::unique_ptr<uint8_t[]> encoder_storage_;
91   const std::unique_ptr<float[]> input_;     // Interleaved audio samples.
92   const std::unique_ptr<uint8_t[]> output_;  // Opus-encoded packet.
93 
94   // The audio delay introduced by the codec.
95   Clock::duration codec_delay_{};
96 
97   // The number of mono/stereo tuples currently queued in the |input_| buffer.
98   // Multiply by |num_channels_| to get the number of array elements.
99   int num_samples_queued_ = 0;
100 
101   // The reference time of the first frame passed to EncodeAndSend(), offset by
102   // the codec delay.
103   Clock::time_point start_time_ = Clock::time_point::min();
104 
105   // Initialized and used by EncodeAndSend() to hold the metadata and data
106   // pointer for each frame being sent.
107   EncodedFrame frame_;
108 
109   // The |reference_time| for the last sent frame. This is used to check that
110   // the reference times are monotonically increasing. If they have [illegally]
111   // gone backwards too much, warnings will be logged.
112   Clock::time_point last_sent_frame_reference_time_;
113 
114   // This is the recommended value, according to documentation in
115   // src/include/opus.h in libopus, so that the Opus encoder does not degrade
116   // the audio due to memory constraints.
117   static constexpr int kOpusMaxPayloadSize = 4000;
118 };
119 
120 }  // namespace cast
121 }  // namespace openscreen
122 
123 #endif  // CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
124