OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 #include "content/renderer/media/rtc_encoding_video_capturer.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "media/base/encoded_bitstream_buffer.h" | |
9 | |
10 namespace content { | |
11 | |
12 namespace { | |
13 | |
14 static const unsigned int kMaxBitrateKbps = 50 * 1000; | |
15 | |
16 } // namespace | |
17 | |
18 // Client of EncodedVideoSource. This object is created and owned by the | |
19 // RtcEncodingVideoCapturer. | |
20 class RtcEncodingVideoCapturer::EncodedVideoSourceClient : | |
21 public media::EncodedVideoSource::Client { | |
22 public: | |
23 EncodedVideoSourceClient( | |
24 media::EncodedVideoSource* encoded_video_source, | |
25 media::VideoEncodingParameters params, | |
26 webrtc::VideoCodecType rtc_codec_type); | |
27 virtual ~EncodedVideoSourceClient(); | |
28 | |
29 // media::EncodedVideoSource::Client implementation. | |
30 virtual void OnOpened( | |
31 const media::VideoEncodingParameters& params) OVERRIDE; | |
32 virtual void OnClosed() OVERRIDE; | |
33 virtual void OnBufferReady( | |
34 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) OVERRIDE; | |
35 virtual void OnConfigChanged( | |
36 const media::RuntimeVideoEncodingParameters& params) OVERRIDE; | |
37 | |
38 // Getters and setters for bitstream properties. | |
39 media::RuntimeVideoEncodingParameters runtime_params() const; | |
40 void set_round_trip_time(base::TimeDelta round_trip_time); | |
41 void set_callback(webrtc::EncodedImageCallback* callback); | |
42 | |
43 // Sets target bitrate and framerate. | |
44 void SetRates(uint32_t target_bitrate, uint32_t frame_rate); | |
45 | |
46 // Requests key frame. | |
47 void RequestKeyFrame(); | |
48 | |
49 private: | |
50 // Convert buffer to webrtc types and invoke encode complete callback. | |
51 void ReportEncodedFrame( | |
52 scoped_refptr<const media::EncodedBitstreamBuffer> buffer); | |
53 | |
54 media::VideoEncodingParameters params_; | |
55 webrtc::VideoCodecType rtc_codec_type_; | |
56 bool finished_; | |
57 | |
58 base::Time time_base_; | |
59 base::TimeDelta round_trip_time_; | |
60 media::EncodedVideoSource* encoded_video_source_; | |
61 webrtc::EncodedImageCallback* callback_; | |
62 | |
63 DISALLOW_COPY_AND_ASSIGN(EncodedVideoSourceClient); | |
64 }; | |
65 | |
66 RtcEncodingVideoCapturer::EncodedVideoSourceClient::EncodedVideoSourceClient( | |
67 media::EncodedVideoSource* encoded_video_source, | |
68 media::VideoEncodingParameters params, | |
69 webrtc::VideoCodecType rtc_codec_type) | |
70 : params_(params), | |
71 rtc_codec_type_(rtc_codec_type), | |
72 finished_(false), | |
73 encoded_video_source_(encoded_video_source), | |
74 callback_(NULL) { | |
75 DCHECK(encoded_video_source_); | |
76 encoded_video_source_->OpenBitstream(this, params); | |
77 } | |
78 | |
79 RtcEncodingVideoCapturer::EncodedVideoSourceClient:: | |
80 ~EncodedVideoSourceClient() { | |
81 if (!finished_) | |
82 encoded_video_source_->CloseBitstream(); | |
83 } | |
84 | |
85 media::RuntimeVideoEncodingParameters | |
86 RtcEncodingVideoCapturer::EncodedVideoSourceClient::runtime_params() const { | |
87 return params_.runtime_params; | |
88 } | |
89 | |
90 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_round_trip_time( | |
91 base::TimeDelta round_trip_time) { | |
92 round_trip_time_ = round_trip_time; | |
93 } | |
94 | |
95 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::set_callback( | |
96 webrtc::EncodedImageCallback* callback) { | |
97 DCHECK(!callback_); | |
98 callback_ = callback; | |
99 } | |
100 | |
101 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnOpened( | |
102 const media::VideoEncodingParameters& params) { | |
103 params_ = params; | |
104 } | |
105 | |
106 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnClosed() { | |
107 finished_ = true; | |
108 } | |
109 | |
110 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnBufferReady( | |
111 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { | |
112 DCHECK(!finished_ && buffer.get()); | |
113 | |
114 // First buffer constitutes the origin of the time for this bitstream context. | |
115 if (time_base_.is_null()) | |
116 time_base_ = buffer->metadata().timestamp; | |
117 | |
118 ReportEncodedFrame(buffer); | |
119 encoded_video_source_->ReturnBitstreamBuffer(buffer); | |
120 } | |
121 | |
122 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::OnConfigChanged( | |
123 const media::RuntimeVideoEncodingParameters& params) { | |
124 params_.runtime_params = params; | |
125 } | |
126 | |
127 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::SetRates( | |
128 uint32_t target_bitrate, uint32_t frame_rate) { | |
129 params_.runtime_params.target_bitrate = target_bitrate; | |
130 params_.runtime_params.frames_per_second = frame_rate; | |
131 encoded_video_source_->TrySetBitstreamConfig(params_.runtime_params); | |
132 } | |
133 | |
134 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::RequestKeyFrame() { | |
135 encoded_video_source_->RequestKeyFrame(); | |
136 } | |
137 | |
138 void RtcEncodingVideoCapturer::EncodedVideoSourceClient::ReportEncodedFrame( | |
139 scoped_refptr<const media::EncodedBitstreamBuffer> buffer) { | |
140 if (!callback_) | |
141 return; | |
142 | |
143 webrtc::EncodedImage image; | |
144 webrtc::CodecSpecificInfo codecInfo; | |
145 webrtc::RTPFragmentationHeader fragHeader; | |
146 | |
147 // TODO(hshi): remove this const_cast. Unfortunately webrtc::EncodedImage | |
148 // defines member |_buffer| of type uint8_t* even though webrtc never modifies | |
149 // the buffer contents. | |
150 image._buffer = const_cast<uint8_t*>(buffer->buffer()); | |
151 image._length = buffer->size(); | |
152 image._size = image._length; | |
153 | |
154 const media::BufferEncodingMetadata& metadata = buffer->metadata(); | |
155 base::TimeDelta capture_time = metadata.timestamp - time_base_; | |
156 image.capture_time_ms_ = capture_time.InMilliseconds(); | |
157 // Convert capture time to 90 kHz RTP timestamp. | |
158 image._timeStamp = (capture_time * 90000).InSeconds(); | |
159 if (metadata.key_frame) { | |
160 image._frameType = webrtc::kKeyFrame; | |
161 } else { | |
162 image._frameType = webrtc::kDeltaFrame; | |
163 } | |
164 image._completeFrame = true; | |
165 image._encodedWidth = params_.resolution.width(); | |
166 image._encodedHeight = params_.resolution.height(); | |
167 | |
168 // TODO(hshi): generate codec specific info for VP8. | |
169 codecInfo.codecType = rtc_codec_type_; | |
170 | |
171 // Generate header containing a single fragmentation. | |
172 fragHeader.VerifyAndAllocateFragmentationHeader(1); | |
173 fragHeader.fragmentationOffset[0] = 0; | |
174 fragHeader.fragmentationLength[0] = buffer->size(); | |
175 fragHeader.fragmentationPlType[0] = 0; | |
176 fragHeader.fragmentationTimeDiff[0] = 0; | |
177 | |
178 callback_->Encoded(image, &codecInfo, &fragHeader); | |
179 } | |
180 | |
181 // RtcEncodingVideoCapturer | |
182 RtcEncodingVideoCapturer::RtcEncodingVideoCapturer( | |
183 media::EncodedVideoSource* encoded_video_source, | |
184 webrtc::VideoCodecType codec_type) | |
185 : encoded_video_source_(encoded_video_source), | |
186 rtc_codec_type_(codec_type) { | |
187 } | |
188 | |
189 RtcEncodingVideoCapturer::~RtcEncodingVideoCapturer() { | |
190 } | |
191 | |
192 int32_t RtcEncodingVideoCapturer::InitEncode( | |
193 const webrtc::VideoCodec* codecSettings, | |
194 int32_t numberOfCores, | |
195 uint32_t maxPayloadSize) { | |
196 DCHECK(!encoded_video_source_client_); | |
197 if (codecSettings->codecType != rtc_codec_type_) | |
198 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
199 if (codecSettings->startBitrate > kMaxBitrateKbps || | |
200 codecSettings->maxBitrate > kMaxBitrateKbps) | |
201 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
202 | |
203 // Convert |codecSettings| to |params|. | |
204 media::VideoEncodingParameters params; | |
205 params.codec_name = codecSettings->plName; | |
206 params.resolution = gfx::Size(codecSettings->width, codecSettings->height); | |
207 params.runtime_params.target_bitrate = codecSettings->startBitrate * 1000; | |
208 params.runtime_params.max_bitrate = codecSettings->maxBitrate * 1000; | |
209 params.runtime_params.frames_per_second = codecSettings->maxFramerate; | |
210 encoded_video_source_client_.reset(new EncodedVideoSourceClient( | |
211 encoded_video_source_, params, rtc_codec_type_)); | |
212 return WEBRTC_VIDEO_CODEC_OK; | |
213 } | |
214 | |
215 int32_t RtcEncodingVideoCapturer::Encode( | |
216 const webrtc::I420VideoFrame& /* inputImage */, | |
217 const webrtc::CodecSpecificInfo* codecSpecificInfo, | |
218 const std::vector<webrtc::VideoFrameType>* frame_types) { | |
219 if (frame_types && !frame_types->empty()) { | |
220 webrtc::VideoFrameType type = frame_types->front(); | |
221 if (type == webrtc::kKeyFrame) | |
222 encoded_video_source_client_->RequestKeyFrame(); | |
223 } | |
224 return WEBRTC_VIDEO_CODEC_OK; | |
225 } | |
226 | |
227 int32_t RtcEncodingVideoCapturer::RegisterEncodeCompleteCallback( | |
228 webrtc::EncodedImageCallback* callback) { | |
229 DCHECK(encoded_video_source_client_); | |
230 encoded_video_source_client_->set_callback(callback); | |
231 return WEBRTC_VIDEO_CODEC_OK; | |
232 } | |
233 | |
234 int32_t RtcEncodingVideoCapturer::Release() { | |
235 DCHECK(encoded_video_source_client_); | |
236 encoded_video_source_client_.reset(NULL); | |
237 return WEBRTC_VIDEO_CODEC_OK; | |
238 } | |
239 | |
240 int32_t RtcEncodingVideoCapturer::SetChannelParameters( | |
241 uint32_t /* packetLoss */, | |
242 int rtt_in_ms) { | |
243 if (!encoded_video_source_client_) | |
244 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
245 encoded_video_source_client_->set_round_trip_time( | |
246 base::TimeDelta::FromMilliseconds(rtt_in_ms)); | |
247 return WEBRTC_VIDEO_CODEC_OK; | |
248 } | |
249 | |
250 int32_t RtcEncodingVideoCapturer::SetRates(uint32_t newBitRate, | |
251 uint32_t frameRate) { | |
252 if (!encoded_video_source_client_) | |
253 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | |
254 if (newBitRate > kMaxBitrateKbps) | |
255 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | |
256 encoded_video_source_client_->SetRates(newBitRate * 1000, frameRate); | |
257 return WEBRTC_VIDEO_CODEC_OK; | |
258 } | |
259 | |
260 } // namespace content | |
OLD | NEW |