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/source/producer_fec.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
19 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
21 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22 #include "webrtc/system_wrappers/interface/trace.h"
23 #include "webrtc/system_wrappers/interface/trace_event.h"
26 enum { REDForFECHeaderLength = 1 };
29 uint16_t rtpHeaderLength;
30 ForwardErrorCorrection::Packet* pkt;
33 RTPSenderVideo::RTPSenderVideo(const int32_t id,
35 RTPSenderInterface* rtpSender) :
37 _rtpSender(*rtpSender),
38 _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
40 _videoType(kRtpVideoGeneric),
41 _videoCodecInformation(NULL),
43 _retransmissionSettings(kRetransmitBaseLayer),
50 _numberFirstPartition(0),
54 _fecOverheadRate(clock),
55 _videoBitrate(clock) {
56 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
57 memset(&key_fec_params_, 0, sizeof(key_fec_params_));
58 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
59 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
63 RTPSenderVideo::~RTPSenderVideo()
65 if(_videoCodecInformation)
67 delete _videoCodecInformation;
69 delete _sendVideoCritsect;
73 RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType)
75 CriticalSectionScoped cs(_sendVideoCritsect);
76 _videoType = videoType;
80 RTPSenderVideo::VideoCodecType() const
85 int32_t RTPSenderVideo::RegisterVideoPayload(
86 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
87 const int8_t payloadType,
88 const uint32_t maxBitRate,
89 ModuleRTPUtility::Payload*& payload) {
90 CriticalSectionScoped cs(_sendVideoCritsect);
92 RtpVideoCodecTypes videoType = kRtpVideoGeneric;
93 if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
94 videoType = kRtpVideoVp8;
95 } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
96 videoType = kRtpVideoGeneric;
98 videoType = kRtpVideoGeneric;
100 payload = new ModuleRTPUtility::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 ModuleRTPUtility::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 return ForwardErrorCorrection::PacketOverhead() +
258 REDForFECHeaderLength;
263 int32_t RTPSenderVideo::SetFecParameters(
264 const FecProtectionParams* delta_params,
265 const FecProtectionParams* key_params) {
266 assert(delta_params);
268 delta_fec_params_ = *delta_params;
269 key_fec_params_ = *key_params;
274 RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
275 const FrameType frameType,
276 const int8_t payloadType,
277 const uint32_t captureTimeStamp,
278 int64_t capture_time_ms,
279 const uint8_t* payloadData,
280 const uint32_t payloadSize,
281 const RTPFragmentationHeader* fragmentation,
282 VideoCodecInformation* codecInfo,
283 const RTPVideoTypeHeader* rtpTypeHdr)
285 if( payloadSize == 0)
290 if (frameType == kVideoFrameKey) {
291 producer_fec_.SetFecParameters(&key_fec_params_,
292 _numberFirstPartition);
294 producer_fec_.SetFecParameters(&delta_fec_params_,
295 _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;
305 case kRtpVideoGeneric:
306 retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
307 capture_time_ms, payloadData, payloadSize);
310 retVal = SendVP8(frameType,
327 WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, _id, "%s(timestamp:%u)",
328 __FUNCTION__, captureTimeStamp);
332 int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type,
333 const int8_t payload_type,
334 const uint32_t capture_timestamp,
335 int64_t capture_time_ms,
336 const uint8_t* payload,
338 assert(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta);
339 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength();
340 uint16_t max_length = _rtpSender.MaxPayloadLength() - FECPacketOverhead() -
341 rtp_header_length - (1 /* generic header length */);
343 // Fragment packets more evenly by splitting the payload up evenly.
344 uint32_t num_packets = (size + max_length - 1) / max_length;
345 uint32_t payload_length = (size + num_packets - 1) / num_packets;
346 assert(payload_length <= max_length);
348 // Fragment packet into packets of max MaxPayloadLength bytes payload.
349 uint8_t buffer[IP_PACKET_SIZE];
351 uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit;
352 if (frame_type == kVideoFrameKey) {
353 generic_header |= RtpFormatVideoGeneric::kKeyFrameBit;
357 if (size < payload_length) {
358 payload_length = size;
360 size -= payload_length;
362 // MarkerBit is 1 on final packet (bytes_to_send == 0)
363 if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
365 capture_time_ms) != rtp_header_length) {
369 uint8_t* out_ptr = &buffer[rtp_header_length];
371 // Put generic header in packet
372 *out_ptr++ = generic_header;
373 // Remove first-packet bit, following packets are intermediate
374 generic_header &= ~RtpFormatVideoGeneric::kFirstPacketBit;
376 // Put payload in packet
377 memcpy(out_ptr, payload, payload_length);
378 payload += payload_length;
380 if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length,
381 capture_timestamp, capture_time_ms,
382 kAllowRetransmission, true)) {
389 VideoCodecInformation*
390 RTPSenderVideo::CodecInformationVideo()
392 return _videoCodecInformation;
396 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)
398 _maxBitrate = maxBitrate;
402 RTPSenderVideo::MaxConfiguredBitrateVideo() const
408 RTPSenderVideo::SendVP8(const FrameType frameType,
409 const int8_t payloadType,
410 const uint32_t captureTimeStamp,
411 int64_t capture_time_ms,
412 const uint8_t* payloadData,
413 const uint32_t payloadSize,
414 const RTPFragmentationHeader* fragmentation,
415 const RTPVideoTypeHeader* rtpTypeHdr)
417 const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
419 int32_t payloadBytesToSend = payloadSize;
420 const uint8_t* data = payloadData;
422 uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength();
425 // Initialize disregarding partition boundaries: this will use kEqualSize
426 // packetization mode, which produces ~equal size packets for each frame.
427 RtpFormatVp8 packetizer(data, payloadBytesToSend, rtpTypeHdr->VP8,
428 maxPayloadLengthVP8);
430 StorageType storage = kAllowRetransmission;
431 if (rtpTypeHdr->VP8.temporalIdx == 0 &&
432 !(_retransmissionSettings & kRetransmitBaseLayer)) {
433 storage = kDontRetransmit;
435 if (rtpTypeHdr->VP8.temporalIdx > 0 &&
436 !(_retransmissionSettings & kRetransmitHigherLayers)) {
437 storage = kDontRetransmit;
441 _numberFirstPartition = 0;
442 // |rtpTypeHdr->VP8.temporalIdx| is zero for base layers, or -1 if the field
443 // isn't used. We currently only protect base layers.
444 bool protect = (rtpTypeHdr->VP8.temporalIdx < 1);
447 // Write VP8 Payload Descriptor and VP8 payload.
448 uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
449 int payloadBytesInPacket = 0;
450 int packetStartPartition =
451 packetizer.NextPacket(&dataBuffer[rtpHeaderLength],
452 &payloadBytesInPacket, &last);
453 // TODO(holmer): Temporarily disable first partition packet counting
454 // to avoid a bug in ProducerFec which doesn't properly handle
455 // important packets.
456 // if (packetStartPartition == 0)
458 // ++_numberFirstPartition;
461 if (packetStartPartition < 0)
467 // Set marker bit true if this is the last packet in frame.
468 _rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
469 captureTimeStamp, capture_time_ms);
470 if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket,
471 rtpHeaderLength, captureTimeStamp,
472 capture_time_ms, storage, protect))
474 WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
475 "RTPSenderVideo::SendVP8 failed to send packet number"
476 " %d", _rtpSender.SequenceNumber());
479 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
480 "timestamp", _rtpSender.Timestamp());
484 void RTPSenderVideo::ProcessBitrate() {
485 _videoBitrate.Process();
486 _fecOverheadRate.Process();
489 uint32_t RTPSenderVideo::VideoBitrateSent() const {
490 return _videoBitrate.BitrateLast();
493 uint32_t RTPSenderVideo::FecOverheadRate() const {
494 return _fecOverheadRate.BitrateLast();
497 int RTPSenderVideo::SelectiveRetransmissions() const {
498 return _retransmissionSettings;
501 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
502 _retransmissionSettings = settings;
506 } // namespace webrtc