Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Side by Side Diff: webrtc/modules/video_coding/codecs/h264/h264_encoder_impl.cc

Issue 1716173002: Histograms for H264EncoderImpl/H264DecoderImpl initialization and errors (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Renamed "...State" enums to "...Event" Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 15
16 #include "third_party/openh264/src/codec/api/svc/codec_api.h" 16 #include "third_party/openh264/src/codec/api/svc/codec_api.h"
17 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h" 17 #include "third_party/openh264/src/codec/api/svc/codec_app_def.h"
18 #include "third_party/openh264/src/codec/api/svc/codec_def.h" 18 #include "third_party/openh264/src/codec/api/svc/codec_def.h"
19 19
20 #include "webrtc/base/checks.h" 20 #include "webrtc/base/checks.h"
21 #include "webrtc/base/logging.h" 21 #include "webrtc/base/logging.h"
22 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 22 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
23 #include "webrtc/system_wrappers/include/metrics.h"
23 24
24 namespace webrtc { 25 namespace webrtc {
25 26
26 namespace { 27 namespace {
27 28
28 const bool kOpenH264EncoderDetailedLogging = false; 29 const bool kOpenH264EncoderDetailedLogging = false;
29 30
31 // Used by histograms. Values of entries should not be changed.
32 enum H264EncoderImplEvent {
33 kH264EncoderEventInit = 0,
34 kH264EncoderEventError = 1,
35 kH264EncoderEventMax = 16,
36 };
37
30 int NumberOfThreads(int width, int height, int number_of_cores) { 38 int NumberOfThreads(int width, int height, int number_of_cores) {
31 // TODO(hbos): In Chromium, multiple threads do not work with sandbox on Mac, 39 // TODO(hbos): In Chromium, multiple threads do not work with sandbox on Mac,
32 // see crbug.com/583348. Until further investigated, only use one thread. 40 // see crbug.com/583348. Until further investigated, only use one thread.
33 // if (width * height >= 1920 * 1080 && number_of_cores > 8) { 41 // if (width * height >= 1920 * 1080 && number_of_cores > 8) {
34 // return 8; // 8 threads for 1080p on high perf machines. 42 // return 8; // 8 threads for 1080p on high perf machines.
35 // } else if (width * height > 1280 * 960 && number_of_cores >= 6) { 43 // } else if (width * height > 1280 * 960 && number_of_cores >= 6) {
36 // return 3; // 3 threads for 1080p. 44 // return 3; // 3 threads for 1080p.
37 // } else if (width * height > 640 * 480 && number_of_cores >= 3) { 45 // } else if (width * height > 640 * 480 && number_of_cores >= 3) {
38 // return 2; // 2 threads for qHD/HD. 46 // return 2; // 2 threads for qHD/HD.
39 // } else { 47 // } else {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 // Copy the entire layer's data (including start codes). 142 // Copy the entire layer's data (including start codes).
135 memcpy(encoded_image->_buffer + encoded_image->_length, 143 memcpy(encoded_image->_buffer + encoded_image->_length,
136 layerInfo.pBsBuf, 144 layerInfo.pBsBuf,
137 layer_len); 145 layer_len);
138 encoded_image->_length += layer_len; 146 encoded_image->_length += layer_len;
139 } 147 }
140 } 148 }
141 149
142 H264EncoderImpl::H264EncoderImpl() 150 H264EncoderImpl::H264EncoderImpl()
143 : openh264_encoder_(nullptr), 151 : openh264_encoder_(nullptr),
144 encoded_image_callback_(nullptr) { 152 encoded_image_callback_(nullptr),
153 has_reported_init_(false),
154 has_reported_error_(false) {
145 } 155 }
146 156
147 H264EncoderImpl::~H264EncoderImpl() { 157 H264EncoderImpl::~H264EncoderImpl() {
148 Release(); 158 Release();
149 } 159 }
150 160
151 int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings, 161 int32_t H264EncoderImpl::InitEncode(const VideoCodec* codec_settings,
152 int32_t number_of_cores, 162 int32_t number_of_cores,
153 size_t /*max_payload_size*/) { 163 size_t /*max_payload_size*/) {
164 ReportInit();
154 if (!codec_settings || 165 if (!codec_settings ||
155 codec_settings->codecType != kVideoCodecH264) { 166 codec_settings->codecType != kVideoCodecH264) {
167 ReportError();
156 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 168 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
157 } 169 }
158 if (codec_settings->maxFramerate == 0) 170 if (codec_settings->maxFramerate == 0) {
171 ReportError();
159 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 172 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
160 if (codec_settings->width < 1 || codec_settings->height < 1) 173 }
174 if (codec_settings->width < 1 || codec_settings->height < 1) {
175 ReportError();
161 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 176 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
177 }
162 178
163 int32_t release_ret = Release(); 179 int32_t release_ret = Release();
164 if (release_ret != WEBRTC_VIDEO_CODEC_OK) 180 if (release_ret != WEBRTC_VIDEO_CODEC_OK) {
181 ReportError();
165 return release_ret; 182 return release_ret;
183 }
166 RTC_DCHECK(!openh264_encoder_); 184 RTC_DCHECK(!openh264_encoder_);
167 185
168 // Create encoder. 186 // Create encoder.
169 if (WelsCreateSVCEncoder(&openh264_encoder_) != 0) { 187 if (WelsCreateSVCEncoder(&openh264_encoder_) != 0) {
170 // Failed to create encoder. 188 // Failed to create encoder.
171 LOG(LS_ERROR) << "Failed to create OpenH264 encoder"; 189 LOG(LS_ERROR) << "Failed to create OpenH264 encoder";
172 RTC_DCHECK(!openh264_encoder_); 190 RTC_DCHECK(!openh264_encoder_);
191 ReportError();
173 return WEBRTC_VIDEO_CODEC_ERROR; 192 return WEBRTC_VIDEO_CODEC_ERROR;
174 } 193 }
175 RTC_DCHECK(openh264_encoder_); 194 RTC_DCHECK(openh264_encoder_);
176 if (kOpenH264EncoderDetailedLogging) { 195 if (kOpenH264EncoderDetailedLogging) {
177 int trace_level = WELS_LOG_DETAIL; 196 int trace_level = WELS_LOG_DETAIL;
178 openh264_encoder_->SetOption(ENCODER_OPTION_TRACE_LEVEL, 197 openh264_encoder_->SetOption(ENCODER_OPTION_TRACE_LEVEL,
179 &trace_level); 198 &trace_level);
180 } 199 }
181 // else WELS_LOG_DEFAULT is used by default. 200 // else WELS_LOG_DEFAULT is used by default.
182 201
183 codec_settings_ = *codec_settings; 202 codec_settings_ = *codec_settings;
184 if (codec_settings_.targetBitrate == 0) 203 if (codec_settings_.targetBitrate == 0)
185 codec_settings_.targetBitrate = codec_settings_.startBitrate; 204 codec_settings_.targetBitrate = codec_settings_.startBitrate;
186 205
187 // Initialization parameters. 206 // Initialization parameters.
188 // There are two ways to initialize. There is SEncParamBase (cleared with 207 // There are two ways to initialize. There is SEncParamBase (cleared with
189 // memset(&p, 0, sizeof(SEncParamBase)) used in Initialize, and SEncParamExt 208 // memset(&p, 0, sizeof(SEncParamBase)) used in Initialize, and SEncParamExt
190 // which is a superset of SEncParamBase (cleared with GetDefaultParams) used 209 // which is a superset of SEncParamBase (cleared with GetDefaultParams) used
191 // in InitializeExt. 210 // in InitializeExt.
192 SEncParamExt init_params; 211 SEncParamExt init_params;
193 openh264_encoder_->GetDefaultParams(&init_params); 212 openh264_encoder_->GetDefaultParams(&init_params);
194 if (codec_settings_.mode == kRealtimeVideo) { 213 if (codec_settings_.mode == kRealtimeVideo) {
195 init_params.iUsageType = CAMERA_VIDEO_REAL_TIME; 214 init_params.iUsageType = CAMERA_VIDEO_REAL_TIME;
196 } else if (codec_settings_.mode == kScreensharing) { 215 } else if (codec_settings_.mode == kScreensharing) {
197 init_params.iUsageType = SCREEN_CONTENT_REAL_TIME; 216 init_params.iUsageType = SCREEN_CONTENT_REAL_TIME;
198 } else { 217 } else {
218 ReportError();
199 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 219 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
200 } 220 }
201 init_params.iPicWidth = codec_settings_.width; 221 init_params.iPicWidth = codec_settings_.width;
202 init_params.iPicHeight = codec_settings_.height; 222 init_params.iPicHeight = codec_settings_.height;
203 // |init_params| uses bit/s, |codec_settings_| uses kbit/s. 223 // |init_params| uses bit/s, |codec_settings_| uses kbit/s.
204 init_params.iTargetBitrate = codec_settings_.targetBitrate * 1000; 224 init_params.iTargetBitrate = codec_settings_.targetBitrate * 1000;
205 init_params.iMaxBitrate = codec_settings_.maxBitrate * 1000; 225 init_params.iMaxBitrate = codec_settings_.maxBitrate * 1000;
206 // Rate Control mode 226 // Rate Control mode
207 init_params.iRCMode = RC_BITRATE_MODE; 227 init_params.iRCMode = RC_BITRATE_MODE;
208 init_params.fMaxFrameRate = static_cast<float>(codec_settings_.maxFramerate); 228 init_params.fMaxFrameRate = static_cast<float>(codec_settings_.maxFramerate);
(...skipping 20 matching lines...) Expand all
229 init_params.sSpatialLayers[0].fFrameRate = init_params.fMaxFrameRate; 249 init_params.sSpatialLayers[0].fFrameRate = init_params.fMaxFrameRate;
230 init_params.sSpatialLayers[0].iSpatialBitrate = init_params.iTargetBitrate; 250 init_params.sSpatialLayers[0].iSpatialBitrate = init_params.iTargetBitrate;
231 init_params.sSpatialLayers[0].iMaxSpatialBitrate = init_params.iMaxBitrate; 251 init_params.sSpatialLayers[0].iMaxSpatialBitrate = init_params.iMaxBitrate;
232 // Slice num according to number of threads. 252 // Slice num according to number of threads.
233 init_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE; 253 init_params.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE;
234 254
235 // Initialize. 255 // Initialize.
236 if (openh264_encoder_->InitializeExt(&init_params) != 0) { 256 if (openh264_encoder_->InitializeExt(&init_params) != 0) {
237 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder"; 257 LOG(LS_ERROR) << "Failed to initialize OpenH264 encoder";
238 Release(); 258 Release();
259 ReportError();
239 return WEBRTC_VIDEO_CODEC_ERROR; 260 return WEBRTC_VIDEO_CODEC_ERROR;
240 } 261 }
241 int video_format = EVideoFormatType::videoFormatI420; 262 int video_format = EVideoFormatType::videoFormatI420;
242 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT, 263 openh264_encoder_->SetOption(ENCODER_OPTION_DATAFORMAT,
243 &video_format); 264 &video_format);
244 265
245 // Initialize encoded image. Default buffer size: size of unencoded data. 266 // Initialize encoded image. Default buffer size: size of unencoded data.
246 encoded_image_._size = CalcBufferSize( 267 encoded_image_._size = CalcBufferSize(
247 kI420, codec_settings_.width, codec_settings_.height); 268 kI420, codec_settings_.width, codec_settings_.height);
248 encoded_image_._buffer = new uint8_t[encoded_image_._size]; 269 encoded_image_._buffer = new uint8_t[encoded_image_._size];
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 &target_bitrate); 313 &target_bitrate);
293 float max_framerate = static_cast<float>(codec_settings_.maxFramerate); 314 float max_framerate = static_cast<float>(codec_settings_.maxFramerate);
294 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE, 315 openh264_encoder_->SetOption(ENCODER_OPTION_FRAME_RATE,
295 &max_framerate); 316 &max_framerate);
296 return WEBRTC_VIDEO_CODEC_OK; 317 return WEBRTC_VIDEO_CODEC_OK;
297 } 318 }
298 319
299 int32_t H264EncoderImpl::Encode( 320 int32_t H264EncoderImpl::Encode(
300 const VideoFrame& frame, const CodecSpecificInfo* codec_specific_info, 321 const VideoFrame& frame, const CodecSpecificInfo* codec_specific_info,
301 const std::vector<FrameType>* frame_types) { 322 const std::vector<FrameType>* frame_types) {
302 if (!IsInitialized()) 323 if (!IsInitialized()) {
324 ReportError();
303 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 325 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
304 if (frame.IsZeroSize()) 326 }
327 if (frame.IsZeroSize()) {
328 ReportError();
305 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 329 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
330 }
306 if (!encoded_image_callback_) { 331 if (!encoded_image_callback_) {
307 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function " 332 LOG(LS_WARNING) << "InitEncode() has been called, but a callback function "
308 << "has not been set with RegisterEncodeCompleteCallback()"; 333 << "has not been set with RegisterEncodeCompleteCallback()";
334 ReportError();
309 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 335 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
310 } 336 }
311 if (frame.width() != codec_settings_.width || 337 if (frame.width() != codec_settings_.width ||
312 frame.height() != codec_settings_.height) { 338 frame.height() != codec_settings_.height) {
313 LOG(LS_WARNING) << "Encoder initialized for " << codec_settings_.width 339 LOG(LS_WARNING) << "Encoder initialized for " << codec_settings_.width
314 << "x" << codec_settings_.height << " but trying to encode " 340 << "x" << codec_settings_.height << " but trying to encode "
315 << frame.width() << "x" << frame.height() << " frame."; 341 << frame.width() << "x" << frame.height() << " frame.";
342 ReportError();
316 return WEBRTC_VIDEO_CODEC_ERR_SIZE; 343 return WEBRTC_VIDEO_CODEC_ERR_SIZE;
317 } 344 }
318 345
319 bool force_key_frame = false; 346 bool force_key_frame = false;
320 if (frame_types != nullptr) { 347 if (frame_types != nullptr) {
321 // We only support a single stream. 348 // We only support a single stream.
322 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1)); 349 RTC_DCHECK_EQ(frame_types->size(), static_cast<size_t>(1));
323 // Skip frame? 350 // Skip frame?
324 if ((*frame_types)[0] == kEmptyFrame) { 351 if ((*frame_types)[0] == kEmptyFrame) {
325 return WEBRTC_VIDEO_CODEC_OK; 352 return WEBRTC_VIDEO_CODEC_OK;
(...skipping 24 matching lines...) Expand all
350 377
351 // EncodeFrame output. 378 // EncodeFrame output.
352 SFrameBSInfo info; 379 SFrameBSInfo info;
353 memset(&info, 0, sizeof(SFrameBSInfo)); 380 memset(&info, 0, sizeof(SFrameBSInfo));
354 381
355 // Encode! 382 // Encode!
356 int enc_ret = openh264_encoder_->EncodeFrame(&picture, &info); 383 int enc_ret = openh264_encoder_->EncodeFrame(&picture, &info);
357 if (enc_ret != 0) { 384 if (enc_ret != 0) {
358 LOG(LS_ERROR) << "OpenH264 frame encoding failed, EncodeFrame returned " 385 LOG(LS_ERROR) << "OpenH264 frame encoding failed, EncodeFrame returned "
359 << enc_ret << "."; 386 << enc_ret << ".";
387 ReportError();
360 return WEBRTC_VIDEO_CODEC_ERROR; 388 return WEBRTC_VIDEO_CODEC_ERROR;
361 } 389 }
362 390
363 encoded_image_._encodedWidth = frame.width(); 391 encoded_image_._encodedWidth = frame.width();
364 encoded_image_._encodedHeight = frame.height(); 392 encoded_image_._encodedHeight = frame.height();
365 encoded_image_._timeStamp = frame.timestamp(); 393 encoded_image_._timeStamp = frame.timestamp();
366 encoded_image_.ntp_time_ms_ = frame.ntp_time_ms(); 394 encoded_image_.ntp_time_ms_ = frame.ntp_time_ms();
367 encoded_image_.capture_time_ms_ = frame.render_time_ms(); 395 encoded_image_.capture_time_ms_ = frame.render_time_ms();
368 encoded_image_._frameType = EVideoFrameType_to_FrameType(info.eFrameType); 396 encoded_image_._frameType = EVideoFrameType_to_FrameType(info.eFrameType);
369 397
(...skipping 12 matching lines...) Expand all
382 &codec_specific, 410 &codec_specific,
383 &frag_header); 411 &frag_header);
384 } 412 }
385 return WEBRTC_VIDEO_CODEC_OK; 413 return WEBRTC_VIDEO_CODEC_OK;
386 } 414 }
387 415
388 bool H264EncoderImpl::IsInitialized() const { 416 bool H264EncoderImpl::IsInitialized() const {
389 return openh264_encoder_ != nullptr; 417 return openh264_encoder_ != nullptr;
390 } 418 }
391 419
420 void H264EncoderImpl::ReportInit() {
421 if (has_reported_init_)
422 return;
423 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
424 kH264EncoderEventInit,
425 kH264EncoderEventMax);
426 has_reported_init_ = true;
427 }
428
429 void H264EncoderImpl::ReportError() {
430 if (has_reported_error_)
431 return;
432 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.H264EncoderImpl.Event",
433 kH264EncoderEventError,
434 kH264EncoderEventMax);
435 has_reported_error_ = true;
436 }
437
392 int32_t H264EncoderImpl::SetChannelParameters( 438 int32_t H264EncoderImpl::SetChannelParameters(
393 uint32_t packet_loss, int64_t rtt) { 439 uint32_t packet_loss, int64_t rtt) {
394 return WEBRTC_VIDEO_CODEC_OK; 440 return WEBRTC_VIDEO_CODEC_OK;
395 } 441 }
396 442
397 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) { 443 int32_t H264EncoderImpl::SetPeriodicKeyFrames(bool enable) {
398 return WEBRTC_VIDEO_CODEC_OK; 444 return WEBRTC_VIDEO_CODEC_OK;
399 } 445 }
400 446
401 void H264EncoderImpl::OnDroppedFrame() { 447 void H264EncoderImpl::OnDroppedFrame() {
402 } 448 }
403 449
404 } // namespace webrtc 450 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698