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 */ |
11 | 11 |
12 #include "webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h" | 12 #include "webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.h" |
13 | 13 |
14 #include <limits> | 14 #include <limits> |
15 #include <string> | 15 #include <string> |
16 | 16 |
17 #include "third_party/openh264/src/codec/api/svc/codec_api.h" | 17 #include "third_party/openh264/src/codec/api/svc/codec_api.h" |
18 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h" | 18 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h" |
19 #include "third_party/openh264/src/codec/api/svc/codec_def.h" | 19 #include "third_party/openh264/src/codec/api/svc/codec_def.h" |
20 #include "third_party/openh264/src/codec/api/svc/codec_ver.h" | 20 #include "third_party/openh264/src/codec/api/svc/codec_ver.h" |
21 | 21 |
22 #include "webrtc/base/checks.h" | 22 #include "webrtc/base/checks.h" |
23 #include "webrtc/base/logging.h" | 23 #include "webrtc/base/logging.h" |
24 #include "webrtc/base/timeutils.h" | |
24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 25 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
25 #include "webrtc/media/base/mediaconstants.h" | |
26 #include "webrtc/system_wrappers/include/metrics.h" | 26 #include "webrtc/system_wrappers/include/metrics.h" |
27 | 27 |
28 namespace webrtc { | 28 namespace webrtc { |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 const bool kOpenH264EncoderDetailedLogging = false; | 32 const bool kOpenH264EncoderDetailedLogging = false; |
33 | 33 |
34 // Used by histograms. Values of entries should not be changed. | 34 // Used by histograms. Values of entries should not be changed. |
35 enum H264EncoderImplEvent { | 35 enum H264EncoderImplEvent { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 target_bps_(0), | 160 target_bps_(0), |
161 max_bps_(0), | 161 max_bps_(0), |
162 mode_(kRealtimeVideo), | 162 mode_(kRealtimeVideo), |
163 frame_dropping_on_(false), | 163 frame_dropping_on_(false), |
164 key_frame_interval_(0), | 164 key_frame_interval_(0), |
165 packetization_mode_(H264PacketizationMode::SingleNalUnit), | 165 packetization_mode_(H264PacketizationMode::SingleNalUnit), |
166 max_payload_size_(0), | 166 max_payload_size_(0), |
167 number_of_cores_(0), | 167 number_of_cores_(0), |
168 encoded_image_callback_(nullptr), | 168 encoded_image_callback_(nullptr), |
169 has_reported_init_(false), | 169 has_reported_init_(false), |
170 has_reported_error_(false) { | 170 has_reported_error_(false), |
171 last_timing_frame_time_ms_(0), | |
sprang_webrtc
2017/05/31 11:12:55
Probably a good idea to use -1 as uninitialized va
ilnik
2017/05/31 15:17:45
Done.
| |
172 timing_frames_delay_ms_(0), | |
173 min_frame_size_to_force_timing_frame_bytes_(0) { | |
171 RTC_CHECK(cricket::CodecNamesEq(codec.name, cricket::kH264CodecName)); | 174 RTC_CHECK(cricket::CodecNamesEq(codec.name, cricket::kH264CodecName)); |
172 std::string packetization_mode_string; | 175 std::string packetization_mode_string; |
173 if (codec.GetParam(cricket::kH264FmtpPacketizationMode, | 176 if (codec.GetParam(cricket::kH264FmtpPacketizationMode, |
174 &packetization_mode_string) && | 177 &packetization_mode_string) && |
175 packetization_mode_string == "1") { | 178 packetization_mode_string == "1") { |
176 packetization_mode_ = H264PacketizationMode::NonInterleaved; | 179 packetization_mode_ = H264PacketizationMode::NonInterleaved; |
177 } | 180 } |
178 } | 181 } |
179 | 182 |
180 H264EncoderImpl::~H264EncoderImpl() { | 183 H264EncoderImpl::~H264EncoderImpl() { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 | 227 |
225 number_of_cores_ = number_of_cores; | 228 number_of_cores_ = number_of_cores; |
226 // Set internal settings from codec_settings | 229 // Set internal settings from codec_settings |
227 width_ = codec_settings->width; | 230 width_ = codec_settings->width; |
228 height_ = codec_settings->height; | 231 height_ = codec_settings->height; |
229 max_frame_rate_ = static_cast<float>(codec_settings->maxFramerate); | 232 max_frame_rate_ = static_cast<float>(codec_settings->maxFramerate); |
230 mode_ = codec_settings->mode; | 233 mode_ = codec_settings->mode; |
231 frame_dropping_on_ = codec_settings->H264().frameDroppingOn; | 234 frame_dropping_on_ = codec_settings->H264().frameDroppingOn; |
232 key_frame_interval_ = codec_settings->H264().keyFrameInterval; | 235 key_frame_interval_ = codec_settings->H264().keyFrameInterval; |
233 max_payload_size_ = max_payload_size; | 236 max_payload_size_ = max_payload_size; |
237 min_frame_size_to_force_timing_frame_bytes_ = | |
238 codec_settings->minFrameSizeToForceTimingFrameBytes; | |
239 timing_frames_delay_ms_ = codec_settings->timingFramesDelayMs; | |
234 | 240 |
235 // Codec_settings uses kbits/second; encoder uses bits/second. | 241 // Codec_settings uses kbits/second; encoder uses bits/second. |
236 max_bps_ = codec_settings->maxBitrate * 1000; | 242 max_bps_ = codec_settings->maxBitrate * 1000; |
237 if (codec_settings->targetBitrate == 0) | 243 if (codec_settings->targetBitrate == 0) |
238 target_bps_ = codec_settings->startBitrate * 1000; | 244 target_bps_ = codec_settings->startBitrate * 1000; |
239 else | 245 else |
240 target_bps_ = codec_settings->targetBitrate * 1000; | 246 target_bps_ = codec_settings->targetBitrate * 1000; |
241 | 247 |
242 SEncParamExt encoder_params = CreateEncoderParams(); | 248 SEncParamExt encoder_params = CreateEncoderParams(); |
243 | 249 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
301 return WEBRTC_VIDEO_CODEC_OK; | 307 return WEBRTC_VIDEO_CODEC_OK; |
302 } | 308 } |
303 | 309 |
304 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, | 310 int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame, |
305 const CodecSpecificInfo* codec_specific_info, | 311 const CodecSpecificInfo* codec_specific_info, |
306 const std::vector<FrameType>* frame_types) { | 312 const std::vector<FrameType>* frame_types) { |
307 if (!IsInitialized()) { | 313 if (!IsInitialized()) { |
308 ReportError(); | 314 ReportError(); |
309 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 315 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
310 } | 316 } |
317 int64_t encode_start_ms = rtc::TimeMillis(); | |
311 if (!encoded_image_callback_) { | 318 if (!encoded_image_callback_) { |
312 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " | 319 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " |
313 << "has not been set with RegisterEncodeCompleteCallback()"; | 320 << "has not been set with RegisterEncodeCompleteCallback()"; |
314 ReportError(); | 321 ReportError(); |
315 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 322 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
316 } | 323 } |
317 | 324 |
318 bool force_key_frame = false; | 325 bool force_key_frame = false; |
319 if (frame_types != nullptr) { | 326 if (frame_types != nullptr) { |
320 // We only support a single stream. | 327 // We only support a single stream. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 &frag_header); | 385 &frag_header); |
379 | 386 |
380 // Encoder can skip frames to save bandwidth in which case | 387 // Encoder can skip frames to save bandwidth in which case |
381 // |encoded_image_._length| == 0. | 388 // |encoded_image_._length| == 0. |
382 if (encoded_image_._length > 0) { | 389 if (encoded_image_._length > 0) { |
383 // Parse QP. | 390 // Parse QP. |
384 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, | 391 h264_bitstream_parser_.ParseBitstream(encoded_image_._buffer, |
385 encoded_image_._length); | 392 encoded_image_._length); |
386 h264_bitstream_parser_.GetLastSliceQp(&encoded_image_.qp_); | 393 h264_bitstream_parser_.GetLastSliceQp(&encoded_image_.qp_); |
387 | 394 |
395 // Add timing information if needed. Timing delay is counted based on | |
396 // capture time to ensure that simulcast encoders will mark frames on all | |
397 // the streams together. | |
398 int64_t now_ms = rtc::TimeMillis(); | |
399 bool is_time_for_timing_frame = | |
400 encoded_image_.capture_time_ms_ - last_timing_frame_time_ms_ >= | |
401 timing_frames_delay_ms_; | |
402 if (is_time_for_timing_frame) { | |
403 last_timing_frame_time_ms_ = encoded_image_.capture_time_ms_; | |
404 } | |
405 if (is_time_for_timing_frame || | |
406 encoded_image_._length >= min_frame_size_to_force_timing_frame_bytes_) { | |
407 encoded_image_.timing_.is_timing_frame = true; | |
408 encoded_image_.timing_.encode_start_ms = encode_start_ms; | |
409 encoded_image_.timing_.encode_finish_ms = now_ms; | |
410 } else { | |
411 encoded_image_.timing_.is_timing_frame = false; | |
412 } | |
413 | |
sprang_webrtc
2017/05/31 11:12:55
I'm not sure you need to do this on a per codec le
ilnik
2017/05/31 15:17:45
Firstly, it will be very troublesome to update VCM
sprang_webrtc
2017/06/05 14:39:20
You can always start by having a simple method dec
ilnik
2017/06/07 14:25:03
Done.
| |
388 // Deliver encoded image. | 414 // Deliver encoded image. |
389 CodecSpecificInfo codec_specific; | 415 CodecSpecificInfo codec_specific; |
390 codec_specific.codecType = kVideoCodecH264; | 416 codec_specific.codecType = kVideoCodecH264; |
391 codec_specific.codecSpecific.H264.packetization_mode = packetization_mode_; | 417 codec_specific.codecSpecific.H264.packetization_mode = packetization_mode_; |
392 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, | 418 encoded_image_callback_->OnEncodedImage(encoded_image_, &codec_specific, |
393 &frag_header); | 419 &frag_header); |
394 } | 420 } |
395 return WEBRTC_VIDEO_CODEC_OK; | 421 return WEBRTC_VIDEO_CODEC_OK; |
396 } | 422 } |
397 | 423 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 | 523 |
498 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { | 524 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { |
499 return WEBRTC_VIDEO_CODEC_OK; | 525 return WEBRTC_VIDEO_CODEC_OK; |
500 } | 526 } |
501 | 527 |
502 VideoEncoder::ScalingSettings H264EncoderImpl::GetScalingSettings() const { | 528 VideoEncoder::ScalingSettings H264EncoderImpl::GetScalingSettings() const { |
503 return VideoEncoder::ScalingSettings(true); | 529 return VideoEncoder::ScalingSettings(true); |
504 } | 530 } |
505 | 531 |
506 } // namespace webrtc | 532 } // namespace webrtc |
OLD | NEW |