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 |