xref: /aosp_15_r20/external/webrtc/video/video_stream_encoder.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef VIDEO_VIDEO_STREAM_ENCODER_H_
12*d9f75844SAndroid Build Coastguard Worker #define VIDEO_VIDEO_STREAM_ENCODER_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <atomic>
15*d9f75844SAndroid Build Coastguard Worker #include <map>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker #include <vector>
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker #include "absl/container/inlined_vector.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/adaptation/resource.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_sender_interface.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/task_queue/pending_task_safety_flag.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/units/data_rate.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/video/encoded_image.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_bitrate_allocator.h"
29*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_rotation.h"
30*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_sink_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_stream_encoder_settings.h"
32*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/video_codec.h"
33*d9f75844SAndroid Build Coastguard Worker #include "api/video_codecs/video_encoder.h"
34*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/adaptation_constraint.h"
35*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/resource_adaptation_processor.h"
36*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/resource_adaptation_processor_interface.h"
37*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/video_source_restrictions.h"
38*d9f75844SAndroid Build Coastguard Worker #include "call/adaptation/video_stream_input_state_provider.h"
39*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/utility/frame_dropper.h"
40*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/utility/qp_parser.h"
41*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/rate_control_settings.h"
42*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/exp_filter.h"
43*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/race_checker.h"
44*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/rate_statistics.h"
45*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/task_queue.h"
46*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h"
47*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h"
48*d9f75844SAndroid Build Coastguard Worker #include "video/adaptation/video_stream_encoder_resource_manager.h"
49*d9f75844SAndroid Build Coastguard Worker #include "video/encoder_bitrate_adjuster.h"
50*d9f75844SAndroid Build Coastguard Worker #include "video/frame_cadence_adapter.h"
51*d9f75844SAndroid Build Coastguard Worker #include "video/frame_encode_metadata_writer.h"
52*d9f75844SAndroid Build Coastguard Worker #include "video/video_source_sink_controller.h"
53*d9f75844SAndroid Build Coastguard Worker #include "video/video_stream_encoder_interface.h"
54*d9f75844SAndroid Build Coastguard Worker #include "video/video_stream_encoder_observer.h"
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
57*d9f75844SAndroid Build Coastguard Worker 
58*d9f75844SAndroid Build Coastguard Worker // VideoStreamEncoder represent a video encoder that accepts raw video frames as
59*d9f75844SAndroid Build Coastguard Worker // input and produces an encoded bit stream.
60*d9f75844SAndroid Build Coastguard Worker // Usage:
61*d9f75844SAndroid Build Coastguard Worker //  Instantiate.
62*d9f75844SAndroid Build Coastguard Worker //  Call SetSink.
63*d9f75844SAndroid Build Coastguard Worker //  Call SetSource.
64*d9f75844SAndroid Build Coastguard Worker //  Call ConfigureEncoder with the codec settings.
65*d9f75844SAndroid Build Coastguard Worker //  Call Stop() when done.
66*d9f75844SAndroid Build Coastguard Worker class VideoStreamEncoder : public VideoStreamEncoderInterface,
67*d9f75844SAndroid Build Coastguard Worker                            private EncodedImageCallback,
68*d9f75844SAndroid Build Coastguard Worker                            public VideoSourceRestrictionsListener {
69*d9f75844SAndroid Build Coastguard Worker  public:
70*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/12000): Reporting of VideoBitrateAllocation is being
71*d9f75844SAndroid Build Coastguard Worker   // deprecated. Instead VideoLayersAllocation should be reported.
72*d9f75844SAndroid Build Coastguard Worker   enum class BitrateAllocationCallbackType {
73*d9f75844SAndroid Build Coastguard Worker     kVideoBitrateAllocation,
74*d9f75844SAndroid Build Coastguard Worker     kVideoBitrateAllocationWhenScreenSharing,
75*d9f75844SAndroid Build Coastguard Worker     kVideoLayersAllocation
76*d9f75844SAndroid Build Coastguard Worker   };
77*d9f75844SAndroid Build Coastguard Worker   VideoStreamEncoder(
78*d9f75844SAndroid Build Coastguard Worker       Clock* clock,
79*d9f75844SAndroid Build Coastguard Worker       uint32_t number_of_cores,
80*d9f75844SAndroid Build Coastguard Worker       VideoStreamEncoderObserver* encoder_stats_observer,
81*d9f75844SAndroid Build Coastguard Worker       const VideoStreamEncoderSettings& settings,
82*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<OveruseFrameDetector> overuse_detector,
83*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter,
84*d9f75844SAndroid Build Coastguard Worker       std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
85*d9f75844SAndroid Build Coastguard Worker           encoder_queue,
86*d9f75844SAndroid Build Coastguard Worker       BitrateAllocationCallbackType allocation_cb_type,
87*d9f75844SAndroid Build Coastguard Worker       const FieldTrialsView& field_trials,
88*d9f75844SAndroid Build Coastguard Worker       webrtc::VideoEncoderFactory::EncoderSelectorInterface* encoder_selector =
89*d9f75844SAndroid Build Coastguard Worker           nullptr);
90*d9f75844SAndroid Build Coastguard Worker   ~VideoStreamEncoder() override;
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker   VideoStreamEncoder(const VideoStreamEncoder&) = delete;
93*d9f75844SAndroid Build Coastguard Worker   VideoStreamEncoder& operator=(const VideoStreamEncoder&) = delete;
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker   void AddAdaptationResource(rtc::scoped_refptr<Resource> resource) override;
96*d9f75844SAndroid Build Coastguard Worker   std::vector<rtc::scoped_refptr<Resource>> GetAdaptationResources() override;
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker   void SetSource(rtc::VideoSourceInterface<VideoFrame>* source,
99*d9f75844SAndroid Build Coastguard Worker                  const DegradationPreference& degradation_preference) override;
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker   void SetSink(EncoderSink* sink, bool rotation_applied) override;
102*d9f75844SAndroid Build Coastguard Worker 
103*d9f75844SAndroid Build Coastguard Worker   // TODO(perkj): Can we remove VideoCodec.startBitrate ?
104*d9f75844SAndroid Build Coastguard Worker   void SetStartBitrate(int start_bitrate_bps) override;
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker   void SetFecControllerOverride(
107*d9f75844SAndroid Build Coastguard Worker       FecControllerOverride* fec_controller_override) override;
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   void ConfigureEncoder(VideoEncoderConfig config,
110*d9f75844SAndroid Build Coastguard Worker                         size_t max_data_payload_length) override;
111*d9f75844SAndroid Build Coastguard Worker   void ConfigureEncoder(VideoEncoderConfig config,
112*d9f75844SAndroid Build Coastguard Worker                         size_t max_data_payload_length,
113*d9f75844SAndroid Build Coastguard Worker                         SetParametersCallback callback) override;
114*d9f75844SAndroid Build Coastguard Worker 
115*d9f75844SAndroid Build Coastguard Worker   // Permanently stop encoding. After this method has returned, it is
116*d9f75844SAndroid Build Coastguard Worker   // guaranteed that no encoded frames will be delivered to the sink.
117*d9f75844SAndroid Build Coastguard Worker   void Stop() override;
118*d9f75844SAndroid Build Coastguard Worker 
119*d9f75844SAndroid Build Coastguard Worker   void SendKeyFrame(const std::vector<VideoFrameType>& layers = {}) override;
120*d9f75844SAndroid Build Coastguard Worker 
121*d9f75844SAndroid Build Coastguard Worker   void OnLossNotification(
122*d9f75844SAndroid Build Coastguard Worker       const VideoEncoder::LossNotification& loss_notification) override;
123*d9f75844SAndroid Build Coastguard Worker 
124*d9f75844SAndroid Build Coastguard Worker   void OnBitrateUpdated(DataRate target_bitrate,
125*d9f75844SAndroid Build Coastguard Worker                         DataRate stable_target_bitrate,
126*d9f75844SAndroid Build Coastguard Worker                         DataRate target_headroom,
127*d9f75844SAndroid Build Coastguard Worker                         uint8_t fraction_lost,
128*d9f75844SAndroid Build Coastguard Worker                         int64_t round_trip_time_ms,
129*d9f75844SAndroid Build Coastguard Worker                         double cwnd_reduce_ratio) override;
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker   DataRate UpdateTargetBitrate(DataRate target_bitrate,
132*d9f75844SAndroid Build Coastguard Worker                                double cwnd_reduce_ratio);
133*d9f75844SAndroid Build Coastguard Worker 
134*d9f75844SAndroid Build Coastguard Worker  protected:
135*d9f75844SAndroid Build Coastguard Worker   // Used for testing. For example the `ScalingObserverInterface` methods must
136*d9f75844SAndroid Build Coastguard Worker   // be called on `encoder_queue_`.
encoder_queue()137*d9f75844SAndroid Build Coastguard Worker   TaskQueueBase* encoder_queue() { return encoder_queue_.Get(); }
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker   void OnVideoSourceRestrictionsUpdated(
140*d9f75844SAndroid Build Coastguard Worker       VideoSourceRestrictions restrictions,
141*d9f75844SAndroid Build Coastguard Worker       const VideoAdaptationCounters& adaptation_counters,
142*d9f75844SAndroid Build Coastguard Worker       rtc::scoped_refptr<Resource> reason,
143*d9f75844SAndroid Build Coastguard Worker       const VideoSourceRestrictions& unfiltered_restrictions) override;
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker   // Used for injected test resources.
146*d9f75844SAndroid Build Coastguard Worker   // TODO(eshr): Move all adaptation tests out of VideoStreamEncoder tests.
147*d9f75844SAndroid Build Coastguard Worker   void InjectAdaptationResource(rtc::scoped_refptr<Resource> resource,
148*d9f75844SAndroid Build Coastguard Worker                                 VideoAdaptationReason reason);
149*d9f75844SAndroid Build Coastguard Worker   void InjectAdaptationConstraint(AdaptationConstraint* adaptation_constraint);
150*d9f75844SAndroid Build Coastguard Worker 
151*d9f75844SAndroid Build Coastguard Worker   void AddRestrictionsListenerForTesting(
152*d9f75844SAndroid Build Coastguard Worker       VideoSourceRestrictionsListener* restrictions_listener);
153*d9f75844SAndroid Build Coastguard Worker   void RemoveRestrictionsListenerForTesting(
154*d9f75844SAndroid Build Coastguard Worker       VideoSourceRestrictionsListener* restrictions_listener);
155*d9f75844SAndroid Build Coastguard Worker 
156*d9f75844SAndroid Build Coastguard Worker  private:
157*d9f75844SAndroid Build Coastguard Worker   class CadenceCallback : public FrameCadenceAdapterInterface::Callback {
158*d9f75844SAndroid Build Coastguard Worker    public:
CadenceCallback(VideoStreamEncoder & video_stream_encoder)159*d9f75844SAndroid Build Coastguard Worker     explicit CadenceCallback(VideoStreamEncoder& video_stream_encoder)
160*d9f75844SAndroid Build Coastguard Worker         : video_stream_encoder_(video_stream_encoder) {}
161*d9f75844SAndroid Build Coastguard Worker     // FrameCadenceAdapterInterface::Callback overrides.
OnFrame(Timestamp post_time,int frames_scheduled_for_processing,const VideoFrame & frame)162*d9f75844SAndroid Build Coastguard Worker     void OnFrame(Timestamp post_time,
163*d9f75844SAndroid Build Coastguard Worker                  int frames_scheduled_for_processing,
164*d9f75844SAndroid Build Coastguard Worker                  const VideoFrame& frame) override {
165*d9f75844SAndroid Build Coastguard Worker       video_stream_encoder_.OnFrame(post_time, frames_scheduled_for_processing,
166*d9f75844SAndroid Build Coastguard Worker                                     frame);
167*d9f75844SAndroid Build Coastguard Worker     }
OnDiscardedFrame()168*d9f75844SAndroid Build Coastguard Worker     void OnDiscardedFrame() override {
169*d9f75844SAndroid Build Coastguard Worker       video_stream_encoder_.OnDiscardedFrame();
170*d9f75844SAndroid Build Coastguard Worker     }
RequestRefreshFrame()171*d9f75844SAndroid Build Coastguard Worker     void RequestRefreshFrame() override {
172*d9f75844SAndroid Build Coastguard Worker       video_stream_encoder_.RequestRefreshFrame();
173*d9f75844SAndroid Build Coastguard Worker     }
174*d9f75844SAndroid Build Coastguard Worker 
175*d9f75844SAndroid Build Coastguard Worker    private:
176*d9f75844SAndroid Build Coastguard Worker     VideoStreamEncoder& video_stream_encoder_;
177*d9f75844SAndroid Build Coastguard Worker   };
178*d9f75844SAndroid Build Coastguard Worker 
179*d9f75844SAndroid Build Coastguard Worker   class VideoFrameInfo {
180*d9f75844SAndroid Build Coastguard Worker    public:
VideoFrameInfo(int width,int height,bool is_texture)181*d9f75844SAndroid Build Coastguard Worker     VideoFrameInfo(int width, int height, bool is_texture)
182*d9f75844SAndroid Build Coastguard Worker         : width(width), height(height), is_texture(is_texture) {}
183*d9f75844SAndroid Build Coastguard Worker     int width;
184*d9f75844SAndroid Build Coastguard Worker     int height;
185*d9f75844SAndroid Build Coastguard Worker     bool is_texture;
pixel_count()186*d9f75844SAndroid Build Coastguard Worker     int pixel_count() const { return width * height; }
187*d9f75844SAndroid Build Coastguard Worker   };
188*d9f75844SAndroid Build Coastguard Worker 
189*d9f75844SAndroid Build Coastguard Worker   struct EncoderRateSettings {
190*d9f75844SAndroid Build Coastguard Worker     EncoderRateSettings();
191*d9f75844SAndroid Build Coastguard Worker     EncoderRateSettings(const VideoBitrateAllocation& bitrate,
192*d9f75844SAndroid Build Coastguard Worker                         double framerate_fps,
193*d9f75844SAndroid Build Coastguard Worker                         DataRate bandwidth_allocation,
194*d9f75844SAndroid Build Coastguard Worker                         DataRate encoder_target,
195*d9f75844SAndroid Build Coastguard Worker                         DataRate stable_encoder_target);
196*d9f75844SAndroid Build Coastguard Worker     bool operator==(const EncoderRateSettings& rhs) const;
197*d9f75844SAndroid Build Coastguard Worker     bool operator!=(const EncoderRateSettings& rhs) const;
198*d9f75844SAndroid Build Coastguard Worker 
199*d9f75844SAndroid Build Coastguard Worker     VideoEncoder::RateControlParameters rate_control;
200*d9f75844SAndroid Build Coastguard Worker     // This is the scalar target bitrate before the VideoBitrateAllocator, i.e.
201*d9f75844SAndroid Build Coastguard Worker     // the `target_bitrate` argument of the OnBitrateUpdated() method. This is
202*d9f75844SAndroid Build Coastguard Worker     // needed because the bitrate allocator may truncate the total bitrate and a
203*d9f75844SAndroid Build Coastguard Worker     // later call to the same allocator instance, e.g.
204*d9f75844SAndroid Build Coastguard Worker     // |using last_encoder_rate_setings_->bitrate.get_sum_bps()|, may trick it
205*d9f75844SAndroid Build Coastguard Worker     // into thinking the available bitrate has decreased since the last call.
206*d9f75844SAndroid Build Coastguard Worker     DataRate encoder_target;
207*d9f75844SAndroid Build Coastguard Worker     DataRate stable_encoder_target;
208*d9f75844SAndroid Build Coastguard Worker   };
209*d9f75844SAndroid Build Coastguard Worker 
210*d9f75844SAndroid Build Coastguard Worker   class DegradationPreferenceManager;
211*d9f75844SAndroid Build Coastguard Worker 
212*d9f75844SAndroid Build Coastguard Worker   void ReconfigureEncoder() RTC_RUN_ON(&encoder_queue_);
213*d9f75844SAndroid Build Coastguard Worker   void OnEncoderSettingsChanged() RTC_RUN_ON(&encoder_queue_);
214*d9f75844SAndroid Build Coastguard Worker   void OnFrame(Timestamp post_time,
215*d9f75844SAndroid Build Coastguard Worker                int frames_scheduled_for_processing,
216*d9f75844SAndroid Build Coastguard Worker                const VideoFrame& video_frame);
217*d9f75844SAndroid Build Coastguard Worker   void OnDiscardedFrame();
218*d9f75844SAndroid Build Coastguard Worker   void RequestRefreshFrame();
219*d9f75844SAndroid Build Coastguard Worker 
220*d9f75844SAndroid Build Coastguard Worker   void MaybeEncodeVideoFrame(const VideoFrame& frame,
221*d9f75844SAndroid Build Coastguard Worker                              int64_t time_when_posted_in_ms);
222*d9f75844SAndroid Build Coastguard Worker 
223*d9f75844SAndroid Build Coastguard Worker   void EncodeVideoFrame(const VideoFrame& frame,
224*d9f75844SAndroid Build Coastguard Worker                         int64_t time_when_posted_in_ms);
225*d9f75844SAndroid Build Coastguard Worker   // Indicates whether frame should be dropped because the pixel count is too
226*d9f75844SAndroid Build Coastguard Worker   // large for the current bitrate configuration.
227*d9f75844SAndroid Build Coastguard Worker   bool DropDueToSize(uint32_t pixel_count) const RTC_RUN_ON(&encoder_queue_);
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker   // Implements EncodedImageCallback.
230*d9f75844SAndroid Build Coastguard Worker   EncodedImageCallback::Result OnEncodedImage(
231*d9f75844SAndroid Build Coastguard Worker       const EncodedImage& encoded_image,
232*d9f75844SAndroid Build Coastguard Worker       const CodecSpecificInfo* codec_specific_info) override;
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker   void OnDroppedFrame(EncodedImageCallback::DropReason reason) override;
235*d9f75844SAndroid Build Coastguard Worker 
236*d9f75844SAndroid Build Coastguard Worker   bool EncoderPaused() const;
237*d9f75844SAndroid Build Coastguard Worker   void TraceFrameDropStart();
238*d9f75844SAndroid Build Coastguard Worker   void TraceFrameDropEnd();
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker   // Returns a copy of `rate_settings` with the `bitrate` field updated using
241*d9f75844SAndroid Build Coastguard Worker   // the current VideoBitrateAllocator.
242*d9f75844SAndroid Build Coastguard Worker   EncoderRateSettings UpdateBitrateAllocation(
243*d9f75844SAndroid Build Coastguard Worker       const EncoderRateSettings& rate_settings) RTC_RUN_ON(&encoder_queue_);
244*d9f75844SAndroid Build Coastguard Worker 
245*d9f75844SAndroid Build Coastguard Worker   uint32_t GetInputFramerateFps() RTC_RUN_ON(&encoder_queue_);
246*d9f75844SAndroid Build Coastguard Worker   void SetEncoderRates(const EncoderRateSettings& rate_settings)
247*d9f75844SAndroid Build Coastguard Worker       RTC_RUN_ON(&encoder_queue_);
248*d9f75844SAndroid Build Coastguard Worker 
249*d9f75844SAndroid Build Coastguard Worker   void RunPostEncode(const EncodedImage& encoded_image,
250*d9f75844SAndroid Build Coastguard Worker                      int64_t time_sent_us,
251*d9f75844SAndroid Build Coastguard Worker                      int temporal_index,
252*d9f75844SAndroid Build Coastguard Worker                      DataSize frame_size);
253*d9f75844SAndroid Build Coastguard Worker   void ReleaseEncoder() RTC_RUN_ON(&encoder_queue_);
254*d9f75844SAndroid Build Coastguard Worker   // After calling this function `resource_adaptation_processor_` will be null.
255*d9f75844SAndroid Build Coastguard Worker   void ShutdownResourceAdaptationQueue();
256*d9f75844SAndroid Build Coastguard Worker 
257*d9f75844SAndroid Build Coastguard Worker   void CheckForAnimatedContent(const VideoFrame& frame,
258*d9f75844SAndroid Build Coastguard Worker                                int64_t time_when_posted_in_ms)
259*d9f75844SAndroid Build Coastguard Worker       RTC_RUN_ON(&encoder_queue_);
260*d9f75844SAndroid Build Coastguard Worker 
261*d9f75844SAndroid Build Coastguard Worker   void RequestEncoderSwitch() RTC_RUN_ON(&encoder_queue_);
262*d9f75844SAndroid Build Coastguard Worker 
263*d9f75844SAndroid Build Coastguard Worker   // Augments an EncodedImage received from an encoder with parsable
264*d9f75844SAndroid Build Coastguard Worker   // information.
265*d9f75844SAndroid Build Coastguard Worker   EncodedImage AugmentEncodedImage(
266*d9f75844SAndroid Build Coastguard Worker       const EncodedImage& encoded_image,
267*d9f75844SAndroid Build Coastguard Worker       const CodecSpecificInfo* codec_specific_info);
268*d9f75844SAndroid Build Coastguard Worker 
269*d9f75844SAndroid Build Coastguard Worker   const FieldTrialsView& field_trials_;
270*d9f75844SAndroid Build Coastguard Worker   TaskQueueBase* const worker_queue_;
271*d9f75844SAndroid Build Coastguard Worker 
272*d9f75844SAndroid Build Coastguard Worker   const int number_of_cores_;
273*d9f75844SAndroid Build Coastguard Worker 
274*d9f75844SAndroid Build Coastguard Worker   EncoderSink* sink_;
275*d9f75844SAndroid Build Coastguard Worker   const VideoStreamEncoderSettings settings_;
276*d9f75844SAndroid Build Coastguard Worker   const BitrateAllocationCallbackType allocation_cb_type_;
277*d9f75844SAndroid Build Coastguard Worker   const RateControlSettings rate_control_settings_;
278*d9f75844SAndroid Build Coastguard Worker 
279*d9f75844SAndroid Build Coastguard Worker   webrtc::VideoEncoderFactory::EncoderSelectorInterface* const
280*d9f75844SAndroid Build Coastguard Worker       encoder_selector_from_constructor_;
281*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> const
282*d9f75844SAndroid Build Coastguard Worker       encoder_selector_from_factory_;
283*d9f75844SAndroid Build Coastguard Worker   // Pointing to either encoder_selector_from_constructor_ or
284*d9f75844SAndroid Build Coastguard Worker   // encoder_selector_from_factory_ but can be nullptr.
285*d9f75844SAndroid Build Coastguard Worker   VideoEncoderFactory::EncoderSelectorInterface* const encoder_selector_;
286*d9f75844SAndroid Build Coastguard Worker 
287*d9f75844SAndroid Build Coastguard Worker   VideoStreamEncoderObserver* const encoder_stats_observer_;
288*d9f75844SAndroid Build Coastguard Worker   // Adapter that avoids public inheritance of the cadence adapter's callback
289*d9f75844SAndroid Build Coastguard Worker   // interface.
290*d9f75844SAndroid Build Coastguard Worker   CadenceCallback cadence_callback_;
291*d9f75844SAndroid Build Coastguard Worker   // Frame cadence encoder adapter. Frames enter this adapter first, and it then
292*d9f75844SAndroid Build Coastguard Worker   // forwards them to our OnFrame method.
293*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter_
294*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_);
295*d9f75844SAndroid Build Coastguard Worker 
296*d9f75844SAndroid Build Coastguard Worker   VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
297*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
298*d9f75844SAndroid Build Coastguard Worker       RTC_PT_GUARDED_BY(&encoder_queue_);
299*d9f75844SAndroid Build Coastguard Worker   bool encoder_initialized_;
300*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<VideoBitrateAllocator> rate_allocator_
301*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_);
302*d9f75844SAndroid Build Coastguard Worker   int max_framerate_ RTC_GUARDED_BY(&encoder_queue_);
303*d9f75844SAndroid Build Coastguard Worker 
304*d9f75844SAndroid Build Coastguard Worker   // Set when ConfigureEncoder has been called in order to lazy reconfigure the
305*d9f75844SAndroid Build Coastguard Worker   // encoder on the next frame.
306*d9f75844SAndroid Build Coastguard Worker   bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(&encoder_queue_);
307*d9f75844SAndroid Build Coastguard Worker   // Set when configuration must create a new encoder object, e.g.,
308*d9f75844SAndroid Build Coastguard Worker   // because of a codec change.
309*d9f75844SAndroid Build Coastguard Worker   bool pending_encoder_creation_ RTC_GUARDED_BY(&encoder_queue_);
310*d9f75844SAndroid Build Coastguard Worker   absl::InlinedVector<SetParametersCallback, 2> encoder_configuration_callbacks_
311*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
312*d9f75844SAndroid Build Coastguard Worker 
313*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoFrameInfo> last_frame_info_
314*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
315*d9f75844SAndroid Build Coastguard Worker   int crop_width_ RTC_GUARDED_BY(&encoder_queue_);
316*d9f75844SAndroid Build Coastguard Worker   int crop_height_ RTC_GUARDED_BY(&encoder_queue_);
317*d9f75844SAndroid Build Coastguard Worker   absl::optional<uint32_t> encoder_target_bitrate_bps_
318*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
319*d9f75844SAndroid Build Coastguard Worker   size_t max_data_payload_length_ RTC_GUARDED_BY(&encoder_queue_);
320*d9f75844SAndroid Build Coastguard Worker   absl::optional<EncoderRateSettings> last_encoder_rate_settings_
321*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
322*d9f75844SAndroid Build Coastguard Worker   bool encoder_paused_and_dropped_frame_ RTC_GUARDED_BY(&encoder_queue_);
323*d9f75844SAndroid Build Coastguard Worker 
324*d9f75844SAndroid Build Coastguard Worker   // Set to true if at least one frame was sent to encoder since last encoder
325*d9f75844SAndroid Build Coastguard Worker   // initialization.
326*d9f75844SAndroid Build Coastguard Worker   bool was_encode_called_since_last_initialization_
327*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
328*d9f75844SAndroid Build Coastguard Worker 
329*d9f75844SAndroid Build Coastguard Worker   bool encoder_failed_ RTC_GUARDED_BY(&encoder_queue_);
330*d9f75844SAndroid Build Coastguard Worker   Clock* const clock_;
331*d9f75844SAndroid Build Coastguard Worker 
332*d9f75844SAndroid Build Coastguard Worker   // Used to make sure incoming time stamp is increasing for every frame.
333*d9f75844SAndroid Build Coastguard Worker   int64_t last_captured_timestamp_ RTC_GUARDED_BY(&encoder_queue_);
334*d9f75844SAndroid Build Coastguard Worker   // Delta used for translating between NTP and internal timestamps.
335*d9f75844SAndroid Build Coastguard Worker   const int64_t delta_ntp_internal_ms_ RTC_GUARDED_BY(&encoder_queue_);
336*d9f75844SAndroid Build Coastguard Worker 
337*d9f75844SAndroid Build Coastguard Worker   int64_t last_frame_log_ms_ RTC_GUARDED_BY(&encoder_queue_);
338*d9f75844SAndroid Build Coastguard Worker   int captured_frame_count_ RTC_GUARDED_BY(&encoder_queue_);
339*d9f75844SAndroid Build Coastguard Worker   int dropped_frame_cwnd_pushback_count_ RTC_GUARDED_BY(&encoder_queue_);
340*d9f75844SAndroid Build Coastguard Worker   int dropped_frame_encoder_block_count_ RTC_GUARDED_BY(&encoder_queue_);
341*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoFrame> pending_frame_ RTC_GUARDED_BY(&encoder_queue_);
342*d9f75844SAndroid Build Coastguard Worker   int64_t pending_frame_post_time_us_ RTC_GUARDED_BY(&encoder_queue_);
343*d9f75844SAndroid Build Coastguard Worker 
344*d9f75844SAndroid Build Coastguard Worker   VideoFrame::UpdateRect accumulated_update_rect_
345*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
346*d9f75844SAndroid Build Coastguard Worker   bool accumulated_update_rect_is_valid_ RTC_GUARDED_BY(&encoder_queue_);
347*d9f75844SAndroid Build Coastguard Worker 
348*d9f75844SAndroid Build Coastguard Worker   // Used for automatic content type detection.
349*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoFrame::UpdateRect> last_update_rect_
350*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
351*d9f75844SAndroid Build Coastguard Worker   Timestamp animation_start_time_ RTC_GUARDED_BY(&encoder_queue_);
352*d9f75844SAndroid Build Coastguard Worker   bool cap_resolution_due_to_video_content_ RTC_GUARDED_BY(&encoder_queue_);
353*d9f75844SAndroid Build Coastguard Worker   // Used to correctly ignore changes in update_rect introduced by
354*d9f75844SAndroid Build Coastguard Worker   // resize triggered by animation detection.
355*d9f75844SAndroid Build Coastguard Worker   enum class ExpectResizeState {
356*d9f75844SAndroid Build Coastguard Worker     kNoResize,              // Normal operation.
357*d9f75844SAndroid Build Coastguard Worker     kResize,                // Resize was triggered by the animation detection.
358*d9f75844SAndroid Build Coastguard Worker     kFirstFrameAfterResize  // Resize observed.
359*d9f75844SAndroid Build Coastguard Worker   } expect_resize_state_ RTC_GUARDED_BY(&encoder_queue_);
360*d9f75844SAndroid Build Coastguard Worker 
361*d9f75844SAndroid Build Coastguard Worker   FecControllerOverride* fec_controller_override_
362*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
363*d9f75844SAndroid Build Coastguard Worker   absl::optional<int64_t> last_parameters_update_ms_
364*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
365*d9f75844SAndroid Build Coastguard Worker   absl::optional<int64_t> last_encode_info_ms_ RTC_GUARDED_BY(&encoder_queue_);
366*d9f75844SAndroid Build Coastguard Worker 
367*d9f75844SAndroid Build Coastguard Worker   VideoEncoder::EncoderInfo encoder_info_ RTC_GUARDED_BY(&encoder_queue_);
368*d9f75844SAndroid Build Coastguard Worker   VideoCodec send_codec_ RTC_GUARDED_BY(&encoder_queue_);
369*d9f75844SAndroid Build Coastguard Worker 
370*d9f75844SAndroid Build Coastguard Worker   FrameDropper frame_dropper_ RTC_GUARDED_BY(&encoder_queue_);
371*d9f75844SAndroid Build Coastguard Worker   // If frame dropper is not force disabled, frame dropping might still be
372*d9f75844SAndroid Build Coastguard Worker   // disabled if VideoEncoder::GetEncoderInfo() indicates that the encoder has a
373*d9f75844SAndroid Build Coastguard Worker   // trusted rate controller. This is determined on a per-frame basis, as the
374*d9f75844SAndroid Build Coastguard Worker   // encoder behavior might dynamically change.
375*d9f75844SAndroid Build Coastguard Worker   bool force_disable_frame_dropper_ RTC_GUARDED_BY(&encoder_queue_);
376*d9f75844SAndroid Build Coastguard Worker   // Incremented on worker thread whenever `frame_dropper_` determines that a
377*d9f75844SAndroid Build Coastguard Worker   // frame should be dropped. Decremented on whichever thread runs
378*d9f75844SAndroid Build Coastguard Worker   // OnEncodedImage(), which is only called by one thread but not necessarily
379*d9f75844SAndroid Build Coastguard Worker   // the worker thread.
380*d9f75844SAndroid Build Coastguard Worker   std::atomic<int> pending_frame_drops_;
381*d9f75844SAndroid Build Coastguard Worker 
382*d9f75844SAndroid Build Coastguard Worker   // Congestion window frame drop ratio (drop 1 in every
383*d9f75844SAndroid Build Coastguard Worker   // cwnd_frame_drop_interval_ frames).
384*d9f75844SAndroid Build Coastguard Worker   absl::optional<int> cwnd_frame_drop_interval_ RTC_GUARDED_BY(&encoder_queue_);
385*d9f75844SAndroid Build Coastguard Worker   // Frame counter for congestion window frame drop.
386*d9f75844SAndroid Build Coastguard Worker   int cwnd_frame_counter_ RTC_GUARDED_BY(&encoder_queue_);
387*d9f75844SAndroid Build Coastguard Worker 
388*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<EncoderBitrateAdjuster> bitrate_adjuster_
389*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
390*d9f75844SAndroid Build Coastguard Worker 
391*d9f75844SAndroid Build Coastguard Worker   // TODO(sprang): Change actually support keyframe per simulcast stream, or
392*d9f75844SAndroid Build Coastguard Worker   // turn this into a simple bool `pending_keyframe_request_`.
393*d9f75844SAndroid Build Coastguard Worker   std::vector<VideoFrameType> next_frame_types_ RTC_GUARDED_BY(&encoder_queue_);
394*d9f75844SAndroid Build Coastguard Worker 
395*d9f75844SAndroid Build Coastguard Worker   FrameEncodeMetadataWriter frame_encode_metadata_writer_;
396*d9f75844SAndroid Build Coastguard Worker 
397*d9f75844SAndroid Build Coastguard Worker   // Experiment groups parsed from field trials for realtime video ([0]) and
398*d9f75844SAndroid Build Coastguard Worker   // screenshare ([1]). 0 means no group specified. Positive values are
399*d9f75844SAndroid Build Coastguard Worker   // experiment group numbers incremented by 1.
400*d9f75844SAndroid Build Coastguard Worker   const std::array<uint8_t, 2> experiment_groups_;
401*d9f75844SAndroid Build Coastguard Worker 
402*d9f75844SAndroid Build Coastguard Worker   struct AutomaticAnimationDetectionExperiment {
403*d9f75844SAndroid Build Coastguard Worker     bool enabled = false;
404*d9f75844SAndroid Build Coastguard Worker     int min_duration_ms = 2000;
405*d9f75844SAndroid Build Coastguard Worker     double min_area_ratio = 0.8;
406*d9f75844SAndroid Build Coastguard Worker     int min_fps = 10;
ParserAutomaticAnimationDetectionExperiment407*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<StructParametersParser> Parser() {
408*d9f75844SAndroid Build Coastguard Worker       return StructParametersParser::Create(
409*d9f75844SAndroid Build Coastguard Worker           "enabled", &enabled,                  //
410*d9f75844SAndroid Build Coastguard Worker           "min_duration_ms", &min_duration_ms,  //
411*d9f75844SAndroid Build Coastguard Worker           "min_area_ratio", &min_area_ratio,    //
412*d9f75844SAndroid Build Coastguard Worker           "min_fps", &min_fps);
413*d9f75844SAndroid Build Coastguard Worker     }
414*d9f75844SAndroid Build Coastguard Worker   };
415*d9f75844SAndroid Build Coastguard Worker 
416*d9f75844SAndroid Build Coastguard Worker   AutomaticAnimationDetectionExperiment
417*d9f75844SAndroid Build Coastguard Worker   ParseAutomatincAnimationDetectionFieldTrial() const;
418*d9f75844SAndroid Build Coastguard Worker 
419*d9f75844SAndroid Build Coastguard Worker   AutomaticAnimationDetectionExperiment
420*d9f75844SAndroid Build Coastguard Worker       automatic_animation_detection_experiment_ RTC_GUARDED_BY(&encoder_queue_);
421*d9f75844SAndroid Build Coastguard Worker 
422*d9f75844SAndroid Build Coastguard Worker   // Provides video stream input states: current resolution and frame rate.
423*d9f75844SAndroid Build Coastguard Worker   VideoStreamInputStateProvider input_state_provider_;
424*d9f75844SAndroid Build Coastguard Worker 
425*d9f75844SAndroid Build Coastguard Worker   const std::unique_ptr<VideoStreamAdapter> video_stream_adapter_
426*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
427*d9f75844SAndroid Build Coastguard Worker   // Responsible for adapting input resolution or frame rate to ensure resources
428*d9f75844SAndroid Build Coastguard Worker   // (e.g. CPU or bandwidth) are not overused. Adding resources can occur on any
429*d9f75844SAndroid Build Coastguard Worker   // thread.
430*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<ResourceAdaptationProcessorInterface>
431*d9f75844SAndroid Build Coastguard Worker       resource_adaptation_processor_ RTC_GUARDED_BY(&encoder_queue_);
432*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<DegradationPreferenceManager> degradation_preference_manager_
433*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
434*d9f75844SAndroid Build Coastguard Worker   std::vector<AdaptationConstraint*> adaptation_constraints_
435*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
436*d9f75844SAndroid Build Coastguard Worker   // Handles input, output and stats reporting related to VideoStreamEncoder
437*d9f75844SAndroid Build Coastguard Worker   // specific resources, such as "encode usage percent" measurements and "QP
438*d9f75844SAndroid Build Coastguard Worker   // scaling". Also involved with various mitigations such as initial frame
439*d9f75844SAndroid Build Coastguard Worker   // dropping.
440*d9f75844SAndroid Build Coastguard Worker   // The manager primarily operates on the `encoder_queue_` but its lifetime is
441*d9f75844SAndroid Build Coastguard Worker   // tied to the VideoStreamEncoder (which is destroyed off the encoder queue)
442*d9f75844SAndroid Build Coastguard Worker   // and its resource list is accessible from any thread.
443*d9f75844SAndroid Build Coastguard Worker   VideoStreamEncoderResourceManager stream_resource_manager_
444*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
445*d9f75844SAndroid Build Coastguard Worker   std::vector<rtc::scoped_refptr<Resource>> additional_resources_
446*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
447*d9f75844SAndroid Build Coastguard Worker   // Carries out the VideoSourceRestrictions provided by the
448*d9f75844SAndroid Build Coastguard Worker   // ResourceAdaptationProcessor, i.e. reconfigures the source of video frames
449*d9f75844SAndroid Build Coastguard Worker   // to provide us with different resolution or frame rate.
450*d9f75844SAndroid Build Coastguard Worker   // This class is thread-safe.
451*d9f75844SAndroid Build Coastguard Worker   VideoSourceSinkController video_source_sink_controller_
452*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(worker_queue_);
453*d9f75844SAndroid Build Coastguard Worker 
454*d9f75844SAndroid Build Coastguard Worker   // Default bitrate limits in EncoderInfoSettings allowed.
455*d9f75844SAndroid Build Coastguard Worker   const bool default_limits_allowed_;
456*d9f75844SAndroid Build Coastguard Worker 
457*d9f75844SAndroid Build Coastguard Worker   // QP parser is used to extract QP value from encoded frame when that is not
458*d9f75844SAndroid Build Coastguard Worker   // provided by encoder.
459*d9f75844SAndroid Build Coastguard Worker   QpParser qp_parser_;
460*d9f75844SAndroid Build Coastguard Worker   const bool qp_parsing_allowed_;
461*d9f75844SAndroid Build Coastguard Worker 
462*d9f75844SAndroid Build Coastguard Worker   // Enables encoder switching on initialization failures.
463*d9f75844SAndroid Build Coastguard Worker   bool switch_encoder_on_init_failures_;
464*d9f75844SAndroid Build Coastguard Worker 
465*d9f75844SAndroid Build Coastguard Worker   const absl::optional<int> vp9_low_tier_core_threshold_;
466*d9f75844SAndroid Build Coastguard Worker 
467*d9f75844SAndroid Build Coastguard Worker   // These are copies of restrictions (glorified max_pixel_count) set by
468*d9f75844SAndroid Build Coastguard Worker   // a) OnVideoSourceRestrictionsUpdated
469*d9f75844SAndroid Build Coastguard Worker   // b) CheckForAnimatedContent
470*d9f75844SAndroid Build Coastguard Worker   // They are used to scale down encoding resolution if needed when using
471*d9f75844SAndroid Build Coastguard Worker   // requested_resolution.
472*d9f75844SAndroid Build Coastguard Worker   //
473*d9f75844SAndroid Build Coastguard Worker   // TODO(webrtc:14451) Split video_source_sink_controller_
474*d9f75844SAndroid Build Coastguard Worker   // so that ownership on restrictions/wants is kept on &encoder_queue_, that
475*d9f75844SAndroid Build Coastguard Worker   // these extra copies would not be needed.
476*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoSourceRestrictions> latest_restrictions_
477*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
478*d9f75844SAndroid Build Coastguard Worker   absl::optional<VideoSourceRestrictions> animate_restrictions_
479*d9f75844SAndroid Build Coastguard Worker       RTC_GUARDED_BY(&encoder_queue_);
480*d9f75844SAndroid Build Coastguard Worker 
481*d9f75844SAndroid Build Coastguard Worker   // Used to cancel any potentially pending tasks to the worker thread.
482*d9f75844SAndroid Build Coastguard Worker   // Refrenced by tasks running on `encoder_queue_` so need to be destroyed
483*d9f75844SAndroid Build Coastguard Worker   // after stopping that queue. Must be created and destroyed on
484*d9f75844SAndroid Build Coastguard Worker   // `worker_queue_`.
485*d9f75844SAndroid Build Coastguard Worker   ScopedTaskSafety task_safety_;
486*d9f75844SAndroid Build Coastguard Worker 
487*d9f75844SAndroid Build Coastguard Worker   // Public methods are proxied to the task queues. The queues must be destroyed
488*d9f75844SAndroid Build Coastguard Worker   // first to make sure no tasks run that use other members.
489*d9f75844SAndroid Build Coastguard Worker   rtc::TaskQueue encoder_queue_;
490*d9f75844SAndroid Build Coastguard Worker };
491*d9f75844SAndroid Build Coastguard Worker 
492*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
493*d9f75844SAndroid Build Coastguard Worker 
494*d9f75844SAndroid Build Coastguard Worker #endif  // VIDEO_VIDEO_STREAM_ENCODER_H_
495