diff options
Diffstat (limited to 'cast/standalone_sender/streaming_vpx_encoder.h')
-rw-r--r-- | cast/standalone_sender/streaming_vpx_encoder.h | 160 |
1 files changed, 11 insertions, 149 deletions
diff --git a/cast/standalone_sender/streaming_vpx_encoder.h b/cast/standalone_sender/streaming_vpx_encoder.h index 6935efdd..5c99309e 100644 --- a/cast/standalone_sender/streaming_vpx_encoder.h +++ b/cast/standalone_sender/streaming_vpx_encoder.h @@ -18,6 +18,7 @@ #include <vector> #include "absl/base/thread_annotations.h" +#include "cast/standalone_sender/streaming_video_encoder.h" #include "cast/streaming/constants.h" #include "cast/streaming/frame_id.h" #include "cast/streaming/rtp_time.h" @@ -53,140 +54,19 @@ class Sender; // to further optimize the user experience. For example, the stats can be used // as a signal to reduce the data volume (i.e., resolution and/or frame rate) // coming from the video capture source. -class StreamingVpxEncoder { +class StreamingVpxEncoder : public StreamingVideoEncoder { public: - // Configurable parameters passed to the StreamingVpxEncoder constructor. - struct Parameters { - // Number of threads to parallelize frame encoding. This should be set based - // on the number of CPU cores available for encoding, but no more than 8. - int num_encode_threads = - std::min(std::max<int>(std::thread::hardware_concurrency(), 1), 8); - - // Best-quality quantizer (lower is better quality). Range: [0,63] - int min_quantizer = 4; - - // Worst-quality quantizer (lower is better quality). Range: [0,63] - int max_quantizer = 63; - - // Worst-quality quantizer to use when the CPU is extremely constrained. - // Range: [min_quantizer,max_quantizer] - int max_cpu_saver_quantizer = 25; - - // Maximum amount of wall-time a frame's encode can take, relative to the - // frame's duration, before the CPU-saver logic is activated. The default - // (70%) is appropriate for systems with four or more cores, but should be - // reduced (e.g., 50%) for systems with fewer than three cores. - // - // Example: For 30 FPS (continuous) video, the frame duration is ~33.3ms, - // and a value of 0.5 here would mean that the CPU-saver logic starts - // sacrificing quality when frame encodes start taking longer than ~16.7ms. - double max_time_utilization = 0.7; - - // Determines which codec (VP8 or VP9) is to be used for encoding. Defaults - // to VP8. - VideoCodec codec = VideoCodec::kVp8; - }; - - // Represents an input VideoFrame, passed to EncodeAndSend(). - struct VideoFrame { - // Image width and height. - int width; - int height; - - // I420 format image pointers and row strides (the number of bytes between - // the start of successive rows). The pointers only need to remain valid - // until the EncodeAndSend() call returns. - const uint8_t* yuv_planes[3]; - int yuv_strides[3]; - - // How long this frame will be held before the next frame will be displayed, - // or zero if unknown. The frame duration is passed to the VP8/9 codec, - // affecting a number of important behaviors, including: per-frame - // bandwidth, CPU time spent encoding, temporal quality trade-offs, and - // key/golden/alt-ref frame generation intervals. - Clock::duration duration; - }; - - // Performance statistics for a single frame's encode. - // - // For full details on how to use these stats in an end-to-end system, see: - // https://www.chromium.org/developers/design-documents/ - // auto-throttled-screen-capture-and-mirroring - // and https://source.chromium.org/chromium/chromium/src/+/master: - // media/cast/sender/performance_metrics_overlay.h - struct Stats { - // The Cast Streaming ID that was assigned to the frame. - FrameId frame_id; - - // The RTP timestamp of the frame. - RtpTimeTicks rtp_timestamp; - - // How long the frame took to encode. This is wall time, not CPU time or - // some other load metric. - Clock::duration encode_wall_time; - - // The frame's predicted duration; or, the actual duration if it was - // provided in the VideoFrame. - Clock::duration frame_duration; - - // The encoded frame's size in bytes. - int encoded_size; - - // The average size of an encoded frame in bytes, having this - // |frame_duration| and current target bitrate. - double target_size; - - // The actual quantizer the VP8 encoder used, in the range [0,63]. - int quantizer; - - // The "hindsight" quantizer value that would have produced the best quality - // encoding of the frame at the current target bitrate. The nominal range is - // [0.0,63.0]. If it is larger than 63.0, then it was impossible for VP8 to - // encode the frame within the current target bitrate (e.g., too much - // "entropy" in the image, or too low a target bitrate). - double perfect_quantizer; - - // Utilization feedback metrics. The nominal range for each of these is - // [0.0,1.0] where 1.0 means "the entire budget available for the frame was - // exhausted." Going above 1.0 is okay for one or a few frames, since it's - // the average over many frames that matters before the system is considered - // "redlining." - // - // The max of these three provides an overall utilization control signal. - // The usual approach is for upstream control logic to increase/decrease the - // data volume (e.g., video resolution and/or frame rate) to maintain a good - // target point. - double time_utilization() const { - return static_cast<double>(encode_wall_time.count()) / - frame_duration.count(); - } - double space_utilization() const { return encoded_size / target_size; } - double entropy_utilization() const { - return perfect_quantizer / kMaxQuantizer; - } - }; - StreamingVpxEncoder(const Parameters& params, TaskRunner* task_runner, Sender* sender); ~StreamingVpxEncoder(); - // Get/Set the target bitrate. This may be changed at any time, as frequently - // as desired, and it will take effect internally as soon as possible. - int GetTargetBitrate() const; - void SetTargetBitrate(int new_bitrate); - - // Encode |frame| using the VP8 encoder, assemble an EncodedFrame, and enqueue - // into the Sender. The frame may be dropped if too many frames are in-flight. - // If provided, the |stats_callback| is run after the frame is enqueued in the - // Sender (via the main TaskRunner). + int GetTargetBitrate() const override; + void SetTargetBitrate(int new_bitrate) override; void EncodeAndSend(const VideoFrame& frame, Clock::time_point reference_time, - std::function<void(Stats)> stats_callback); - - static constexpr int kMinQuantizer = 0; - static constexpr int kMaxQuantizer = 63; + std::function<void(Stats)> stats_callback) override; private: // Syntactic convenience to wrap the vpx_image_t alloc/free API in a smart @@ -209,7 +89,7 @@ class StreamingVpxEncoder { // Same as WorkUnit, but with additional fields to carry the encode results. struct WorkUnitWithResults : public WorkUnit { std::vector<uint8_t> payload; - bool is_key_frame; + bool is_key_frame = false; Stats stats; }; @@ -224,24 +104,20 @@ class StreamingVpxEncoder { void ProcessWorkUnitsUntilTimeToQuit(); // If the |encoder_| is live, attempt reconfiguration to allow it to encode - // frames at a new frame size, target bitrate, or "CPU encoding speed." If - // reconfiguration is not possible, destroy the existing instance and - // re-create a new |encoder_| instance. + // frames at a new frame size or target bitrate. If reconfiguration is not + // possible, destroy the existing instance and re-create a new |encoder_| + // instance. void PrepareEncoder(int width, int height, int target_bitrate); // Wraps the complex libvpx vpx_codec_encode() call using inputs from // |work_unit| and populating results there. - void EncodeFrame(bool force_key_frame, WorkUnitWithResults* work_unit); + void EncodeFrame(bool force_key_frame, WorkUnitWithResults& work_unit); // Computes and populates |work_unit.stats| after the last call to // EncodeFrame(). void ComputeFrameEncodeStats(Clock::duration encode_wall_time, int target_bitrate, - WorkUnitWithResults* work_unit); - - // Updates the |ideal_speed_setting_|, to take effect with the next frame - // encode, based on the given performance |stats|. - void UpdateSpeedSettingForNextFrame(const Stats& stats); + WorkUnitWithResults& work_unit); // Assembles and enqueues an EncodedFrame with the Sender on the main thread. void SendEncodedFrame(WorkUnitWithResults results); @@ -249,10 +125,6 @@ class StreamingVpxEncoder { // Allocates a vpx_image_t and copies the content from |frame| to it. static VpxImageUniquePtr CloneAsVpxImage(const VideoFrame& frame); - const Parameters params_; - TaskRunner* const main_task_runner_; - Sender* const sender_; - // The reference time of the first frame passed to EncodeAndSend(). Clock::time_point start_time_ = Clock::time_point::min(); @@ -287,18 +159,8 @@ class StreamingVpxEncoder { // below). vpx_codec_enc_cfg_t config_{}; - // These represent the magnitude of the VP8 speed setting, where larger values - // (i.e., faster speed) request less CPU usage but will provide lower video - // quality. Only the encode thread accesses these. - double ideal_speed_setting_; // A time-weighted average, from measurements. - int current_speed_setting_; // Current |encoder_| speed setting. - // libvpx VP8/9 encoder instance. Only the encode thread accesses this. vpx_codec_ctx_t encoder_; - - // This member should be last in the class since the thread should not start - // until all above members have been initialized by the constructor. - std::thread encode_thread_; }; } // namespace cast |