| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 #include "webrtc/modules/video_coding/generic_encoder.h" | 11 #include "webrtc/modules/video_coding/generic_encoder.h" |
| 12 | 12 |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "webrtc/base/checks.h" | 15 #include "webrtc/base/checks.h" |
| 16 #include "webrtc/base/logging.h" | 16 #include "webrtc/base/logging.h" |
| 17 #include "webrtc/base/trace_event.h" | 17 #include "webrtc/base/trace_event.h" |
| 18 #include "webrtc/engine_configurations.h" | 18 #include "webrtc/engine_configurations.h" |
| 19 #include "webrtc/modules/video_coding/encoded_frame.h" | 19 #include "webrtc/modules/video_coding/encoded_frame.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 case kVideoCodecGeneric: | 84 case kVideoCodecGeneric: |
| 85 rtp->codec = kRtpVideoGeneric; | 85 rtp->codec = kRtpVideoGeneric; |
| 86 rtp->simulcastIdx = info->codecSpecific.generic.simulcast_idx; | 86 rtp->simulcastIdx = info->codecSpecific.generic.simulcast_idx; |
| 87 return; | 87 return; |
| 88 default: | 88 default: |
| 89 return; | 89 return; |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 } // namespace | 92 } // namespace |
| 93 | 93 |
| 94 // #define DEBUG_ENCODER_BIT_STREAM | |
| 95 | |
| 96 VCMGenericEncoder::VCMGenericEncoder( | 94 VCMGenericEncoder::VCMGenericEncoder( |
| 97 VideoEncoder* encoder, | 95 VideoEncoder* encoder, |
| 98 VideoEncoderRateObserver* rate_observer, | 96 VideoEncoderRateObserver* rate_observer, |
| 99 VCMEncodedFrameCallback* encoded_frame_callback, | 97 VCMEncodedFrameCallback* encoded_frame_callback, |
| 100 bool internalSource) | 98 bool internal_source) |
| 101 : encoder_(encoder), | 99 : encoder_(encoder), |
| 102 rate_observer_(rate_observer), | 100 rate_observer_(rate_observer), |
| 103 vcm_encoded_frame_callback_(encoded_frame_callback), | 101 vcm_encoded_frame_callback_(encoded_frame_callback), |
| 104 internal_source_(internalSource), | 102 internal_source_(internal_source), |
| 105 encoder_params_({0, 0, 0, 0}), | 103 encoder_params_({0, 0, 0, 0}), |
| 106 rotation_(kVideoRotation_0), | 104 rotation_(kVideoRotation_0), |
| 107 is_screenshare_(false) {} | 105 is_screenshare_(false) {} |
| 108 | 106 |
| 109 VCMGenericEncoder::~VCMGenericEncoder() {} | 107 VCMGenericEncoder::~VCMGenericEncoder() {} |
| 110 | 108 |
| 111 int32_t VCMGenericEncoder::Release() { | 109 int32_t VCMGenericEncoder::Release() { |
| 112 TRACE_EVENT0("webrtc", "VCMGenericEncoder::Release"); | 110 TRACE_EVENT0("webrtc", "VCMGenericEncoder::Release"); |
| 113 return encoder_->Release(); | 111 return encoder_->Release(); |
| 114 } | 112 } |
| 115 | 113 |
| 116 int32_t VCMGenericEncoder::InitEncode(const VideoCodec* settings, | 114 int32_t VCMGenericEncoder::InitEncode(const VideoCodec* settings, |
| 117 int32_t numberOfCores, | 115 int32_t number_of_cores, |
| 118 size_t maxPayloadSize) { | 116 size_t max_payload_size) { |
| 119 TRACE_EVENT0("webrtc", "VCMGenericEncoder::InitEncode"); | 117 TRACE_EVENT0("webrtc", "VCMGenericEncoder::InitEncode"); |
| 120 { | 118 { |
| 121 rtc::CritScope lock(¶ms_lock_); | 119 rtc::CritScope lock(¶ms_lock_); |
| 122 encoder_params_.target_bitrate = settings->startBitrate * 1000; | 120 encoder_params_.target_bitrate = settings->startBitrate * 1000; |
| 123 encoder_params_.input_frame_rate = settings->maxFramerate; | 121 encoder_params_.input_frame_rate = settings->maxFramerate; |
| 124 } | 122 } |
| 125 | 123 |
| 126 is_screenshare_ = settings->mode == VideoCodecMode::kScreensharing; | 124 is_screenshare_ = settings->mode == VideoCodecMode::kScreensharing; |
| 127 if (encoder_->InitEncode(settings, numberOfCores, maxPayloadSize) != 0) { | 125 if (encoder_->InitEncode(settings, number_of_cores, max_payload_size) != 0) { |
| 128 LOG(LS_ERROR) << "Failed to initialize the encoder associated with " | 126 LOG(LS_ERROR) << "Failed to initialize the encoder associated with " |
| 129 "payload name: " | 127 "payload name: " |
| 130 << settings->plName; | 128 << settings->plName; |
| 131 return -1; | 129 return -1; |
| 132 } | 130 } |
| 133 encoder_->RegisterEncodeCompleteCallback(vcm_encoded_frame_callback_); | 131 encoder_->RegisterEncodeCompleteCallback(vcm_encoded_frame_callback_); |
| 134 return 0; | 132 return 0; |
| 135 } | 133 } |
| 136 | 134 |
| 137 int32_t VCMGenericEncoder::Encode(const VideoFrame& inputFrame, | 135 int32_t VCMGenericEncoder::Encode(const VideoFrame& frame, |
| 138 const CodecSpecificInfo* codecSpecificInfo, | 136 const CodecSpecificInfo* codec_specific, |
| 139 const std::vector<FrameType>& frameTypes) { | 137 const std::vector<FrameType>& frame_types) { |
| 140 TRACE_EVENT1("webrtc", "VCMGenericEncoder::Encode", "timestamp", | 138 TRACE_EVENT1("webrtc", "VCMGenericEncoder::Encode", "timestamp", |
| 141 inputFrame.timestamp()); | 139 frame.timestamp()); |
| 142 | 140 |
| 143 for (FrameType frame_type : frameTypes) | 141 for (FrameType frame_type : frame_types) |
| 144 RTC_DCHECK(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta); | 142 RTC_DCHECK(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta); |
| 145 | 143 |
| 146 rotation_ = inputFrame.rotation(); | 144 rotation_ = frame.rotation(); |
| 147 | 145 |
| 148 // Keep track of the current frame rotation and apply to the output of the | 146 // Keep track of the current frame rotation and apply to the output of the |
| 149 // encoder. There might not be exact as the encoder could have one frame delay | 147 // encoder. There might not be exact as the encoder could have one frame delay |
| 150 // but it should be close enough. | 148 // but it should be close enough. |
| 151 // TODO(pbos): Map from timestamp, this is racy (even if rotation_ is locked | 149 // TODO(pbos): Map from timestamp, this is racy (even if rotation_ is locked |
| 152 // properly, which it isn't). More than one frame may be in the pipeline. | 150 // properly, which it isn't). More than one frame may be in the pipeline. |
| 153 vcm_encoded_frame_callback_->SetRotation(rotation_); | 151 vcm_encoded_frame_callback_->SetRotation(rotation_); |
| 154 | 152 |
| 155 int32_t result = encoder_->Encode(inputFrame, codecSpecificInfo, &frameTypes); | 153 int32_t result = encoder_->Encode(frame, codec_specific, &frame_types); |
| 156 | 154 |
| 157 if (vcm_encoded_frame_callback_) { | 155 if (vcm_encoded_frame_callback_) { |
| 158 vcm_encoded_frame_callback_->SignalLastEncoderImplementationUsed( | 156 vcm_encoded_frame_callback_->SignalLastEncoderImplementationUsed( |
| 159 encoder_->ImplementationName()); | 157 encoder_->ImplementationName()); |
| 160 } | 158 } |
| 161 | 159 |
| 162 if (is_screenshare_ && | 160 if (is_screenshare_ && |
| 163 result == WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT) { | 161 result == WEBRTC_VIDEO_CODEC_TARGET_BITRATE_OVERSHOOT) { |
| 164 // Target bitrate exceeded, encoder state has been reset - try again. | 162 // Target bitrate exceeded, encoder state has been reset - try again. |
| 165 return encoder_->Encode(inputFrame, codecSpecificInfo, &frameTypes); | 163 return encoder_->Encode(frame, codec_specific, &frame_types); |
| 166 } | 164 } |
| 167 | 165 |
| 168 return result; | 166 return result; |
| 169 } | 167 } |
| 170 | 168 |
| 171 void VCMGenericEncoder::SetEncoderParameters(const EncoderParameters& params) { | 169 void VCMGenericEncoder::SetEncoderParameters(const EncoderParameters& params) { |
| 172 bool channel_parameters_have_changed; | 170 bool channel_parameters_have_changed; |
| 173 bool rates_have_changed; | 171 bool rates_have_changed; |
| 174 { | 172 { |
| 175 rtc::CritScope lock(¶ms_lock_); | 173 rtc::CritScope lock(¶ms_lock_); |
| 176 channel_parameters_have_changed = | 174 channel_parameters_have_changed = |
| 177 params.loss_rate != encoder_params_.loss_rate || | 175 params.loss_rate != encoder_params_.loss_rate || |
| 178 params.rtt != encoder_params_.rtt; | 176 params.rtt != encoder_params_.rtt; |
| 179 rates_have_changed = | 177 rates_have_changed = |
| 180 params.target_bitrate != encoder_params_.target_bitrate || | 178 params.target_bitrate != encoder_params_.target_bitrate || |
| 181 params.input_frame_rate != encoder_params_.input_frame_rate; | 179 params.input_frame_rate != encoder_params_.input_frame_rate; |
| 182 encoder_params_ = params; | 180 encoder_params_ = params; |
| 183 } | 181 } |
| 184 if (channel_parameters_have_changed) | 182 if (channel_parameters_have_changed) |
| 185 encoder_->SetChannelParameters(params.loss_rate, params.rtt); | 183 encoder_->SetChannelParameters(params.loss_rate, params.rtt); |
| 186 if (rates_have_changed) { | 184 if (rates_have_changed) { |
| 187 uint32_t target_bitrate_kbps = (params.target_bitrate + 500) / 1000; | 185 uint32_t target_bitrate_kbps = (params.target_bitrate + 500) / 1000; |
| 188 encoder_->SetRates(target_bitrate_kbps, params.input_frame_rate); | 186 encoder_->SetRates(target_bitrate_kbps, params.input_frame_rate); |
| 189 if (rate_observer_ != nullptr) { | 187 if (rate_observer_) { |
| 190 rate_observer_->OnSetRates(params.target_bitrate, | 188 rate_observer_->OnSetRates(params.target_bitrate, |
| 191 params.input_frame_rate); | 189 params.input_frame_rate); |
| 192 } | 190 } |
| 193 } | 191 } |
| 194 } | 192 } |
| 195 | 193 |
| 196 EncoderParameters VCMGenericEncoder::GetEncoderParameters() const { | 194 EncoderParameters VCMGenericEncoder::GetEncoderParameters() const { |
| 197 rtc::CritScope lock(¶ms_lock_); | 195 rtc::CritScope lock(¶ms_lock_); |
| 198 return encoder_params_; | 196 return encoder_params_; |
| 199 } | 197 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 217 } | 215 } |
| 218 | 216 |
| 219 bool VCMGenericEncoder::SupportsNativeHandle() const { | 217 bool VCMGenericEncoder::SupportsNativeHandle() const { |
| 220 return encoder_->SupportsNativeHandle(); | 218 return encoder_->SupportsNativeHandle(); |
| 221 } | 219 } |
| 222 | 220 |
| 223 int VCMGenericEncoder::GetTargetFramerate() { | 221 int VCMGenericEncoder::GetTargetFramerate() { |
| 224 return encoder_->GetTargetFramerate(); | 222 return encoder_->GetTargetFramerate(); |
| 225 } | 223 } |
| 226 | 224 |
| 227 /*************************** | |
| 228 * Callback Implementation | |
| 229 ***************************/ | |
| 230 VCMEncodedFrameCallback::VCMEncodedFrameCallback( | 225 VCMEncodedFrameCallback::VCMEncodedFrameCallback( |
| 231 EncodedImageCallback* post_encode_callback) | 226 EncodedImageCallback* post_encode_callback) |
| 232 : send_callback_(), | 227 : send_callback_(), |
| 233 _mediaOpt(NULL), | 228 media_opt_(nullptr), |
| 234 _payloadType(0), | 229 payload_type_(0), |
| 235 _internalSource(false), | 230 internal_source_(false), |
| 236 _rotation(kVideoRotation_0), | 231 rotation_(kVideoRotation_0), |
| 237 post_encode_callback_(post_encode_callback) | 232 post_encode_callback_(post_encode_callback) {} |
| 238 #ifdef DEBUG_ENCODER_BIT_STREAM | |
| 239 , | |
| 240 _bitStreamAfterEncoder(NULL) | |
| 241 #endif | |
| 242 { | |
| 243 #ifdef DEBUG_ENCODER_BIT_STREAM | |
| 244 _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb"); | |
| 245 #endif | |
| 246 } | |
| 247 | 233 |
| 248 VCMEncodedFrameCallback::~VCMEncodedFrameCallback() { | 234 VCMEncodedFrameCallback::~VCMEncodedFrameCallback() {} |
| 249 #ifdef DEBUG_ENCODER_BIT_STREAM | |
| 250 fclose(_bitStreamAfterEncoder); | |
| 251 #endif | |
| 252 } | |
| 253 | 235 |
| 254 int32_t VCMEncodedFrameCallback::SetTransportCallback( | 236 int32_t VCMEncodedFrameCallback::SetTransportCallback( |
| 255 VCMPacketizationCallback* transport) { | 237 VCMPacketizationCallback* transport) { |
| 256 send_callback_ = transport; | 238 send_callback_ = transport; |
| 257 return VCM_OK; | 239 return VCM_OK; |
| 258 } | 240 } |
| 259 | 241 |
| 260 int32_t VCMEncodedFrameCallback::Encoded( | 242 int32_t VCMEncodedFrameCallback::Encoded( |
| 261 const EncodedImage& encoded_image, | 243 const EncodedImage& encoded_image, |
| 262 const CodecSpecificInfo* codecSpecificInfo, | 244 const CodecSpecificInfo* codec_specific, |
| 263 const RTPFragmentationHeader* fragmentationHeader) { | 245 const RTPFragmentationHeader* fragmentation_header) { |
| 264 TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded", | 246 TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded", |
| 265 "timestamp", encoded_image._timeStamp); | 247 "timestamp", encoded_image._timeStamp); |
| 266 post_encode_callback_->Encoded(encoded_image, NULL, NULL); | 248 post_encode_callback_->Encoded(encoded_image, nullptr, nullptr); |
| 267 | 249 |
| 268 if (send_callback_ == NULL) { | 250 if (send_callback_ == nullptr) |
| 269 return VCM_UNINITIALIZED; | 251 return VCM_UNINITIALIZED; |
| 270 } | |
| 271 | 252 |
| 272 #ifdef DEBUG_ENCODER_BIT_STREAM | 253 RTPVideoHeader rtp_video_header; |
| 273 if (_bitStreamAfterEncoder != NULL) { | 254 memset(&rtp_video_header, 0, sizeof(RTPVideoHeader)); |
| 274 fwrite(encoded_image._buffer, 1, encoded_image._length, | 255 if (codec_specific) |
| 275 _bitStreamAfterEncoder); | 256 CopyCodecSpecific(codec_specific, &rtp_video_header); |
| 276 } | 257 rtp_video_header.rotation = rotation_; |
| 277 #endif | |
| 278 | 258 |
| 279 RTPVideoHeader rtpVideoHeader; | 259 int32_t ret_val = send_callback_->SendData( |
| 280 memset(&rtpVideoHeader, 0, sizeof(RTPVideoHeader)); | 260 payload_type_, encoded_image, fragmentation_header, &rtp_video_header); |
| 281 RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader; | 261 if (ret_val < 0) |
| 282 if (codecSpecificInfo) { | 262 return ret_val; |
| 283 CopyCodecSpecific(codecSpecificInfo, rtpVideoHeaderPtr); | |
| 284 } | |
| 285 rtpVideoHeader.rotation = _rotation; | |
| 286 | 263 |
| 287 int32_t callbackReturn = send_callback_->SendData( | 264 if (media_opt_) { |
| 288 _payloadType, encoded_image, fragmentationHeader, rtpVideoHeaderPtr); | 265 media_opt_->UpdateWithEncodedData(encoded_image); |
| 289 if (callbackReturn < 0) { | 266 if (internal_source_) |
| 290 return callbackReturn; | 267 return media_opt_->DropFrame(); // Signal to encoder to drop next frame. |
| 291 } | |
| 292 | |
| 293 if (_mediaOpt != NULL) { | |
| 294 _mediaOpt->UpdateWithEncodedData(encoded_image); | |
| 295 if (_internalSource) | |
| 296 return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame. | |
| 297 } | 268 } |
| 298 return VCM_OK; | 269 return VCM_OK; |
| 299 } | 270 } |
| 300 | 271 |
| 301 void VCMEncodedFrameCallback::SetMediaOpt( | 272 void VCMEncodedFrameCallback::SetMediaOpt( |
| 302 media_optimization::MediaOptimization* mediaOpt) { | 273 media_optimization::MediaOptimization* mediaOpt) { |
| 303 _mediaOpt = mediaOpt; | 274 media_opt_ = mediaOpt; |
| 304 } | 275 } |
| 305 | 276 |
| 306 void VCMEncodedFrameCallback::SignalLastEncoderImplementationUsed( | 277 void VCMEncodedFrameCallback::SignalLastEncoderImplementationUsed( |
| 307 const char* implementation_name) { | 278 const char* implementation_name) { |
| 308 if (send_callback_) | 279 if (send_callback_) |
| 309 send_callback_->OnEncoderImplementationName(implementation_name); | 280 send_callback_->OnEncoderImplementationName(implementation_name); |
| 310 } | 281 } |
| 311 | |
| 312 } // namespace webrtc | 282 } // namespace webrtc |
| OLD | NEW |