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 RtpUtility::Payload*& payload) {
88 CriticalSectionScoped cs(_sendVideoCritsect);
90 RtpVideoCodecTypes videoType = kRtpVideoGeneric;
91 if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
92 videoType = kRtpVideoVp8;
93 } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
94 videoType = kRtpVideoH264;
95 } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
96 videoType = kRtpVideoGeneric;
98 videoType = kRtpVideoGeneric;
100 payload = new RtpUtility::Payload;
101 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
102 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
103 payload->typeSpecific.Video.videoCodecType = videoType;
104 payload->typeSpecific.Video.maxRate = maxBitRate;
105 payload->audio = false;
110 RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer,
111 const uint16_t payload_length,
112 const uint16_t rtp_header_length,
113 const uint32_t capture_timestamp,
114 int64_t capture_time_ms,
119 int fec_overhead_sent = 0;
122 RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer,
126 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketRed",
127 "timestamp", capture_timestamp,
128 "seqnum", _rtpSender.SequenceNumber());
129 // Sending the media packet with RED header.
130 int packet_success = _rtpSender.SendToNetwork(
132 red_packet->length() - rtp_header_length,
136 PacedSender::kNormalPriority);
138 ret |= packet_success;
140 if (packet_success == 0) {
141 video_sent += red_packet->length();
147 ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer,
154 while (producer_fec_.FecAvailable()) {
155 red_packet = producer_fec_.GetFecPacket(
158 _rtpSender.IncrementSequenceNumber(),
160 StorageType storage = kDontRetransmit;
161 if (_retransmissionSettings & kRetransmitFECPackets) {
162 storage = kAllowRetransmission;
164 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketFec",
165 "timestamp", capture_timestamp,
166 "seqnum", _rtpSender.SequenceNumber());
167 // Sending FEC packet with RED header.
168 int packet_success = _rtpSender.SendToNetwork(
170 red_packet->length() - rtp_header_length,
174 PacedSender::kNormalPriority);
176 ret |= packet_success;
178 if (packet_success == 0) {
179 fec_overhead_sent += red_packet->length();
184 _videoBitrate.Update(video_sent);
185 _fecOverheadRate.Update(fec_overhead_sent);
188 TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal",
189 "timestamp", capture_timestamp,
190 "seqnum", _rtpSender.SequenceNumber());
191 int ret = _rtpSender.SendToNetwork(data_buffer,
196 PacedSender::kNormalPriority);
198 _videoBitrate.Update(payload_length + rtp_header_length);
204 RTPSenderVideo::SendRTPIntraRequest()
207 // 5.2.1. Full intra-frame Request (FIR) packet
214 data[3] = 1; // length
216 RtpUtility::AssignUWord32ToBuffer(data + 4, _rtpSender.SSRC());
218 TRACE_EVENT_INSTANT1("webrtc_rtp",
219 "Video::IntraRequest",
220 "seqnum", _rtpSender.SequenceNumber());
221 return _rtpSender.SendToNetwork(data, 0, length, -1, kDontStore,
222 PacedSender::kNormalPriority);
226 RTPSenderVideo::SetGenericFECStatus(const bool enable,
227 const uint8_t payloadTypeRED,
228 const uint8_t payloadTypeFEC)
230 _fecEnabled = enable;
231 _payloadTypeRED = payloadTypeRED;
232 _payloadTypeFEC = payloadTypeFEC;
233 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
234 memset(&key_fec_params_, 0, sizeof(key_fec_params_));
235 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
236 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
242 RTPSenderVideo::GenericFECStatus(bool& enable,
243 uint8_t& payloadTypeRED,
244 uint8_t& payloadTypeFEC) const
246 enable = _fecEnabled;
247 payloadTypeRED = _payloadTypeRED;
248 payloadTypeFEC = _payloadTypeFEC;
253 RTPSenderVideo::FECPacketOverhead() const
257 // Overhead is FEC headers plus RED for FEC header plus anything in RTP
258 // header beyond the 12 bytes base header (CSRC list, extensions...)
259 // This reason for the header extensions to be included here is that
260 // from an FEC viewpoint, they are part of the payload to be protected.
261 // (The base RTP header is already protected by the FEC header.)
262 return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength +
263 (_rtpSender.RTPHeaderLength() - kRtpHeaderSize);
268 int32_t RTPSenderVideo::SetFecParameters(
269 const FecProtectionParams* delta_params,
270 const FecProtectionParams* key_params) {
271 assert(delta_params);
273 delta_fec_params_ = *delta_params;
274 key_fec_params_ = *key_params;
278 int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
279 const FrameType frameType,
280 const int8_t payloadType,
281 const uint32_t captureTimeStamp,
282 int64_t capture_time_ms,
283 const uint8_t* payloadData,
284 const uint32_t payloadSize,
285 const RTPFragmentationHeader* fragmentation,
286 VideoCodecInformation* codecInfo,
287 const RTPVideoTypeHeader* rtpTypeHdr) {
288 if (payloadSize == 0) {
292 if (frameType == kVideoFrameKey) {
293 producer_fec_.SetFecParameters(&key_fec_params_, _numberFirstPartition);
295 producer_fec_.SetFecParameters(&delta_fec_params_, _numberFirstPartition);
298 // Default setting for number of first partition packets:
299 // Will be extracted in SendVP8 for VP8 codec; other codecs use 0
300 _numberFirstPartition = 0;
303 case kRtpVideoGeneric:
304 return SendGeneric(frameType,
311 return SendVP8(frameType,
320 return SendH264(frameType,
337 int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type,
338 const int8_t payload_type,
339 const uint32_t capture_timestamp,
340 int64_t capture_time_ms,
341 const uint8_t* payload,
343 assert(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta);
344 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength();
345 uint16_t max_length = _rtpSender.MaxPayloadLength() - FECPacketOverhead() -
346 rtp_header_length - (1 /* generic header length */);
348 // Fragment packets more evenly by splitting the payload up evenly.
349 uint32_t num_packets = (size + max_length - 1) / max_length;
350 uint32_t payload_length = (size + num_packets - 1) / num_packets;
351 assert(payload_length <= max_length);
353 // Fragment packet into packets of max MaxPayloadLength bytes payload.
354 uint8_t buffer[IP_PACKET_SIZE];
356 uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit;
357 if (frame_type == kVideoFrameKey) {
358 generic_header |= RtpFormatVideoGeneric::kKeyFrameBit;
362 if (size < payload_length) {
363 payload_length = size;
365 size -= payload_length;
367 // MarkerBit is 1 on final packet (bytes_to_send == 0)
368 if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
370 capture_time_ms) != rtp_header_length) {
374 uint8_t* out_ptr = &buffer[rtp_header_length];
376 // Put generic header in packet
377 *out_ptr++ = generic_header;
378 // Remove first-packet bit, following packets are intermediate
379 generic_header &= ~RtpFormatVideoGeneric::kFirstPacketBit;
381 // Put payload in packet
382 memcpy(out_ptr, payload, payload_length);
383 payload += payload_length;
385 if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length,
386 capture_timestamp, capture_time_ms,
387 kAllowRetransmission, true)) {
394 VideoCodecInformation*
395 RTPSenderVideo::CodecInformationVideo()
397 return _videoCodecInformation;
401 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)
403 _maxBitrate = maxBitrate;
407 RTPSenderVideo::MaxConfiguredBitrateVideo() const
413 RTPSenderVideo::SendVP8(const FrameType frameType,
414 const int8_t payloadType,
415 const uint32_t captureTimeStamp,
416 int64_t capture_time_ms,
417 const uint8_t* payloadData,
418 const uint32_t payloadSize,
419 const RTPFragmentationHeader* fragmentation,
420 const RTPVideoTypeHeader* rtpTypeHdr)
422 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
424 int32_t payloadBytesToSend = payloadSize;
425 const uint8_t* data = payloadData;
427 uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength();
430 // Initialize disregarding partition boundaries: this will use kEqualSize
431 // packetization mode, which produces ~equal size packets for each frame.
432 RtpPacketizerVp8 packetizer(rtpTypeHdr->VP8, maxPayloadLengthVP8);
433 packetizer.SetPayloadData(data, payloadBytesToSend, NULL);
435 StorageType storage = kAllowRetransmission;
436 if (rtpTypeHdr->VP8.temporalIdx == 0 &&
437 !(_retransmissionSettings & kRetransmitBaseLayer)) {
438 storage = kDontRetransmit;
439 } else if (rtpTypeHdr->VP8.temporalIdx != kNoTemporalIdx &&
440 rtpTypeHdr->VP8.temporalIdx > 0 &&
441 !(_retransmissionSettings & kRetransmitHigherLayers)) {
442 storage = kDontRetransmit;
446 _numberFirstPartition = 0;
447 // |rtpTypeHdr->VP8.temporalIdx| is zero for base layers, or kNoTemporalIdx
448 // if the field isn't used (so all layers are the base layer). We currently
449 // only protect base layers, so look for these two cases.
450 bool protect = rtpTypeHdr->VP8.temporalIdx == 0 ||
451 rtpTypeHdr->VP8.temporalIdx == kNoTemporalIdx;
454 // Write VP8 Payload Descriptor and VP8 payload.
455 uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
456 size_t payloadBytesInPacket = 0;
457 if (!packetizer.NextPacket(
458 &dataBuffer[rtpHeaderLength], &payloadBytesInPacket, &last))
462 // Set marker bit true if this is the last packet in frame.
463 _rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
464 captureTimeStamp, capture_time_ms);
465 if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket,
466 rtpHeaderLength, captureTimeStamp,
467 capture_time_ms, storage, protect))
470 << "RTPSenderVideo::SendVP8 failed to send packet number "
471 << _rtpSender.SequenceNumber();
474 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
475 "timestamp", _rtpSender.Timestamp());
479 bool RTPSenderVideo::SendH264(const FrameType frameType,
480 const int8_t payloadType,
481 const uint32_t captureTimeStamp,
482 int64_t capture_time_ms,
483 const uint8_t* payloadData,
484 const uint32_t payloadSize,
485 const RTPFragmentationHeader* fragmentation,
486 const RTPVideoTypeHeader* rtpTypeHdr) {
487 size_t rtp_header_length = _rtpSender.RTPHeaderLength();
488 int32_t payload_bytes_to_send = payloadSize;
489 const uint8_t* data = payloadData;
490 size_t max_payload_length = _rtpSender.MaxDataPayloadLength();
492 scoped_ptr<RtpPacketizer> packetizer(
493 RtpPacketizer::Create(kRtpVideoH264, max_payload_length));
494 packetizer->SetPayloadData(data, payload_bytes_to_send, fragmentation);
496 StorageType storage = kAllowRetransmission;
497 bool protect = (frameType == kVideoFrameKey);
501 // Write H264 payload.
502 uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
503 size_t payload_bytes_in_packet = 0;
504 if (!packetizer->NextPacket(
505 &dataBuffer[rtp_header_length], &payload_bytes_in_packet, &last)) {
510 // Set marker bit true if this is the last packet in frame.
511 _rtpSender.BuildRTPheader(
512 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms);
513 if (SendVideoPacket(dataBuffer,
514 payload_bytes_in_packet,
521 << "RTPSenderVideo::SendH264 failed to send packet number "
522 << _rtpSender.SequenceNumber();
528 void RTPSenderVideo::ProcessBitrate() {
529 _videoBitrate.Process();
530 _fecOverheadRate.Process();
533 uint32_t RTPSenderVideo::VideoBitrateSent() const {
534 return _videoBitrate.BitrateLast();
537 uint32_t RTPSenderVideo::FecOverheadRate() const {
538 return _fecOverheadRate.BitrateLast();
541 int RTPSenderVideo::SelectiveRetransmissions() const {
542 return _retransmissionSettings;
545 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
546 _retransmissionSettings = settings;
550 } // namespace webrtc