OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 * | 9 * |
10 */ | 10 */ |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 } | 194 } |
195 RTC_DCHECK(openh264_encoder_); | 195 RTC_DCHECK(openh264_encoder_); |
196 if (kOpenH264EncoderDetailedLogging) { | 196 if (kOpenH264EncoderDetailedLogging) { |
197 int trace_level = WELS_LOG_DETAIL; | 197 int trace_level = WELS_LOG_DETAIL; |
198 openh264_encoder_->SetOption(ENCODER_OPTION_TRACE_LEVEL, | 198 openh264_encoder_->SetOption(ENCODER_OPTION_TRACE_LEVEL, |
199 &trace_level); | 199 &trace_level); |
200 } | 200 } |
201 // else WELS_LOG_DEFAULT is used by default. | 201 // else WELS_LOG_DEFAULT is used by default. |
202 | 202 |
203 number_of_cores_ = number_of_cores; | 203 number_of_cores_ = number_of_cores; |
204 codec_settings_ = *codec_settings; | 204 // Set internal settings from codec_settings |
205 if (codec_settings_.targetBitrate == 0) | 205 width_ = codec_settings->width; |
206 codec_settings_.targetBitrate = codec_settings_.startBitrate; | 206 height_ = codec_settings->height; |
| 207 max_frame_rate_ = static_cast<float>(codec_settings->maxFramerate); |
| 208 mode_ = codec_settings->mode; |
| 209 frame_dropping_on_ = codec_settings->H264().frameDroppingOn; |
| 210 key_frame_interval_ = codec_settings->H264().keyFrameInterval; |
| 211 |
| 212 // Codec_settings uses kbits/second; encoder uses bits/second. |
| 213 max_bps_ = codec_settings->maxBitrate * 1000; |
| 214 if (codec_settings->targetBitrate == 0) |
| 215 target_bps_ = codec_settings->startBitrate * 1000; |
| 216 else |
| 217 target_bps_ = codec_settings->targetBitrate * 1000; |
207 | 218 |
208 SEncParamExt encoder_params = CreateEncoderParams(); | 219 SEncParamExt encoder_params = CreateEncoderParams(); |
209 // Initialize. | 220 // Initialize. |
210 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { | 221 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { |
211 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; | 222 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; |
212 Release(); | 223 Release(); |
213 ReportError(); | 224 ReportError(); |
214 return WEBRTC_VIDEO_CODEC_ERROR; | 225 return WEBRTC_VIDEO_CODEC_ERROR; |
215 } | 226 } |
216 // TODO(pbos): Base init params on these values before submitting. | 227 // TODO(pbos): Base init params on these values before submitting. |
217 quality_scaler_.Init(codec_settings_.codecType, codec_settings_.startBitrate, | 228 quality_scaler_.Init(codec_settings->codecType, codec_settings->startBitrate, |
218 codec_settings_.width, codec_settings_.height, | 229 codec_settings->width, codec_settings->height, |
219 codec_settings_.maxFramerate); | 230 codec_settings->maxFramerate); |
220 int video_format = EVideoFormatType::videoFormatI420; | 231 int video_format = EVideoFormatType::videoFormatI420; |
221 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, | 232 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, |
222 &video_format); | 233 &video_format); |
223 | 234 |
224 // Initialize encoded image. Default buffer size: size of unencoded data. | 235 // Initialize encoded image. Default buffer size: size of unencoded data. |
225 encoded_image_._size = CalcBufferSize( | 236 encoded_image_._size = |
226 kI420, codec_settings_.width, codec_settings_.height); | 237 CalcBufferSize(kI420, codec_settings->width, codec_settings->height); |
227 encoded_image_._buffer = new uint8_t[encoded_image_._size]; | 238 encoded_image_._buffer = new uint8_t[encoded_image_._size]; |
228 encoded_image_buffer_.reset(encoded_image_._buffer); | 239 encoded_image_buffer_.reset(encoded_image_._buffer); |
229 encoded_image_._completeFrame = true; | 240 encoded_image_._completeFrame = true; |
230 encoded_image_._encodedWidth = 0; | 241 encoded_image_._encodedWidth = 0; |
231 encoded_image_._encodedHeight = 0; | 242 encoded_image_._encodedHeight = 0; |
232 encoded_image_._length = 0; | 243 encoded_image_._length = 0; |
233 return WEBRTC_VIDEO_CODEC_OK; | 244 return WEBRTC_VIDEO_CODEC_OK; |
234 } | 245 } |
235 | 246 |
236 int32_t H264EncoderImpl::Release() { | 247 int32_t H264EncoderImpl::Release() { |
(...skipping 10 matching lines...) Expand all Loading... |
247 int32_t H264EncoderImpl::RegisterEncodeCompleteCallback( | 258 int32_t H264EncoderImpl::RegisterEncodeCompleteCallback( |
248 EncodedImageCallback* callback) { | 259 EncodedImageCallback* callback) { |
249 encoded_image_callback_ = callback; | 260 encoded_image_callback_ = callback; |
250 return WEBRTC_VIDEO_CODEC_OK; | 261 return WEBRTC_VIDEO_CODEC_OK; |
251 } | 262 } |
252 | 263 |
253 int32_t H264EncoderImpl::SetRates(uint32_t bitrate, uint32_t framerate) { | 264 int32_t H264EncoderImpl::SetRates(uint32_t bitrate, uint32_t framerate) { |
254 if (bitrate <= 0 || framerate <= 0) { | 265 if (bitrate <= 0 || framerate <= 0) { |
255 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 266 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
256 } | 267 } |
257 codec_settings_.targetBitrate = bitrate; | 268 target_bps_ = bitrate * 1000; |
258 codec_settings_.maxFramerate = framerate; | 269 max_frame_rate_ = static_cast<float>(framerate); |
259 quality_scaler_.ReportFramerate(framerate); | 270 quality_scaler_.ReportFramerate(framerate); |
260 | 271 |
261 SBitrateInfo target_bitrate; | 272 SBitrateInfo target_bitrate; |
262 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); | 273 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); |
263 target_bitrate.iLayer = SPATIAL_LAYER_ALL, | 274 target_bitrate.iLayer = SPATIAL_LAYER_ALL, |
264 target_bitrate.iBitrate = codec_settings_.targetBitrate * 1000; | 275 target_bitrate.iBitrate = target_bps_; |
265 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, | 276 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, |
266 &target_bitrate); | 277 &target_bitrate); |
267 float max_framerate = static_cast<float>(codec_settings_.maxFramerate); | 278 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, &max_frame_rate_); |
268 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, | |
269 &max_framerate); | |
270 return WEBRTC_VIDEO_CODEC_OK; | 279 return WEBRTC_VIDEO_CODEC_OK; |
271 } | 280 } |
272 | 281 |
273 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, | 282 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, |
274 const CodecSpecificInfo* codec_specific_info, | 283 const CodecSpecificInfo* codec_specific_info, |
275 const std::vector<FrameType>* frame_types) { | 284 const std::vector<FrameType>* frame_types) { |
276 if (!IsInitialized()) { | 285 if (!IsInitialized()) { |
277 ReportError(); | 286 ReportError(); |
278 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 287 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
279 } | 288 } |
280 if (input_frame.IsZeroSize()) { | 289 if (input_frame.IsZeroSize()) { |
281 ReportError(); | 290 ReportError(); |
282 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 291 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
283 } | 292 } |
284 if (!encoded_image_callback_) { | 293 if (!encoded_image_callback_) { |
285 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " | 294 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " |
286 << "has not been set with RegisterEncodeCompleteCallback()"; | 295 << "has not been set with RegisterEncodeCompleteCallback()"; |
287 ReportError(); | 296 ReportError(); |
288 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 297 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
289 } | 298 } |
290 | 299 |
291 quality_scaler_.OnEncodeFrame(input_frame.width(), input_frame.height()); | 300 quality_scaler_.OnEncodeFrame(input_frame.width(), input_frame.height()); |
292 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = | 301 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = |
293 quality_scaler_.GetScaledBuffer(input_frame.video_frame_buffer()); | 302 quality_scaler_.GetScaledBuffer(input_frame.video_frame_buffer()); |
294 if (frame_buffer->width() != codec_settings_.width || | 303 if (frame_buffer->width() != width_ || frame_buffer->height() != height_) { |
295 frame_buffer->height() != codec_settings_.height) { | 304 LOG(LS_INFO) << "Encoder reinitialized from " << width_ << "x" << height_ |
296 LOG(LS_INFO) << "Encoder reinitialized from " << codec_settings_.width | 305 << " to " << frame_buffer->width() << "x" |
297 << "x" << codec_settings_.height << " to " | 306 << frame_buffer->height(); |
298 << frame_buffer->width() << "x" << frame_buffer->height(); | 307 width_ = frame_buffer->width(); |
299 codec_settings_.width = frame_buffer->width(); | 308 height_ = frame_buffer->height(); |
300 codec_settings_.height = frame_buffer->height(); | |
301 SEncParamExt encoder_params = CreateEncoderParams(); | 309 SEncParamExt encoder_params = CreateEncoderParams(); |
302 openh264_encoder_->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, | 310 openh264_encoder_->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, |
303 &encoder_params); | 311 &encoder_params); |
304 } | 312 } |
305 | 313 |
306 bool force_key_frame = false; | 314 bool force_key_frame = false; |
307 if (frame_types != nullptr) { | 315 if (frame_types != nullptr) { |
308 // We only support a single stream. | 316 // We only support a single stream. |
309 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1)); | 317 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1)); |
310 // Skip frame? | 318 // Skip frame? |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 | 400 |
393 // Initialization parameters. | 401 // Initialization parameters. |
394 // There are two ways to initialize. There is SEncParamBase (cleared with | 402 // There are two ways to initialize. There is SEncParamBase (cleared with |
395 // memset(&p, 0, sizeof(SEncParamBase)) used in Initialize, and SEncParamExt | 403 // memset(&p, 0, sizeof(SEncParamBase)) used in Initialize, and SEncParamExt |
396 // which is a superset of SEncParamBase (cleared with GetDefaultParams) used | 404 // which is a superset of SEncParamBase (cleared with GetDefaultParams) used |
397 // in InitializeExt. | 405 // in InitializeExt. |
398 SEncParamExt H264EncoderImpl::CreateEncoderParams() const { | 406 SEncParamExt H264EncoderImpl::CreateEncoderParams() const { |
399 RTC_DCHECK(openh264_encoder_); | 407 RTC_DCHECK(openh264_encoder_); |
400 SEncParamExt encoder_params; | 408 SEncParamExt encoder_params; |
401 openh264_encoder_->GetDefaultParams(&encoder_params); | 409 openh264_encoder_->GetDefaultParams(&encoder_params); |
402 if (codec_settings_.mode == kRealtimeVideo) { | 410 if (mode_ == kRealtimeVideo) { |
403 encoder_params.iUsageType = CAMERA_VIDEO_REAL_TIME; | 411 encoder_params.iUsageType = CAMERA_VIDEO_REAL_TIME; |
404 } else if (codec_settings_.mode == kScreensharing) { | 412 } else if (mode_ == kScreensharing) { |
405 encoder_params.iUsageType = SCREEN_CONTENT_REAL_TIME; | 413 encoder_params.iUsageType = SCREEN_CONTENT_REAL_TIME; |
406 } else { | 414 } else { |
407 RTC_NOTREACHED(); | 415 RTC_NOTREACHED(); |
408 } | 416 } |
409 encoder_params.iPicWidth = codec_settings_.width; | 417 encoder_params.iPicWidth = width_; |
410 encoder_params.iPicHeight = codec_settings_.height; | 418 encoder_params.iPicHeight = height_; |
411 // |encoder_params| uses bit/s, |codec_settings_| uses kbit/s. | 419 encoder_params.iTargetBitrate = target_bps_; |
412 encoder_params.iTargetBitrate = codec_settings_.targetBitrate * 1000; | 420 encoder_params.iMaxBitrate = max_bps_; |
413 encoder_params.iMaxBitrate = codec_settings_.maxBitrate * 1000; | |
414 // Rate Control mode | 421 // Rate Control mode |
415 encoder_params.iRCMode = RC_BITRATE_MODE; | 422 encoder_params.iRCMode = RC_BITRATE_MODE; |
416 encoder_params.fMaxFrameRate = | 423 encoder_params.fMaxFrameRate = max_frame_rate_; |
417 static_cast<float>(codec_settings_.maxFramerate); | |
418 | 424 |
419 // The following parameters are extension parameters (they're in SEncParamExt, | 425 // The following parameters are extension parameters (they're in SEncParamExt, |
420 // not in SEncParamBase). | 426 // not in SEncParamBase). |
421 encoder_params.bEnableFrameSkip = | 427 encoder_params.bEnableFrameSkip = frame_dropping_on_; |
422 codec_settings_.codecSpecific.H264.frameDroppingOn; | |
423 // |uiIntraPeriod| - multiple of GOP size | 428 // |uiIntraPeriod| - multiple of GOP size |
424 // |keyFrameInterval| - number of frames | 429 // |keyFrameInterval| - number of frames |
425 encoder_params.uiIntraPeriod = | 430 encoder_params.uiIntraPeriod = key_frame_interval_; |
426 codec_settings_.codecSpecific.H264.keyFrameInterval; | |
427 encoder_params.uiMaxNalSize = 0; | 431 encoder_params.uiMaxNalSize = 0; |
428 // Threading model: use auto. | 432 // Threading model: use auto. |
429 // 0: auto (dynamic imp. internal encoder) | 433 // 0: auto (dynamic imp. internal encoder) |
430 // 1: single thread (default value) | 434 // 1: single thread (default value) |
431 // >1: number of threads | 435 // >1: number of threads |
432 encoder_params.iMultipleThreadIdc = NumberOfThreads( | 436 encoder_params.iMultipleThreadIdc = NumberOfThreads( |
433 encoder_params.iPicWidth, encoder_params.iPicHeight, number_of_cores_); | 437 encoder_params.iPicWidth, encoder_params.iPicHeight, number_of_cores_); |
434 // The base spatial layer 0 is the only one we use. | 438 // The base spatial layer 0 is the only one we use. |
435 encoder_params.sSpatialLayers[0].iVideoWidth = encoder_params.iPicWidth; | 439 encoder_params.sSpatialLayers[0].iVideoWidth = encoder_params.iPicWidth; |
436 encoder_params.sSpatialLayers[0].iVideoHeight = encoder_params.iPicHeight; | 440 encoder_params.sSpatialLayers[0].iVideoHeight = encoder_params.iPicHeight; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 | 482 |
479 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { | 483 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { |
480 return WEBRTC_VIDEO_CODEC_OK; | 484 return WEBRTC_VIDEO_CODEC_OK; |
481 } | 485 } |
482 | 486 |
483 void H264EncoderImpl::OnDroppedFrame() { | 487 void H264EncoderImpl::OnDroppedFrame() { |
484 quality_scaler_.ReportDroppedFrame(); | 488 quality_scaler_.ReportDroppedFrame(); |
485 } | 489 } |
486 | 490 |
487 } // namespace webrtc | 491 } // namespace webrtc |
OLD | NEW |