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 <stdlib.h> 14#include <string.h> 15 16#include <vector> 17 18#include "webrtc/base/checks.h" 19#include "webrtc/base/logging.h" 20#include "webrtc/base/trace_event.h" 21#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 22#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 23#include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 24#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" 25#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" 26#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" 27#include "webrtc/system_wrappers/include/critical_section_wrapper.h" 28 29namespace webrtc { 30enum { REDForFECHeaderLength = 1 }; 31 32struct RtpPacket { 33 uint16_t rtpHeaderLength; 34 ForwardErrorCorrection::Packet* pkt; 35}; 36 37RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender) 38 : _rtpSender(*rtpSender), 39 crit_(CriticalSectionWrapper::CreateCriticalSection()), 40 _videoType(kRtpVideoGeneric), 41 _maxBitrate(0), 42 _retransmissionSettings(kRetransmitBaseLayer), 43 44 // Generic FEC 45 fec_(), 46 fec_enabled_(false), 47 red_payload_type_(-1), 48 fec_payload_type_(-1), 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 61RTPSenderVideo::~RTPSenderVideo() { 62} 63 64void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) { 65 _videoType = videoType; 66} 67 68RtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const { 69 return _videoType; 70} 71 72// Static. 73RtpUtility::Payload* RTPSenderVideo::CreateVideoPayload( 74 const char payloadName[RTP_PAYLOAD_NAME_SIZE], 75 const int8_t payloadType, 76 const uint32_t maxBitRate) { 77 RtpVideoCodecTypes videoType = kRtpVideoGeneric; 78 if (RtpUtility::StringCompare(payloadName, "VP8", 3)) { 79 videoType = kRtpVideoVp8; 80 } else if (RtpUtility::StringCompare(payloadName, "VP9", 3)) { 81 videoType = kRtpVideoVp9; 82 } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) { 83 videoType = kRtpVideoH264; 84 } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) { 85 videoType = kRtpVideoGeneric; 86 } else { 87 videoType = kRtpVideoGeneric; 88 } 89 RtpUtility::Payload* payload = new RtpUtility::Payload(); 90 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; 91 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 92 payload->typeSpecific.Video.videoCodecType = videoType; 93 payload->typeSpecific.Video.maxRate = maxBitRate; 94 payload->audio = false; 95 return payload; 96} 97 98void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, 99 const size_t payload_length, 100 const size_t rtp_header_length, 101 uint16_t seq_num, 102 const uint32_t capture_timestamp, 103 int64_t capture_time_ms, 104 StorageType storage) { 105 if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length, 106 capture_time_ms, storage, 107 RtpPacketSender::kLowPriority) == 0) { 108 _videoBitrate.Update(payload_length + rtp_header_length); 109 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), 110 "Video::PacketNormal", "timestamp", capture_timestamp, 111 "seqnum", seq_num); 112 } else { 113 LOG(LS_WARNING) << "Failed to send video packet " << seq_num; 114 } 115} 116 117void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, 118 const size_t payload_length, 119 const size_t rtp_header_length, 120 uint16_t media_seq_num, 121 const uint32_t capture_timestamp, 122 int64_t capture_time_ms, 123 StorageType media_packet_storage, 124 bool protect) { 125 rtc::scoped_ptr<RedPacket> red_packet; 126 std::vector<RedPacket*> fec_packets; 127 StorageType fec_storage = kDontRetransmit; 128 uint16_t next_fec_sequence_number = 0; 129 { 130 // Only protect while creating RED and FEC packets, not when sending. 131 CriticalSectionScoped cs(crit_.get()); 132 red_packet.reset(producer_fec_.BuildRedPacket( 133 data_buffer, payload_length, rtp_header_length, red_payload_type_)); 134 if (protect) { 135 producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length, 136 rtp_header_length); 137 } 138 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets(); 139 if (num_fec_packets > 0) { 140 next_fec_sequence_number = 141 _rtpSender.AllocateSequenceNumber(num_fec_packets); 142 fec_packets = producer_fec_.GetFecPackets( 143 red_payload_type_, fec_payload_type_, next_fec_sequence_number, 144 rtp_header_length); 145 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); 146 if (_retransmissionSettings & kRetransmitFECPackets) 147 fec_storage = kAllowRetransmission; 148 } 149 } 150 if (_rtpSender.SendToNetwork( 151 red_packet->data(), red_packet->length() - rtp_header_length, 152 rtp_header_length, capture_time_ms, media_packet_storage, 153 RtpPacketSender::kLowPriority) == 0) { 154 _videoBitrate.Update(red_packet->length()); 155 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), 156 "Video::PacketRed", "timestamp", capture_timestamp, 157 "seqnum", media_seq_num); 158 } else { 159 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num; 160 } 161 for (RedPacket* fec_packet : fec_packets) { 162 if (_rtpSender.SendToNetwork( 163 fec_packet->data(), fec_packet->length() - rtp_header_length, 164 rtp_header_length, capture_time_ms, fec_storage, 165 RtpPacketSender::kLowPriority) == 0) { 166 _fecOverheadRate.Update(fec_packet->length()); 167 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), 168 "Video::PacketFec", "timestamp", capture_timestamp, 169 "seqnum", next_fec_sequence_number); 170 } else { 171 LOG(LS_WARNING) << "Failed to send FEC packet " 172 << next_fec_sequence_number; 173 } 174 delete fec_packet; 175 ++next_fec_sequence_number; 176 } 177} 178 179void RTPSenderVideo::SetGenericFECStatus(const bool enable, 180 const uint8_t payloadTypeRED, 181 const uint8_t payloadTypeFEC) { 182 CriticalSectionScoped cs(crit_.get()); 183 fec_enabled_ = enable; 184 red_payload_type_ = payloadTypeRED; 185 fec_payload_type_ = payloadTypeFEC; 186 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 187 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 188 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; 189 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = 190 kFecMaskRandom; 191} 192 193void RTPSenderVideo::GenericFECStatus(bool* enable, 194 uint8_t* payloadTypeRED, 195 uint8_t* payloadTypeFEC) const { 196 CriticalSectionScoped cs(crit_.get()); 197 *enable = fec_enabled_; 198 *payloadTypeRED = red_payload_type_; 199 *payloadTypeFEC = fec_payload_type_; 200} 201 202size_t RTPSenderVideo::FECPacketOverhead() const { 203 CriticalSectionScoped cs(crit_.get()); 204 if (fec_enabled_) { 205 // Overhead is FEC headers plus RED for FEC header plus anything in RTP 206 // header beyond the 12 bytes base header (CSRC list, extensions...) 207 // This reason for the header extensions to be included here is that 208 // from an FEC viewpoint, they are part of the payload to be protected. 209 // (The base RTP header is already protected by the FEC header.) 210 return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength + 211 (_rtpSender.RTPHeaderLength() - kRtpHeaderSize); 212 } 213 return 0; 214} 215 216void RTPSenderVideo::SetFecParameters(const FecProtectionParams* delta_params, 217 const FecProtectionParams* key_params) { 218 CriticalSectionScoped cs(crit_.get()); 219 RTC_DCHECK(delta_params); 220 RTC_DCHECK(key_params); 221 delta_fec_params_ = *delta_params; 222 key_fec_params_ = *key_params; 223} 224 225int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, 226 const FrameType frameType, 227 const int8_t payloadType, 228 const uint32_t captureTimeStamp, 229 int64_t capture_time_ms, 230 const uint8_t* payloadData, 231 const size_t payloadSize, 232 const RTPFragmentationHeader* fragmentation, 233 const RTPVideoHeader* rtpHdr) { 234 if (payloadSize == 0) { 235 return -1; 236 } 237 238 rtc::scoped_ptr<RtpPacketizer> packetizer( 239 RtpPacketizer::Create(videoType, _rtpSender.MaxDataPayloadLength(), 240 &(rtpHdr->codecHeader), frameType)); 241 242 StorageType storage; 243 bool fec_enabled; 244 { 245 CriticalSectionScoped cs(crit_.get()); 246 FecProtectionParams* fec_params = 247 frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; 248 producer_fec_.SetFecParameters(fec_params, 0); 249 storage = packetizer->GetStorageType(_retransmissionSettings); 250 fec_enabled = fec_enabled_; 251 } 252 253 // Register CVO rtp header extension at the first time when we receive a frame 254 // with pending rotation. 255 RTPSenderInterface::CVOMode cvo_mode = RTPSenderInterface::kCVONone; 256 if (rtpHdr && rtpHdr->rotation != kVideoRotation_0) { 257 cvo_mode = _rtpSender.ActivateCVORtpHeaderExtension(); 258 } 259 260 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); 261 size_t payload_bytes_to_send = payloadSize; 262 const uint8_t* data = payloadData; 263 264 // TODO(changbin): we currently don't support to configure the codec to 265 // output multiple partitions for VP8. Should remove below check after the 266 // issue is fixed. 267 const RTPFragmentationHeader* frag = 268 (videoType == kRtpVideoVp8) ? NULL : fragmentation; 269 270 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); 271 272 bool last = false; 273 while (!last) { 274 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; 275 size_t payload_bytes_in_packet = 0; 276 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length], 277 &payload_bytes_in_packet, &last)) { 278 return -1; 279 } 280 // Write RTP header. 281 // Set marker bit true if this is the last packet in frame. 282 _rtpSender.BuildRTPheader( 283 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms); 284 // According to 285 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ 286 // ts_126114v120700p.pdf Section 7.4.5: 287 // The MTSI client shall add the payload bytes as defined in this clause 288 // onto the last RTP packet in each group of packets which make up a key 289 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 290 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP 291 // packet in each group of packets which make up another type of frame 292 // (e.g. a P-Frame) only if the current value is different from the previous 293 // value sent. 294 // Here we are adding it to every packet of every frame at this point. 295 if (!rtpHdr) { 296 RTC_DCHECK(!_rtpSender.IsRtpHeaderExtensionRegistered( 297 kRtpExtensionVideoRotation)); 298 } else if (cvo_mode == RTPSenderInterface::kCVOActivated) { 299 // Checking whether CVO header extension is registered will require taking 300 // a lock. It'll be a no-op if it's not registered. 301 // TODO(guoweis): For now, all packets sent will carry the CVO such that 302 // the RTP header length is consistent, although the receiver side will 303 // only exam the packets with marker bit set. 304 size_t packetSize = payloadSize + rtp_header_length; 305 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); 306 RTPHeader rtp_header; 307 rtp_parser.Parse(&rtp_header); 308 _rtpSender.UpdateVideoRotation(dataBuffer, packetSize, rtp_header, 309 rtpHdr->rotation); 310 } 311 if (fec_enabled) { 312 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet, 313 rtp_header_length, _rtpSender.SequenceNumber(), 314 captureTimeStamp, capture_time_ms, storage, 315 packetizer->GetProtectionType() == kProtectedPacket); 316 } else { 317 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length, 318 _rtpSender.SequenceNumber(), captureTimeStamp, 319 capture_time_ms, storage); 320 } 321 } 322 323 TRACE_EVENT_ASYNC_END1( 324 "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp()); 325 return 0; 326} 327 328void RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) { 329 _maxBitrate = maxBitrate; 330} 331 332uint32_t RTPSenderVideo::MaxConfiguredBitrateVideo() const { 333 return _maxBitrate; 334} 335 336void RTPSenderVideo::ProcessBitrate() { 337 _videoBitrate.Process(); 338 _fecOverheadRate.Process(); 339} 340 341uint32_t RTPSenderVideo::VideoBitrateSent() const { 342 return _videoBitrate.BitrateLast(); 343} 344 345uint32_t RTPSenderVideo::FecOverheadRate() const { 346 return _fecOverheadRate.BitrateLast(); 347} 348 349int RTPSenderVideo::SelectiveRetransmissions() const { 350 CriticalSectionScoped cs(crit_.get()); 351 return _retransmissionSettings; 352} 353 354void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { 355 CriticalSectionScoped cs(crit_.get()); 356 _retransmissionSettings = settings; 357} 358 359} // namespace webrtc 360