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/modules/rtp_rtcp/source/rtp_sender_video.h" 12 13 #include <assert.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" 18 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 19 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" 20 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" 21 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 22 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 23 #include "webrtc/system_wrappers/interface/logging.h" 24 #include "webrtc/system_wrappers/interface/trace_event.h" 25 26 namespace webrtc { 27 enum { REDForFECHeaderLength = 1 }; 28 29 struct RtpPacket { 30 uint16_t rtpHeaderLength; 31 ForwardErrorCorrection::Packet* pkt; 32 }; 33 34 RTPSenderVideo::RTPSenderVideo(Clock* clock, 35 RTPSenderInterface* rtpSender) 36 : _rtpSender(*rtpSender), 37 _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()), 38 _videoType(kRtpVideoGeneric), 39 _videoCodecInformation(NULL), 40 _maxBitrate(0), 41 _retransmissionSettings(kRetransmitBaseLayer), 42 43 // Generic FEC 44 _fec(), 45 _fecEnabled(false), 46 _payloadTypeRED(-1), 47 _payloadTypeFEC(-1), 48 _numberFirstPartition(0), 49 delta_fec_params_(), 50 key_fec_params_(), 51 producer_fec_(&_fec), 52 _fecOverheadRate(clock, NULL), 53 _videoBitrate(clock, NULL) { 54 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 55 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 56 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; 57 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = 58 kFecMaskRandom; 59 } 60 61 RTPSenderVideo::~RTPSenderVideo() 62 { 63 if(_videoCodecInformation) 64 { 65 delete _videoCodecInformation; 66 } 67 delete _sendVideoCritsect; 68 } 69 70 void 71 RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) 72 { 73 CriticalSectionScoped cs(_sendVideoCritsect); 74 _videoType = videoType; 75 } 76 77 RtpVideoCodecTypes 78 RTPSenderVideo::VideoCodecType() const 79 { 80 return _videoType; 81 } 82 83 int32_t RTPSenderVideo::RegisterVideoPayload( 84 const char payloadName[RTP_PAYLOAD_NAME_SIZE], 85 const int8_t payloadType, 86 const uint32_t maxBitRate, 87 ModuleRTPUtility::Payload*& payload) { 88 CriticalSectionScoped cs(_sendVideoCritsect); 89 90 RtpVideoCodecTypes videoType = kRtpVideoGeneric; 91 if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) { 92 videoType = kRtpVideoVp8; 93 } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) { 94 videoType = kRtpVideoGeneric; 95 } else { 96 videoType = kRtpVideoGeneric; 97 } 98 payload = new ModuleRTPUtility::Payload; 99 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; 100 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 101 payload->typeSpecific.Video.videoCodecType = videoType; 102 payload->typeSpecific.Video.maxRate = maxBitRate; 103 payload->audio = false; 104 return 0; 105 } 106 107 int32_t 108 RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, 109 const uint16_t payload_length, 110 const uint16_t rtp_header_length, 111 const uint32_t capture_timestamp, 112 int64_t capture_time_ms, 113 StorageType storage, 114 bool protect) { 115 if(_fecEnabled) { 116 int ret = 0; 117 int fec_overhead_sent = 0; 118 int video_sent = 0; 119 120 RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer, 121 payload_length, 122 rtp_header_length, 123 _payloadTypeRED); 124 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketRed", 125 "timestamp", capture_timestamp, 126 "seqnum", _rtpSender.SequenceNumber()); 127 // Sending the media packet with RED header. 128 int packet_success = _rtpSender.SendToNetwork( 129 red_packet->data(), 130 red_packet->length() - rtp_header_length, 131 rtp_header_length, 132 capture_time_ms, 133 storage, 134 PacedSender::kNormalPriority); 135 136 ret |= packet_success; 137 138 if (packet_success == 0) { 139 video_sent += red_packet->length(); 140 } 141 delete red_packet; 142 red_packet = NULL; 143 144 if (protect) { 145 ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, 146 payload_length, 147 rtp_header_length); 148 if (ret != 0) 149 return ret; 150 } 151 152 while (producer_fec_.FecAvailable()) { 153 red_packet = producer_fec_.GetFecPacket( 154 _payloadTypeRED, 155 _payloadTypeFEC, 156 _rtpSender.IncrementSequenceNumber(), 157 rtp_header_length); 158 StorageType storage = kDontRetransmit; 159 if (_retransmissionSettings & kRetransmitFECPackets) { 160 storage = kAllowRetransmission; 161 } 162 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketFec", 163 "timestamp", capture_timestamp, 164 "seqnum", _rtpSender.SequenceNumber()); 165 // Sending FEC packet with RED header. 166 int packet_success = _rtpSender.SendToNetwork( 167 red_packet->data(), 168 red_packet->length() - rtp_header_length, 169 rtp_header_length, 170 capture_time_ms, 171 storage, 172 PacedSender::kNormalPriority); 173 174 ret |= packet_success; 175 176 if (packet_success == 0) { 177 fec_overhead_sent += red_packet->length(); 178 } 179 delete red_packet; 180 red_packet = NULL; 181 } 182 _videoBitrate.Update(video_sent); 183 _fecOverheadRate.Update(fec_overhead_sent); 184 return ret; 185 } 186 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal", 187 "timestamp", capture_timestamp, 188 "seqnum", _rtpSender.SequenceNumber()); 189 int ret = _rtpSender.SendToNetwork(data_buffer, 190 payload_length, 191 rtp_header_length, 192 capture_time_ms, 193 storage, 194 PacedSender::kNormalPriority); 195 if (ret == 0) { 196 _videoBitrate.Update(payload_length + rtp_header_length); 197 } 198 return ret; 199 } 200 201 int32_t 202 RTPSenderVideo::SendRTPIntraRequest() 203 { 204 // RFC 2032 205 // 5.2.1. Full intra-frame Request (FIR) packet 206 207 uint16_t length = 8; 208 uint8_t data[8]; 209 data[0] = 0x80; 210 data[1] = 192; 211 data[2] = 0; 212 data[3] = 1; // length 213 214 ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC()); 215 216 TRACE_EVENT_INSTANT1("webrtc_rtp", 217 "Video::IntraRequest", 218 "seqnum", _rtpSender.SequenceNumber()); 219 return _rtpSender.SendToNetwork(data, 0, length, -1, kDontStore, 220 PacedSender::kNormalPriority); 221 } 222 223 int32_t 224 RTPSenderVideo::SetGenericFECStatus(const bool enable, 225 const uint8_t payloadTypeRED, 226 const uint8_t payloadTypeFEC) 227 { 228 _fecEnabled = enable; 229 _payloadTypeRED = payloadTypeRED; 230 _payloadTypeFEC = payloadTypeFEC; 231 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 232 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 233 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; 234 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = 235 kFecMaskRandom; 236 return 0; 237 } 238 239 int32_t 240 RTPSenderVideo::GenericFECStatus(bool& enable, 241 uint8_t& payloadTypeRED, 242 uint8_t& payloadTypeFEC) const 243 { 244 enable = _fecEnabled; 245 payloadTypeRED = _payloadTypeRED; 246 payloadTypeFEC = _payloadTypeFEC; 247 return 0; 248 } 249 250 uint16_t 251 RTPSenderVideo::FECPacketOverhead() const 252 { 253 if (_fecEnabled) 254 { 255 // Overhead is FEC headers plus RED for FEC header plus anything in RTP 256 // header beyond the 12 bytes base header (CSRC list, extensions...) 257 // This reason for the header extensions to be included here is that 258 // from an FEC viewpoint, they are part of the payload to be protected. 259 // (The base RTP header is already protected by the FEC header.) 260 return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength + 261 (_rtpSender.RTPHeaderLength() - kRtpHeaderSize); 262 } 263 return 0; 264 } 265 266 int32_t RTPSenderVideo::SetFecParameters( 267 const FecProtectionParams* delta_params, 268 const FecProtectionParams* key_params) { 269 assert(delta_params); 270 assert(key_params); 271 delta_fec_params_ = *delta_params; 272 key_fec_params_ = *key_params; 273 return 0; 274 } 275 276 int32_t 277 RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, 278 const FrameType frameType, 279 const int8_t payloadType, 280 const uint32_t captureTimeStamp, 281 int64_t capture_time_ms, 282 const uint8_t* payloadData, 283 const uint32_t payloadSize, 284 const RTPFragmentationHeader* fragmentation, 285 VideoCodecInformation* codecInfo, 286 const RTPVideoTypeHeader* rtpTypeHdr) 287 { 288 if( payloadSize == 0) 289 { 290 return -1; 291 } 292 293 if (frameType == kVideoFrameKey) { 294 producer_fec_.SetFecParameters(&key_fec_params_, 295 _numberFirstPartition); 296 } else { 297 producer_fec_.SetFecParameters(&delta_fec_params_, 298 _numberFirstPartition); 299 } 300 301 // Default setting for number of first partition packets: 302 // Will be extracted in SendVP8 for VP8 codec; other codecs use 0 303 _numberFirstPartition = 0; 304 305 int32_t retVal = -1; 306 switch(videoType) 307 { 308 case kRtpVideoGeneric: 309 retVal = SendGeneric(frameType, payloadType, captureTimeStamp, 310 capture_time_ms, payloadData, payloadSize); 311 break; 312 case kRtpVideoVp8: 313 retVal = SendVP8(frameType, 314 payloadType, 315 captureTimeStamp, 316 capture_time_ms, 317 payloadData, 318 payloadSize, 319 fragmentation, 320 rtpTypeHdr); 321 break; 322 default: 323 assert(false); 324 break; 325 } 326 if(retVal <= 0) 327 { 328 return retVal; 329 } 330 return 0; 331 } 332 333 int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type, 334 const int8_t payload_type, 335 const uint32_t capture_timestamp, 336 int64_t capture_time_ms, 337 const uint8_t* payload, 338 uint32_t size) { 339 assert(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta); 340 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); 341 uint16_t max_length = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - 342 rtp_header_length - (1 /* generic header length */); 343 344 // Fragment packets more evenly by splitting the payload up evenly. 345 uint32_t num_packets = (size + max_length - 1) / max_length; 346 uint32_t payload_length = (size + num_packets - 1) / num_packets; 347 assert(payload_length <= max_length); 348 349 // Fragment packet into packets of max MaxPayloadLength bytes payload. 350 uint8_t buffer[IP_PACKET_SIZE]; 351 352 uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit; 353 if (frame_type == kVideoFrameKey) { 354 generic_header |= RtpFormatVideoGeneric::kKeyFrameBit; 355 } 356 357 while (size > 0) { 358 if (size < payload_length) { 359 payload_length = size; 360 } 361 size -= payload_length; 362 363 // MarkerBit is 1 on final packet (bytes_to_send == 0) 364 if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0, 365 capture_timestamp, 366 capture_time_ms) != rtp_header_length) { 367 return -1; 368 } 369 370 uint8_t* out_ptr = &buffer[rtp_header_length]; 371 372 // Put generic header in packet 373 *out_ptr++ = generic_header; 374 // Remove first-packet bit, following packets are intermediate 375 generic_header &= ~RtpFormatVideoGeneric::kFirstPacketBit; 376 377 // Put payload in packet 378 memcpy(out_ptr, payload, payload_length); 379 payload += payload_length; 380 381 if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length, 382 capture_timestamp, capture_time_ms, 383 kAllowRetransmission, true)) { 384 return -1; 385 } 386 } 387 return 0; 388 } 389 390 VideoCodecInformation* 391 RTPSenderVideo::CodecInformationVideo() 392 { 393 return _videoCodecInformation; 394 } 395 396 void 397 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) 398 { 399 _maxBitrate = maxBitrate; 400 } 401 402 uint32_t 403 RTPSenderVideo::MaxConfiguredBitrateVideo() const 404 { 405 return _maxBitrate; 406 } 407 408 int32_t 409 RTPSenderVideo::SendVP8(const FrameType frameType, 410 const int8_t payloadType, 411 const uint32_t captureTimeStamp, 412 int64_t capture_time_ms, 413 const uint8_t* payloadData, 414 const uint32_t payloadSize, 415 const RTPFragmentationHeader* fragmentation, 416 const RTPVideoTypeHeader* rtpTypeHdr) 417 { 418 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength(); 419 420 int32_t payloadBytesToSend = payloadSize; 421 const uint8_t* data = payloadData; 422 423 uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength(); 424 425 assert(rtpTypeHdr); 426 // Initialize disregarding partition boundaries: this will use kEqualSize 427 // packetization mode, which produces ~equal size packets for each frame. 428 RtpFormatVp8 packetizer(data, payloadBytesToSend, rtpTypeHdr->VP8, 429 maxPayloadLengthVP8); 430 431 StorageType storage = kAllowRetransmission; 432 if (rtpTypeHdr->VP8.temporalIdx == 0 && 433 !(_retransmissionSettings & kRetransmitBaseLayer)) { 434 storage = kDontRetransmit; 435 } 436 if (rtpTypeHdr->VP8.temporalIdx > 0 && 437 !(_retransmissionSettings & kRetransmitHigherLayers)) { 438 storage = kDontRetransmit; 439 } 440 441 bool last = false; 442 _numberFirstPartition = 0; 443 // |rtpTypeHdr->VP8.temporalIdx| is zero for base layers, or -1 if the field 444 // isn't used. We currently only protect base layers. 445 bool protect = (rtpTypeHdr->VP8.temporalIdx < 1); 446 while (!last) 447 { 448 // Write VP8 Payload Descriptor and VP8 payload. 449 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; 450 int payloadBytesInPacket = 0; 451 int packetStartPartition = 452 packetizer.NextPacket(&dataBuffer[rtpHeaderLength], 453 &payloadBytesInPacket, &last); 454 // TODO(holmer): Temporarily disable first partition packet counting 455 // to avoid a bug in ProducerFec which doesn't properly handle 456 // important packets. 457 // if (packetStartPartition == 0) 458 // { 459 // ++_numberFirstPartition; 460 // } 461 // else 462 if (packetStartPartition < 0) 463 { 464 return -1; 465 } 466 467 // Write RTP header. 468 // Set marker bit true if this is the last packet in frame. 469 _rtpSender.BuildRTPheader(dataBuffer, payloadType, last, 470 captureTimeStamp, capture_time_ms); 471 if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket, 472 rtpHeaderLength, captureTimeStamp, 473 capture_time_ms, storage, protect)) 474 { 475 LOG(LS_WARNING) 476 << "RTPSenderVideo::SendVP8 failed to send packet number " 477 << _rtpSender.SequenceNumber(); 478 } 479 } 480 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, 481 "timestamp", _rtpSender.Timestamp()); 482 return 0; 483 } 484 485 void RTPSenderVideo::ProcessBitrate() { 486 _videoBitrate.Process(); 487 _fecOverheadRate.Process(); 488 } 489 490 uint32_t RTPSenderVideo::VideoBitrateSent() const { 491 return _videoBitrate.BitrateLast(); 492 } 493 494 uint32_t RTPSenderVideo::FecOverheadRate() const { 495 return _fecOverheadRate.BitrateLast(); 496 } 497 498 int RTPSenderVideo::SelectiveRetransmissions() const { 499 return _retransmissionSettings; 500 } 501 502 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { 503 _retransmissionSettings = settings; 504 return 0; 505 } 506 507 } // namespace webrtc 508