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