1 // Copyright 2014 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.
5 #ifndef MEDIA_CAST_SENDER_EXTERNAL_VIDEO_ENCODER_H_
6 #define MEDIA_CAST_SENDER_EXTERNAL_VIDEO_ENCODER_H_
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/weak_ptr.h"
10 #include "media/cast/cast_config.h"
11 #include "media/cast/cast_environment.h"
12 #include "media/cast/sender/size_adaptable_video_encoder_base.h"
13 #include "media/cast/sender/video_encoder.h"
14 #include "media/video/video_encode_accelerator.h"
15 #include "ui/gfx/geometry/size.h"
20 // Cast MAIN thread proxy to the internal media::VideoEncodeAccelerator
21 // implementation running on a separate thread. Encodes media::VideoFrames and
22 // emits media::cast::EncodedFrames.
23 class ExternalVideoEncoder
: public VideoEncoder
{
25 // Returns true if the current platform and system configuration supports
26 // using ExternalVideoEncoder with the given |video_config|.
27 static bool IsSupported(const VideoSenderConfig
& video_config
);
30 const scoped_refptr
<CastEnvironment
>& cast_environment
,
31 const VideoSenderConfig
& video_config
,
32 const gfx::Size
& frame_size
,
33 uint32 first_frame_id
,
34 const StatusChangeCallback
& status_change_cb
,
35 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
36 const CreateVideoEncodeMemoryCallback
& create_video_encode_memory_cb
);
38 ~ExternalVideoEncoder() final
;
40 // VideoEncoder implementation.
41 bool EncodeVideoFrame(
42 const scoped_refptr
<media::VideoFrame
>& video_frame
,
43 const base::TimeTicks
& reference_time
,
44 const FrameEncodedCallback
& frame_encoded_callback
) final
;
45 void SetBitRate(int new_bit_rate
) final
;
46 void GenerateKeyFrame() final
;
47 void LatestFrameIdToReference(uint32 frame_id
) final
;
52 // Method invoked by the CreateVideoEncodeAcceleratorCallback to construct a
53 // VEAClientImpl to own and interface with a new |vea|. Upon return,
54 // |client_| holds a reference to the new VEAClientImpl.
55 void OnCreateVideoEncodeAccelerator(
56 const VideoSenderConfig
& video_config
,
57 uint32 first_frame_id
,
58 const StatusChangeCallback
& status_change_cb
,
59 scoped_refptr
<base::SingleThreadTaskRunner
> encoder_task_runner
,
60 scoped_ptr
<media::VideoEncodeAccelerator
> vea
);
62 const scoped_refptr
<CastEnvironment
> cast_environment_
;
63 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_
;
65 // The size of the visible region of the video frames to be encoded.
66 const gfx::Size frame_size_
;
69 bool key_frame_requested_
;
71 scoped_refptr
<VEAClientImpl
> client_
;
73 // Provides a weak pointer for the OnCreateVideoEncoderAccelerator() callback.
74 // NOTE: Weak pointers must be invalidated before all other member variables.
75 base::WeakPtrFactory
<ExternalVideoEncoder
> weak_factory_
;
77 DISALLOW_COPY_AND_ASSIGN(ExternalVideoEncoder
);
80 // An implementation of SizeAdaptableVideoEncoderBase to proxy for
81 // ExternalVideoEncoder instances.
82 class SizeAdaptableExternalVideoEncoder
: public SizeAdaptableVideoEncoderBase
{
84 SizeAdaptableExternalVideoEncoder(
85 const scoped_refptr
<CastEnvironment
>& cast_environment
,
86 const VideoSenderConfig
& video_config
,
87 const StatusChangeCallback
& status_change_cb
,
88 const CreateVideoEncodeAcceleratorCallback
& create_vea_cb
,
89 const CreateVideoEncodeMemoryCallback
& create_video_encode_memory_cb
);
91 ~SizeAdaptableExternalVideoEncoder() final
;
94 scoped_ptr
<VideoEncoder
> CreateEncoder() final
;
97 // Special callbacks needed by media::cast::ExternalVideoEncoder.
98 // TODO(miu): Remove these. http://crbug.com/454029
99 const CreateVideoEncodeAcceleratorCallback create_vea_cb_
;
100 const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_
;
102 DISALLOW_COPY_AND_ASSIGN(SizeAdaptableExternalVideoEncoder
);
105 // A utility class for examining the sequence of frames sent to an external
106 // encoder, and returning an estimate of the what the software VP8 encoder would
107 // have used for a quantizer value when encoding each frame. The quantizer
108 // value is related to the complexity of the content of the frame.
109 class QuantizerEstimator
{
113 MIN_VP8_QUANTIZER
= 4,
114 MAX_VP8_QUANTIZER
= 63,
117 QuantizerEstimator();
118 ~QuantizerEstimator();
120 // Discard any state related to the processing of prior frames.
123 // Examine |frame| and estimate and return the quantizer value the software
124 // VP8 encoder would have used when encoding the frame, in the range
125 // [4.0,63.0]. If |frame| is not in planar YUV format, or its size is empty,
126 // this returns |NO_RESULT|.
127 double EstimateForKeyFrame(const VideoFrame
& frame
);
128 double EstimateForDeltaFrame(const VideoFrame
& frame
);
132 // The percentage of each frame to sample. This value is based on an
133 // analysis that showed sampling 10% of the rows of a frame generated
134 // reasonably accurate results.
135 FRAME_SAMPLING_PERCENT
= 10,
138 // Returns true if the frame is in planar YUV format.
139 static bool CanExamineFrame(const VideoFrame
& frame
);
141 // Returns a value in the range [0,log2(num_buckets)], the Shannon Entropy
142 // based on the probabilities of values falling within each of the buckets of
143 // the given |histogram|.
144 static double ComputeEntropyFromHistogram(const int* histogram
,
148 // Map the |shannon_entropy| to its corresponding software VP8 quantizer.
149 static double ToQuantizerEstimate(double shannon_entropy
);
151 // A cache of a subset of rows of pixels from the last frame examined. This
152 // is used to compute the entropy of the difference between frames, which in
153 // turn is used to compute the entropy and quantizer.
154 scoped_ptr
<uint8
[]> last_frame_pixel_buffer_
;
155 gfx::Size last_frame_size_
;
157 DISALLOW_COPY_AND_ASSIGN(QuantizerEstimator
);
163 #endif // MEDIA_CAST_SENDER_EXTERNAL_VIDEO_ENCODER_H_