| 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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 | 228 |
| 229 SEncParamExt encoder_params = CreateEncoderParams(); | 229 SEncParamExt encoder_params = CreateEncoderParams(); |
| 230 // Initialize. | 230 // Initialize. |
| 231 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { | 231 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { |
| 232 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; | 232 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; |
| 233 Release(); | 233 Release(); |
| 234 ReportError(); | 234 ReportError(); |
| 235 return WEBRTC_VIDEO_CODEC_ERROR; | 235 return WEBRTC_VIDEO_CODEC_ERROR; |
| 236 } | 236 } |
| 237 // TODO(pbos): Base init params on these values before submitting. | 237 // TODO(pbos): Base init params on these values before submitting. |
| 238 quality_scaler_.Init(codec_settings->codecType, codec_settings->startBitrate, | |
| 239 codec_settings->width, codec_settings->height, | |
| 240 codec_settings->maxFramerate); | |
| 241 int video_format = EVideoFormatType::videoFormatI420; | 238 int video_format = EVideoFormatType::videoFormatI420; |
| 242 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, | 239 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, |
| 243 &video_format); | 240 &video_format); |
| 244 | 241 |
| 245 // Initialize encoded image. Default buffer size: size of unencoded data. | 242 // Initialize encoded image. Default buffer size: size of unencoded data. |
| 246 encoded_image_._size = | 243 encoded_image_._size = |
| 247 CalcBufferSize(kI420, codec_settings->width, codec_settings->height); | 244 CalcBufferSize(kI420, codec_settings->width, codec_settings->height); |
| 248 encoded_image_._buffer = new uint8_t[encoded_image_._size]; | 245 encoded_image_._buffer = new uint8_t[encoded_image_._size]; |
| 249 encoded_image_buffer_.reset(encoded_image_._buffer); | 246 encoded_image_buffer_.reset(encoded_image_._buffer); |
| 250 encoded_image_._completeFrame = true; | 247 encoded_image_._completeFrame = true; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 272 } | 269 } |
| 273 | 270 |
| 274 int32_t H264EncoderImpl::SetRateAllocation( | 271 int32_t H264EncoderImpl::SetRateAllocation( |
| 275 const BitrateAllocation& bitrate_allocation, | 272 const BitrateAllocation& bitrate_allocation, |
| 276 uint32_t framerate) { | 273 uint32_t framerate) { |
| 277 if (bitrate_allocation.get_sum_bps() <= 0 || framerate <= 0) | 274 if (bitrate_allocation.get_sum_bps() <= 0 || framerate <= 0) |
| 278 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 275 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 279 | 276 |
| 280 target_bps_ = bitrate_allocation.get_sum_bps(); | 277 target_bps_ = bitrate_allocation.get_sum_bps(); |
| 281 max_frame_rate_ = static_cast<float>(framerate); | 278 max_frame_rate_ = static_cast<float>(framerate); |
| 282 quality_scaler_.ReportFramerate(framerate); | |
| 283 | 279 |
| 284 SBitrateInfo target_bitrate; | 280 SBitrateInfo target_bitrate; |
| 285 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); | 281 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); |
| 286 target_bitrate.iLayer = SPATIAL_LAYER_ALL, | 282 target_bitrate.iLayer = SPATIAL_LAYER_ALL, |
| 287 target_bitrate.iBitrate = target_bps_; | 283 target_bitrate.iBitrate = target_bps_; |
| 288 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, | 284 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, |
| 289 &target_bitrate); | 285 &target_bitrate); |
| 290 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, &max_frame_rate_); | 286 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, &max_frame_rate_); |
| 291 return WEBRTC_VIDEO_CODEC_OK; | 287 return WEBRTC_VIDEO_CODEC_OK; |
| 292 } | 288 } |
| 293 | 289 |
| 294 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, | 290 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, |
| 295 const CodecSpecificInfo* codec_specific_info, | 291 const CodecSpecificInfo* codec_specific_info, |
| 296 const std::vector<FrameType>* frame_types) { | 292 const std::vector<FrameType>* frame_types) { |
| 297 if (!IsInitialized()) { | 293 if (!IsInitialized()) { |
| 298 ReportError(); | 294 ReportError(); |
| 299 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 295 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 300 } | 296 } |
| 301 if (input_frame.IsZeroSize()) { | 297 if (input_frame.IsZeroSize()) { |
| 302 ReportError(); | 298 ReportError(); |
| 303 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 299 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
| 304 } | 300 } |
| 305 if (!encoded_image_callback_) { | 301 if (!encoded_image_callback_) { |
| 306 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " | 302 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " |
| 307 << "has not been set with RegisterEncodeCompleteCallback()"; | 303 << "has not been set with RegisterEncodeCompleteCallback()"; |
| 308 ReportError(); | 304 ReportError(); |
| 309 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 305 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
| 310 } | 306 } |
| 311 | 307 |
| 312 quality_scaler_.OnEncodeFrame(input_frame.width(), input_frame.height()); | |
| 313 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = | |
| 314 quality_scaler_.GetScaledBuffer(input_frame.video_frame_buffer()); | |
| 315 if (frame_buffer->width() != width_ || frame_buffer->height() != height_) { | |
| 316 LOG(LS_INFO) << "Encoder reinitialized from " << width_ << "x" << height_ | |
| 317 << " to " << frame_buffer->width() << "x" | |
| 318 << frame_buffer->height(); | |
| 319 width_ = frame_buffer->width(); | |
| 320 height_ = frame_buffer->height(); | |
| 321 SEncParamExt encoder_params = CreateEncoderParams(); | |
| 322 openh264_encoder_->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, | |
| 323 &encoder_params); | |
| 324 } | |
| 325 | |
| 326 bool force_key_frame = false; | 308 bool force_key_frame = false; |
| 327 if (frame_types != nullptr) { | 309 if (frame_types != nullptr) { |
| 328 // We only support a single stream. | 310 // We only support a single stream. |
| 329 RTC_DCHECK_EQ(frame_types->size(), 1); | 311 RTC_DCHECK_EQ(frame_types->size(), 1); |
| 330 // Skip frame? | 312 // Skip frame? |
| 331 if ((*frame_types)[0] == kEmptyFrame) { | 313 if ((*frame_types)[0] == kEmptyFrame) { |
| 332 return WEBRTC_VIDEO_CODEC_OK; | 314 return WEBRTC_VIDEO_CODEC_OK; |
| 333 } | 315 } |
| 334 // Force key frame? | 316 // Force key frame? |
| 335 force_key_frame = (*frame_types)[0] == kVideoFrameKey; | 317 force_key_frame = (*frame_types)[0] == kVideoFrameKey; |
| 336 } | 318 } |
| 337 if (force_key_frame) { | 319 if (force_key_frame) { |
| 338 // API doc says ForceIntraFrame(false) does nothing, but calling this | 320 // API doc says ForceIntraFrame(false) does nothing, but calling this |
| 339 // function forces a key frame regardless of the |bIDR| argument's value. | 321 // function forces a key frame regardless of the |bIDR| argument's value. |
| 340 // (If every frame is a key frame we get lag/delays.) | 322 // (If every frame is a key frame we get lag/delays.) |
| 341 openh264_encoder_->ForceIntraFrame(true); | 323 openh264_encoder_->ForceIntraFrame(true); |
| 342 } | 324 } |
| 343 | 325 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = |
| 326 input_frame.video_frame_buffer(); |
| 344 // EncodeFrame input. | 327 // EncodeFrame input. |
| 345 SSourcePicture picture; | 328 SSourcePicture picture; |
| 346 memset(&picture, 0, sizeof(SSourcePicture)); | 329 memset(&picture, 0, sizeof(SSourcePicture)); |
| 347 picture.iPicWidth = frame_buffer->width(); | 330 picture.iPicWidth = frame_buffer->width(); |
| 348 picture.iPicHeight = frame_buffer->height(); | 331 picture.iPicHeight = frame_buffer->height(); |
| 349 picture.iColorFormat = EVideoFormatType::videoFormatI420; | 332 picture.iColorFormat = EVideoFormatType::videoFormatI420; |
| 350 picture.uiTimeStamp = input_frame.ntp_time_ms(); | 333 picture.uiTimeStamp = input_frame.ntp_time_ms(); |
| 351 picture.iStride[0] = frame_buffer->StrideY(); | 334 picture.iStride[0] = frame_buffer->StrideY(); |
| 352 picture.iStride[1] = frame_buffer->StrideU(); | 335 picture.iStride[1] = frame_buffer->StrideU(); |
| 353 picture.iStride[2] = frame_buffer->StrideV(); | 336 picture.iStride[2] = frame_buffer->StrideV(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 377 encoded_image_._frameType = ConvertToVideoFrameType(info.eFrameType); | 360 encoded_image_._frameType = ConvertToVideoFrameType(info.eFrameType); |
| 378 | 361 |
| 379 // Split encoded image up into fragments. This also updates |encoded_image_|. | 362 // Split encoded image up into fragments. This also updates |encoded_image_|. |
| 380 RTPFragmentationHeader frag_header; | 363 RTPFragmentationHeader frag_header; |
| 381 RtpFragmentize(&encoded_image_, &encoded_image_buffer_, *frame_buffer, &info, | 364 RtpFragmentize(&encoded_image_, &encoded_image_buffer_, *frame_buffer, &info, |
| 382 &frag_header); | 365 &frag_header); |
| 383 | 366 |
| 384 // Encoder can skip frames to save bandwidth in which case | 367 // Encoder can skip frames to save bandwidth in which case |
| 385 // |encoded_image_._length| == 0. | 368 // |encoded_image_._length| == 0. |
| 386 if (encoded_image_._length > 0) { | 369 if (encoded_image_._length > 0) { |
| 387 // Parse and report QP. | |
| 388 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, | |
| 389 encoded_image_._length); | |
| 390 int qp = -1; | |
| 391 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) { | |
| 392 quality_scaler_.ReportQP(qp); | |
| 393 encoded_image_.qp_ = qp; | |
| 394 } | |
| 395 | |
| 396 // Deliver encoded image. | 370 // Deliver encoded image. |
| 397 CodecSpecificInfo codec_specific; | 371 CodecSpecificInfo codec_specific; |
| 398 codec_specific.codecType = kVideoCodecH264; | 372 codec_specific.codecType = kVideoCodecH264; |
| 399 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, | 373 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, |
| 400 &frag_header); | 374 &frag_header); |
| 401 } else { | 375 |
| 402 quality_scaler_.ReportDroppedFrame(); | 376 // Parse and report QP. |
| 377 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, |
| 378 encoded_image_._length); |
| 379 h264_bitstream_parser_.GetLastSliceQp(&encoded_image_.qp_); |
| 403 } | 380 } |
| 404 return WEBRTC_VIDEO_CODEC_OK; | 381 return WEBRTC_VIDEO_CODEC_OK; |
| 405 } | 382 } |
| 406 | 383 |
| 407 const char* H264EncoderImpl::ImplementationName() const { | 384 const char* H264EncoderImpl::ImplementationName() const { |
| 408 return "OpenH264"; | 385 return "OpenH264"; |
| 409 } | 386 } |
| 410 | 387 |
| 411 bool H264EncoderImpl::IsInitialized() const { | 388 bool H264EncoderImpl::IsInitialized() const { |
| 412 return openh264_encoder_ != nullptr; | 389 return openh264_encoder_ != nullptr; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 | 470 |
| 494 int32_t H264EncoderImpl::SetChannelParameters( | 471 int32_t H264EncoderImpl::SetChannelParameters( |
| 495 uint32_t packet_loss, int64_t rtt) { | 472 uint32_t packet_loss, int64_t rtt) { |
| 496 return WEBRTC_VIDEO_CODEC_OK; | 473 return WEBRTC_VIDEO_CODEC_OK; |
| 497 } | 474 } |
| 498 | 475 |
| 499 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { | 476 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { |
| 500 return WEBRTC_VIDEO_CODEC_OK; | 477 return WEBRTC_VIDEO_CODEC_OK; |
| 501 } | 478 } |
| 502 | 479 |
| 503 void H264EncoderImpl::OnDroppedFrame() { | 480 VideoEncoder::ScalingSettings H264EncoderImpl::GetScalingSettings() const { |
| 504 quality_scaler_.ReportDroppedFrame(); | 481 return VideoEncoder::ScalingSettings(true); |
| 505 } | 482 } |
| 506 | 483 |
| 507 } // namespace webrtc | 484 } // namespace webrtc |
| OLD | NEW |