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 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 220 |
221 SEncParamExt encoder_params = CreateEncoderParams(); | 221 SEncParamExt encoder_params = CreateEncoderParams(); |
222 // Initialize. | 222 // Initialize. |
223 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { | 223 if (openh264_encoder_->InitializeExt(&encoder_params) != 0) { |
224 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; | 224 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; |
225 Release(); | 225 Release(); |
226 ReportError(); | 226 ReportError(); |
227 return WEBRTC_VIDEO_CODEC_ERROR; | 227 return WEBRTC_VIDEO_CODEC_ERROR; |
228 } | 228 } |
229 // TODO(pbos): Base init params on these values before submitting. | 229 // TODO(pbos): Base init params on these values before submitting. |
230 quality_scaler_.Init(codec_settings->codecType, codec_settings->startBitrate, | |
231 codec_settings->width, codec_settings->height, | |
232 codec_settings->maxFramerate); | |
233 int video_format = EVideoFormatType::videoFormatI420; | 230 int video_format = EVideoFormatType::videoFormatI420; |
234 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, | 231 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, |
235 &video_format); | 232 &video_format); |
236 | 233 |
237 // Initialize encoded image. Default buffer size: size of unencoded data. | 234 // Initialize encoded image. Default buffer size: size of unencoded data. |
238 encoded_image_._size = | 235 encoded_image_._size = |
239 CalcBufferSize(kI420, codec_settings->width, codec_settings->height); | 236 CalcBufferSize(kI420, codec_settings->width, codec_settings->height); |
240 encoded_image_._buffer = new uint8_t[encoded_image_._size]; | 237 encoded_image_._buffer = new uint8_t[encoded_image_._size]; |
241 encoded_image_buffer_.reset(encoded_image_._buffer); | 238 encoded_image_buffer_.reset(encoded_image_._buffer); |
242 encoded_image_._completeFrame = true; | 239 encoded_image_._completeFrame = true; |
(...skipping 19 matching lines...) Expand all Loading... |
262 encoded_image_callback_ = callback; | 259 encoded_image_callback_ = callback; |
263 return WEBRTC_VIDEO_CODEC_OK; | 260 return WEBRTC_VIDEO_CODEC_OK; |
264 } | 261 } |
265 | 262 |
266 int32_t H264EncoderImpl::SetRates(uint32_t bitrate, uint32_t framerate) { | 263 int32_t H264EncoderImpl::SetRates(uint32_t bitrate, uint32_t framerate) { |
267 if (bitrate <= 0 || framerate <= 0) { | 264 if (bitrate <= 0 || framerate <= 0) { |
268 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 265 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
269 } | 266 } |
270 target_bps_ = bitrate * 1000; | 267 target_bps_ = bitrate * 1000; |
271 max_frame_rate_ = static_cast<float>(framerate); | 268 max_frame_rate_ = static_cast<float>(framerate); |
272 quality_scaler_.ReportFramerate(framerate); | |
273 | 269 |
274 SBitrateInfo target_bitrate; | 270 SBitrateInfo target_bitrate; |
275 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); | 271 memset(&target_bitrate, 0, sizeof(SBitrateInfo)); |
276 target_bitrate.iLayer = SPATIAL_LAYER_ALL, | 272 target_bitrate.iLayer = SPATIAL_LAYER_ALL, |
277 target_bitrate.iBitrate = target_bps_; | 273 target_bitrate.iBitrate = target_bps_; |
278 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, | 274 openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, |
279 &target_bitrate); | 275 &target_bitrate); |
280 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, &max_frame_rate_); | 276 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, &max_frame_rate_); |
281 return WEBRTC_VIDEO_CODEC_OK; | 277 return WEBRTC_VIDEO_CODEC_OK; |
282 } | 278 } |
283 | 279 |
284 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, | 280 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, |
285 const CodecSpecificInfo* codec_specific_info, | 281 const CodecSpecificInfo* codec_specific_info, |
286 const std::vector<FrameType>* frame_types) { | 282 const std::vector<FrameType>* frame_types) { |
287 if (!IsInitialized()) { | 283 if (!IsInitialized()) { |
288 ReportError(); | 284 ReportError(); |
289 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 285 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
290 } | 286 } |
291 if (input_frame.IsZeroSize()) { | 287 if (input_frame.IsZeroSize()) { |
292 ReportError(); | 288 ReportError(); |
293 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 289 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
294 } | 290 } |
295 if (!encoded_image_callback_) { | 291 if (!encoded_image_callback_) { |
296 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " | 292 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " |
297 << "has not been set with RegisterEncodeCompleteCallback()"; | 293 << "has not been set with RegisterEncodeCompleteCallback()"; |
298 ReportError(); | 294 ReportError(); |
299 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 295 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
300 } | 296 } |
301 | 297 |
302 quality_scaler_.OnEncodeFrame(input_frame.width(), input_frame.height()); | |
303 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = | |
304 quality_scaler_.GetScaledBuffer(input_frame.video_frame_buffer()); | |
305 if (frame_buffer->width() != width_ || frame_buffer->height() != height_) { | |
306 LOG(LS_INFO) << "Encoder reinitialized from " << width_ << "x" << height_ | |
307 << " to " << frame_buffer->width() << "x" | |
308 << frame_buffer->height(); | |
309 width_ = frame_buffer->width(); | |
310 height_ = frame_buffer->height(); | |
311 SEncParamExt encoder_params = CreateEncoderParams(); | |
312 openh264_encoder_->SetOption(ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, | |
313 &encoder_params); | |
314 } | |
315 | |
316 bool force_key_frame = false; | 298 bool force_key_frame = false; |
317 if (frame_types != nullptr) { | 299 if (frame_types != nullptr) { |
318 // We only support a single stream. | 300 // We only support a single stream. |
319 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1)); | 301 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1)); |
320 // Skip frame? | 302 // Skip frame? |
321 if ((*frame_types)[0] == kEmptyFrame) { | 303 if ((*frame_types)[0] == kEmptyFrame) { |
322 return WEBRTC_VIDEO_CODEC_OK; | 304 return WEBRTC_VIDEO_CODEC_OK; |
323 } | 305 } |
324 // Force key frame? | 306 // Force key frame? |
325 force_key_frame = (*frame_types)[0] == kVideoFrameKey; | 307 force_key_frame = (*frame_types)[0] == kVideoFrameKey; |
326 } | 308 } |
327 if (force_key_frame) { | 309 if (force_key_frame) { |
328 // API doc says ForceIntraFrame(false) does nothing, but calling this | 310 // API doc says ForceIntraFrame(false) does nothing, but calling this |
329 // function forces a key frame regardless of the |bIDR| argument's value. | 311 // function forces a key frame regardless of the |bIDR| argument's value. |
330 // (If every frame is a key frame we get lag/delays.) | 312 // (If every frame is a key frame we get lag/delays.) |
331 openh264_encoder_->ForceIntraFrame(true); | 313 openh264_encoder_->ForceIntraFrame(true); |
332 } | 314 } |
333 | 315 rtc::scoped_refptr<const VideoFrameBuffer> frame_buffer = |
| 316 input_frame.video_frame_buffer(); |
334 // EncodeFrame input. | 317 // EncodeFrame input. |
335 SSourcePicture picture; | 318 SSourcePicture picture; |
336 memset(&picture, 0, sizeof(SSourcePicture)); | 319 memset(&picture, 0, sizeof(SSourcePicture)); |
337 picture.iPicWidth = frame_buffer->width(); | 320 picture.iPicWidth = frame_buffer->width(); |
338 picture.iPicHeight = frame_buffer->height(); | 321 picture.iPicHeight = frame_buffer->height(); |
339 picture.iColorFormat = EVideoFormatType::videoFormatI420; | 322 picture.iColorFormat = EVideoFormatType::videoFormatI420; |
340 picture.uiTimeStamp = input_frame.ntp_time_ms(); | 323 picture.uiTimeStamp = input_frame.ntp_time_ms(); |
341 picture.iStride[0] = frame_buffer->StrideY(); | 324 picture.iStride[0] = frame_buffer->StrideY(); |
342 picture.iStride[1] = frame_buffer->StrideU(); | 325 picture.iStride[1] = frame_buffer->StrideU(); |
343 picture.iStride[2] = frame_buffer->StrideV(); | 326 picture.iStride[2] = frame_buffer->StrideV(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 if (encoded_image_._length > 0) { | 359 if (encoded_image_._length > 0) { |
377 // Deliver encoded image. | 360 // Deliver encoded image. |
378 CodecSpecificInfo codec_specific; | 361 CodecSpecificInfo codec_specific; |
379 codec_specific.codecType = kVideoCodecH264; | 362 codec_specific.codecType = kVideoCodecH264; |
380 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, | 363 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, |
381 &frag_header); | 364 &frag_header); |
382 | 365 |
383 // Parse and report QP. | 366 // Parse and report QP. |
384 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, | 367 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, |
385 encoded_image_._length); | 368 encoded_image_._length); |
386 int qp = -1; | 369 h264_bitstream_parser_.GetLastSliceQp(&encoded_image_.qp_); |
387 if (h264_bitstream_parser_.GetLastSliceQp(&qp)) | |
388 quality_scaler_.ReportQP(qp); | |
389 } else { | |
390 quality_scaler_.ReportDroppedFrame(); | |
391 } | 370 } |
392 return WEBRTC_VIDEO_CODEC_OK; | 371 return WEBRTC_VIDEO_CODEC_OK; |
393 } | 372 } |
394 | 373 |
395 const char* H264EncoderImpl::ImplementationName() const { | 374 const char* H264EncoderImpl::ImplementationName() const { |
396 return "OpenH264"; | 375 return "OpenH264"; |
397 } | 376 } |
398 | 377 |
399 bool H264EncoderImpl::IsInitialized() const { | 378 bool H264EncoderImpl::IsInitialized() const { |
400 return openh264_encoder_ != nullptr; | 379 return openh264_encoder_ != nullptr; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 | 460 |
482 int32_t H264EncoderImpl::SetChannelParameters( | 461 int32_t H264EncoderImpl::SetChannelParameters( |
483 uint32_t packet_loss, int64_t rtt) { | 462 uint32_t packet_loss, int64_t rtt) { |
484 return WEBRTC_VIDEO_CODEC_OK; | 463 return WEBRTC_VIDEO_CODEC_OK; |
485 } | 464 } |
486 | 465 |
487 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { | 466 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { |
488 return WEBRTC_VIDEO_CODEC_OK; | 467 return WEBRTC_VIDEO_CODEC_OK; |
489 } | 468 } |
490 | 469 |
491 void H264EncoderImpl::OnDroppedFrame() { | 470 QualityScaler::Settings H264EncoderImpl::GetQPThresholds() const { |
492 quality_scaler_.ReportDroppedFrame(); | 471 return QualityScaler::Settings(true); |
493 } | 472 } |
494 | 473 |
495 } // namespace webrtc | 474 } // namespace webrtc |
OLD | NEW |