You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.6 KiB
124 lines
4.6 KiB
// Copyright 2020 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 CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
|
|
#define CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "cast/streaming/encoded_frame.h"
|
|
#include "cast/streaming/sender.h"
|
|
#include "platform/api/time.h"
|
|
|
|
extern "C" {
|
|
struct OpusEncoder;
|
|
}
|
|
|
|
namespace openscreen {
|
|
namespace cast {
|
|
|
|
// Wraps the libopus encoder so that the application can stream
|
|
// interleaved-floats audio samples to a Sender. Either mono or stereo sound is
|
|
// supported.
|
|
class StreamingOpusEncoder {
|
|
public:
|
|
// Constructs the encoder for mono or stereo sound, dividing the stream of
|
|
// audio samples up into chunks as determined by the given
|
|
// |cast_frames_per_second|, and for EncodedFrame output to the given
|
|
// |sender|. The sample rate of the audio is assumed to be the Sender's fixed
|
|
// |rtp_timebase()|.
|
|
StreamingOpusEncoder(int num_channels,
|
|
int cast_frames_per_second,
|
|
Sender* sender);
|
|
|
|
~StreamingOpusEncoder();
|
|
|
|
int num_channels() const { return num_channels_; }
|
|
int sample_rate() const { return sender_->rtp_timebase(); }
|
|
|
|
int GetBitrate() const;
|
|
|
|
// Sets the encoder back to its "AUTO" bitrate setting, for standard quality.
|
|
// This and UseHighQuality() may be called as often as needed as conditions
|
|
// change.
|
|
//
|
|
// Note: As of 2020-01-21, the encoder in "auto bitrate" mode would use a
|
|
// bitrate of 102kbps for 2-channel, 48 kHz audio and a 10 ms frame size.
|
|
void UseStandardQuality();
|
|
|
|
// Sets the encoder to use a high bitrate (virtually no artifacts), when
|
|
// plenty of network bandwidth is available. This and UseStandardQuality() may
|
|
// be called as often as needed as conditions change.
|
|
void UseHighQuality();
|
|
|
|
// Encode and send the given |interleaved_samples|, which contains
|
|
// |num_samples| tuples (i.e., multiply by the number of channels to determine
|
|
// the number of array elements). The audio is assumed to have been captured
|
|
// at the required |sample_rate()|. |reference_time| refers to the first
|
|
// sample.
|
|
void EncodeAndSend(const float* interleaved_samples,
|
|
int num_samples,
|
|
Clock::time_point reference_time);
|
|
|
|
static constexpr int kDefaultCastAudioFramesPerSecond =
|
|
100; // 10 ms frame duration.
|
|
|
|
private:
|
|
OpusEncoder* encoder() const {
|
|
return reinterpret_cast<OpusEncoder*>(encoder_storage_.get());
|
|
}
|
|
|
|
// Updates the |codec_delay_| based on the current encoder settings.
|
|
void UpdateCodecDelay();
|
|
|
|
// Sets the next frame's reference time, accounting for codec buffering delay.
|
|
// Also, checks whether the reference time has drifted too far forwards, and
|
|
// skips if necessary.
|
|
void ResolveTimestampsAndMaybeSkip(Clock::time_point reference_time);
|
|
|
|
// Fills the input buffer as much as possible from the given source data, and
|
|
// returns the number of samples copied into the buffer.
|
|
int FillInputBuffer(const float* interleaved_samples, int num_samples);
|
|
|
|
const int num_channels_;
|
|
Sender* const sender_;
|
|
const int samples_per_cast_frame_;
|
|
const Clock::duration approximate_cast_frame_duration_;
|
|
const std::unique_ptr<uint8_t[]> encoder_storage_;
|
|
const std::unique_ptr<float[]> input_; // Interleaved audio samples.
|
|
const std::unique_ptr<uint8_t[]> output_; // Opus-encoded packet.
|
|
|
|
// The audio delay introduced by the codec.
|
|
Clock::duration codec_delay_{};
|
|
|
|
// The number of mono/stereo tuples currently queued in the |input_| buffer.
|
|
// Multiply by |num_channels_| to get the number of array elements.
|
|
int num_samples_queued_ = 0;
|
|
|
|
// The reference time of the first frame passed to EncodeAndSend(), offset by
|
|
// the codec delay.
|
|
Clock::time_point start_time_ = Clock::time_point::min();
|
|
|
|
// Initialized and used by EncodeAndSend() to hold the metadata and data
|
|
// pointer for each frame being sent.
|
|
EncodedFrame frame_;
|
|
|
|
// The |reference_time| for the last sent frame. This is used to check that
|
|
// the reference times are monotonically increasing. If they have [illegally]
|
|
// gone backwards too much, warnings will be logged.
|
|
Clock::time_point last_sent_frame_reference_time_;
|
|
|
|
// This is the recommended value, according to documentation in
|
|
// src/include/opus.h in libopus, so that the Opus encoder does not degrade
|
|
// the audio due to memory constraints.
|
|
static constexpr int kOpusMaxPayloadSize = 4000;
|
|
};
|
|
|
|
} // namespace cast
|
|
} // namespace openscreen
|
|
|
|
#endif // CAST_STANDALONE_SENDER_STREAMING_OPUS_ENCODER_H_
|