2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
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"
27 enum { REDForFECHeaderLength = 1 };
30 uint16_t rtpHeaderLength;
31 ForwardErrorCorrection::Packet* pkt;
34 RTPSenderVideo::RTPSenderVideo(Clock* clock,
35 RTPSenderInterface* rtpSender)
36 : _rtpSender(*rtpSender),
37 _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
38 _videoType(kRtpVideoGeneric),
39 _videoCodecInformation(NULL),
41 _retransmissionSettings(kRetransmitBaseLayer),
48 _numberFirstPartition(0),
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 =
61 RTPSenderVideo::~RTPSenderVideo()
63 if(_videoCodecInformation)
65 delete _videoCodecInformation;
67 delete _sendVideoCritsect;
71 RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType)
73 CriticalSectionScoped cs(_sendVideoCritsect);
74 _videoType = videoType;
78 RTPSenderVideo::VideoCodecType() const
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);
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;
96 videoType = kRtpVideoGeneric;
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;
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,
117 int fec_overhead_sent = 0;
120 RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer,
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(
130 red_packet->length() - rtp_header_length,
134 PacedSender::kNormalPriority);
136 ret |= packet_success;
138 if (packet_success == 0) {
139 video_sent += red_packet->length();
145 ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer,
152 while (producer_fec_.FecAvailable()) {
153 red_packet = producer_fec_.GetFecPacket(
156 _rtpSender.IncrementSequenceNumber(),
158 StorageType storage = kDontRetransmit;
159 if (_retransmissionSettings & kRetransmitFECPackets) {
160 storage = kAllowRetransmission;
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(
168 red_packet->length() - rtp_header_length,
172 PacedSender::kNormalPriority);
174 ret |= packet_success;
176 if (packet_success == 0) {
177 fec_overhead_sent += red_packet->length();
182 _videoBitrate.Update(video_sent);
183 _fecOverheadRate.Update(fec_overhead_sent);
186 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal",
187 "timestamp", capture_timestamp,
188 "seqnum", _rtpSender.SequenceNumber());
189 int ret = _rtpSender.SendToNetwork(data_buffer,
194 PacedSender::kNormalPriority);
196 _videoBitrate.Update(payload_length + rtp_header_length);
202 RTPSenderVideo::SendRTPIntraRequest()
205 // 5.2.1. Full intra-frame Request (FIR) packet
212 data[3] = 1; // length
214 ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC());
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);
224 RTPSenderVideo::SetGenericFECStatus(const bool enable,
225 const uint8_t payloadTypeRED,
226 const uint8_t payloadTypeFEC)
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 =
240 RTPSenderVideo::GenericFECStatus(bool& enable,
241 uint8_t& payloadTypeRED,
242 uint8_t& payloadTypeFEC) const
244 enable = _fecEnabled;
245 payloadTypeRED = _payloadTypeRED;
246 payloadTypeFEC = _payloadTypeFEC;
251 RTPSenderVideo::FECPacketOverhead() const
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);
266 int32_t RTPSenderVideo::SetFecParameters(
267 const FecProtectionParams* delta_params,
268 const FecProtectionParams* key_params) {
269 assert(delta_params);
271 delta_fec_params_ = *delta_params;
272 key_fec_params_ = *key_params;
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)
288 if( payloadSize == 0)
293 if (frameType == kVideoFrameKey) {
294 producer_fec_.SetFecParameters(&key_fec_params_,
295 _numberFirstPartition);
297 producer_fec_.SetFecParameters(&delta_fec_params_,
298 _numberFirstPartition);
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;
308 case kRtpVideoGeneric:
309 retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
310 capture_time_ms, payloadData, payloadSize);
313 retVal = SendVP8(frameType,
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,
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 */);
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);
349 // Fragment packet into packets of max MaxPayloadLength bytes payload.
350 uint8_t buffer[IP_PACKET_SIZE];
352 uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit;
353 if (frame_type == kVideoFrameKey) {
354 generic_header |= RtpFormatVideoGeneric::kKeyFrameBit;
358 if (size < payload_length) {
359 payload_length = size;
361 size -= payload_length;
363 // MarkerBit is 1 on final packet (bytes_to_send == 0)
364 if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
366 capture_time_ms) != rtp_header_length) {
370 uint8_t* out_ptr = &buffer[rtp_header_length];
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;
377 // Put payload in packet
378 memcpy(out_ptr, payload, payload_length);
379 payload += payload_length;
381 if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length,
382 capture_timestamp, capture_time_ms,
383 kAllowRetransmission, true)) {
390 VideoCodecInformation*
391 RTPSenderVideo::CodecInformationVideo()
393 return _videoCodecInformation;
397 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)
399 _maxBitrate = maxBitrate;
403 RTPSenderVideo::MaxConfiguredBitrateVideo() const
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)
418 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
420 int32_t payloadBytesToSend = payloadSize;
421 const uint8_t* data = payloadData;
423 uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength();
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);
431 StorageType storage = kAllowRetransmission;
432 if (rtpTypeHdr->VP8.temporalIdx == 0 &&
433 !(_retransmissionSettings & kRetransmitBaseLayer)) {
434 storage = kDontRetransmit;
436 if (rtpTypeHdr->VP8.temporalIdx > 0 &&
437 !(_retransmissionSettings & kRetransmitHigherLayers)) {
438 storage = kDontRetransmit;
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);
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)
459 // ++_numberFirstPartition;
462 if (packetStartPartition < 0)
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))
476 << "RTPSenderVideo::SendVP8 failed to send packet number "
477 << _rtpSender.SequenceNumber();
480 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
481 "timestamp", _rtpSender.Timestamp());
485 void RTPSenderVideo::ProcessBitrate() {
486 _videoBitrate.Process();
487 _fecOverheadRate.Process();
490 uint32_t RTPSenderVideo::VideoBitrateSent() const {
491 return _videoBitrate.BitrateLast();
494 uint32_t RTPSenderVideo::FecOverheadRate() const {
495 return _fecOverheadRate.BitrateLast();
498 int RTPSenderVideo::SelectiveRetransmissions() const {
499 return _retransmissionSettings;
502 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
503 _retransmissionSettings = settings;
507 } // namespace webrtc