1/* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/engine_configurations.h" 12#include "webrtc/modules/video_coding/main/source/encoded_frame.h" 13#include "webrtc/modules/video_coding/main/source/generic_encoder.h" 14#include "webrtc/modules/video_coding/main/source/media_optimization.h" 15#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 16#include "webrtc/system_wrappers/interface/logging.h" 17 18namespace webrtc { 19namespace { 20// Map information from info into rtp. If no relevant information is found 21// in info, rtp is set to NULL. 22void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) { 23 if (!info) { 24 *rtp = NULL; 25 return; 26 } 27 switch (info->codecType) { 28 case kVideoCodecVP8: { 29 (*rtp)->codec = kRtpVideoVp8; 30 (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8(); 31 (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId; 32 (*rtp)->codecHeader.VP8.nonReference = 33 info->codecSpecific.VP8.nonReference; 34 (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx; 35 (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync; 36 (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx; 37 (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx; 38 (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx; 39 return; 40 } 41 case kVideoCodecH264: 42 (*rtp)->codec = kRtpVideoH264; 43 return; 44 case kVideoCodecGeneric: 45 (*rtp)->codec = kRtpVideoGeneric; 46 (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx; 47 return; 48 default: 49 // No codec specific info. Change RTP header pointer to NULL. 50 *rtp = NULL; 51 return; 52 } 53} 54} // namespace 55 56//#define DEBUG_ENCODER_BIT_STREAM 57 58VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/) 59: 60_encoder(encoder), 61_codecType(kVideoCodecUnknown), 62_VCMencodedFrameCallback(NULL), 63_bitRate(0), 64_frameRate(0), 65_internalSource(internalSource) 66{ 67} 68 69 70VCMGenericEncoder::~VCMGenericEncoder() 71{ 72} 73 74int32_t VCMGenericEncoder::Release() 75{ 76 _bitRate = 0; 77 _frameRate = 0; 78 _VCMencodedFrameCallback = NULL; 79 return _encoder.Release(); 80} 81 82int32_t 83VCMGenericEncoder::InitEncode(const VideoCodec* settings, 84 int32_t numberOfCores, 85 uint32_t maxPayloadSize) 86{ 87 _bitRate = settings->startBitrate * 1000; 88 _frameRate = settings->maxFramerate; 89 _codecType = settings->codecType; 90 if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) { 91 LOG(LS_ERROR) << "Failed to initialize the encoder associated with " 92 "payload name: " << settings->plName; 93 return -1; 94 } 95 return 0; 96} 97 98int32_t 99VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame, 100 const CodecSpecificInfo* codecSpecificInfo, 101 const std::vector<FrameType>& frameTypes) { 102 std::vector<VideoFrameType> video_frame_types(frameTypes.size(), 103 kDeltaFrame); 104 VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types); 105 return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types); 106} 107 108int32_t 109VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int rtt) 110{ 111 return _encoder.SetChannelParameters(packetLoss, rtt); 112} 113 114int32_t 115VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate) 116{ 117 uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000; 118 int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate); 119 if (ret < 0) 120 { 121 return ret; 122 } 123 _bitRate = newBitRate; 124 _frameRate = frameRate; 125 return VCM_OK; 126} 127 128int32_t 129VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size) 130{ 131 int32_t ret = _encoder.CodecConfigParameters(buffer, size); 132 if (ret < 0) 133 { 134 return ret; 135 } 136 return ret; 137} 138 139uint32_t VCMGenericEncoder::BitRate() const 140{ 141 return _bitRate; 142} 143 144uint32_t VCMGenericEncoder::FrameRate() const 145{ 146 return _frameRate; 147} 148 149int32_t 150VCMGenericEncoder::SetPeriodicKeyFrames(bool enable) 151{ 152 return _encoder.SetPeriodicKeyFrames(enable); 153} 154 155int32_t VCMGenericEncoder::RequestFrame( 156 const std::vector<FrameType>& frame_types) { 157 I420VideoFrame image; 158 std::vector<VideoFrameType> video_frame_types(frame_types.size(), 159 kDeltaFrame); 160 VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types); 161 return _encoder.Encode(image, NULL, &video_frame_types); 162} 163 164int32_t 165VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback) 166{ 167 _VCMencodedFrameCallback = VCMencodedFrameCallback; 168 _VCMencodedFrameCallback->SetInternalSource(_internalSource); 169 return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback); 170} 171 172bool 173VCMGenericEncoder::InternalSource() const 174{ 175 return _internalSource; 176} 177 178 /*************************** 179 * Callback Implementation 180 ***************************/ 181VCMEncodedFrameCallback::VCMEncodedFrameCallback( 182 EncodedImageCallback* post_encode_callback): 183_sendCallback(), 184_mediaOpt(NULL), 185_payloadType(0), 186_internalSource(false), 187post_encode_callback_(post_encode_callback) 188#ifdef DEBUG_ENCODER_BIT_STREAM 189, _bitStreamAfterEncoder(NULL) 190#endif 191{ 192#ifdef DEBUG_ENCODER_BIT_STREAM 193 _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb"); 194#endif 195} 196 197VCMEncodedFrameCallback::~VCMEncodedFrameCallback() 198{ 199#ifdef DEBUG_ENCODER_BIT_STREAM 200 fclose(_bitStreamAfterEncoder); 201#endif 202} 203 204int32_t 205VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport) 206{ 207 _sendCallback = transport; 208 return VCM_OK; 209} 210 211int32_t 212VCMEncodedFrameCallback::Encoded( 213 EncodedImage &encodedImage, 214 const CodecSpecificInfo* codecSpecificInfo, 215 const RTPFragmentationHeader* fragmentationHeader) 216{ 217 post_encode_callback_->Encoded(encodedImage); 218 219 FrameType frameType = VCMEncodedFrame::ConvertFrameType(encodedImage._frameType); 220 221 uint32_t encodedBytes = 0; 222 if (_sendCallback != NULL) 223 { 224 encodedBytes = encodedImage._length; 225 226#ifdef DEBUG_ENCODER_BIT_STREAM 227 if (_bitStreamAfterEncoder != NULL) 228 { 229 fwrite(encodedImage._buffer, 1, encodedImage._length, _bitStreamAfterEncoder); 230 } 231#endif 232 233 RTPVideoHeader rtpVideoHeader; 234 RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader; 235 CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr); 236 237 int32_t callbackReturn = _sendCallback->SendData( 238 frameType, 239 _payloadType, 240 encodedImage._timeStamp, 241 encodedImage.capture_time_ms_, 242 encodedImage._buffer, 243 encodedBytes, 244 *fragmentationHeader, 245 rtpVideoHeaderPtr); 246 if (callbackReturn < 0) 247 { 248 return callbackReturn; 249 } 250 } 251 else 252 { 253 return VCM_UNINITIALIZED; 254 } 255 if (_mediaOpt != NULL) { 256 _mediaOpt->UpdateWithEncodedData(encodedBytes, encodedImage._timeStamp, 257 frameType); 258 if (_internalSource) 259 { 260 return _mediaOpt->DropFrame(); // Signal to encoder to drop next frame 261 } 262 } 263 return VCM_OK; 264} 265 266void 267VCMEncodedFrameCallback::SetMediaOpt( 268 media_optimization::MediaOptimization *mediaOpt) 269{ 270 _mediaOpt = mediaOpt; 271} 272 273} // namespace webrtc 274