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
RTPSenderVideo(Clock * clock,RTPSenderInterface * rtpSender)34 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender)
35 : _rtpSender(*rtpSender),
36 _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
37 _videoType(kRtpVideoGeneric),
38 _videoCodecInformation(NULL),
39 _maxBitrate(0),
40 _retransmissionSettings(kRetransmitBaseLayer),
41
42 // Generic FEC
43 _fec(),
44 _fecEnabled(false),
45 _payloadTypeRED(-1),
46 _payloadTypeFEC(-1),
47 _numberFirstPartition(0),
48 delta_fec_params_(),
49 key_fec_params_(),
50 producer_fec_(&_fec),
51 _fecOverheadRate(clock, NULL),
52 _videoBitrate(clock, NULL) {
53 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
54 memset(&key_fec_params_, 0, sizeof(key_fec_params_));
55 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
56 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
57 kFecMaskRandom;
58 }
59
~RTPSenderVideo()60 RTPSenderVideo::~RTPSenderVideo() {
61 if (_videoCodecInformation) {
62 delete _videoCodecInformation;
63 }
64 delete _sendVideoCritsect;
65 }
66
SetVideoCodecType(RtpVideoCodecTypes videoType)67 void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) {
68 CriticalSectionScoped cs(_sendVideoCritsect);
69 _videoType = videoType;
70 }
71
VideoCodecType() const72 RtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const {
73 return _videoType;
74 }
75
RegisterVideoPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE],const int8_t payloadType,const uint32_t maxBitRate,RtpUtility::Payload * & payload)76 int32_t RTPSenderVideo::RegisterVideoPayload(
77 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
78 const int8_t payloadType,
79 const uint32_t maxBitRate,
80 RtpUtility::Payload*& payload) {
81 CriticalSectionScoped cs(_sendVideoCritsect);
82
83 RtpVideoCodecTypes videoType = kRtpVideoGeneric;
84 if (RtpUtility::StringCompare(payloadName, "VP8", 3)) {
85 videoType = kRtpVideoVp8;
86 } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) {
87 videoType = kRtpVideoH264;
88 } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) {
89 videoType = kRtpVideoGeneric;
90 } else {
91 videoType = kRtpVideoGeneric;
92 }
93 payload = new RtpUtility::Payload;
94 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
95 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
96 payload->typeSpecific.Video.videoCodecType = videoType;
97 payload->typeSpecific.Video.maxRate = maxBitRate;
98 payload->audio = false;
99 return 0;
100 }
101
SendVideoPacket(uint8_t * data_buffer,const uint16_t payload_length,const uint16_t rtp_header_length,const uint32_t capture_timestamp,int64_t capture_time_ms,StorageType storage,bool protect)102 int32_t RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer,
103 const uint16_t payload_length,
104 const uint16_t rtp_header_length,
105 const uint32_t capture_timestamp,
106 int64_t capture_time_ms,
107 StorageType storage,
108 bool protect) {
109 if (_fecEnabled) {
110 int ret = 0;
111 int fec_overhead_sent = 0;
112 int video_sent = 0;
113
114 RedPacket* red_packet = producer_fec_.BuildRedPacket(
115 data_buffer, payload_length, rtp_header_length, _payloadTypeRED);
116 TRACE_EVENT_INSTANT2("webrtc_rtp",
117 "Video::PacketRed",
118 "timestamp",
119 capture_timestamp,
120 "seqnum",
121 _rtpSender.SequenceNumber());
122 // Sending the media packet with RED header.
123 int packet_success =
124 _rtpSender.SendToNetwork(red_packet->data(),
125 red_packet->length() - rtp_header_length,
126 rtp_header_length,
127 capture_time_ms,
128 storage,
129 PacedSender::kNormalPriority);
130
131 ret |= packet_success;
132
133 if (packet_success == 0) {
134 video_sent += red_packet->length();
135 }
136 delete red_packet;
137 red_packet = NULL;
138
139 if (protect) {
140 ret = producer_fec_.AddRtpPacketAndGenerateFec(
141 data_buffer, payload_length, rtp_header_length);
142 if (ret != 0)
143 return ret;
144 }
145
146 while (producer_fec_.FecAvailable()) {
147 red_packet =
148 producer_fec_.GetFecPacket(_payloadTypeRED,
149 _payloadTypeFEC,
150 _rtpSender.IncrementSequenceNumber(),
151 rtp_header_length);
152 StorageType storage = kDontRetransmit;
153 if (_retransmissionSettings & kRetransmitFECPackets) {
154 storage = kAllowRetransmission;
155 }
156 TRACE_EVENT_INSTANT2("webrtc_rtp",
157 "Video::PacketFec",
158 "timestamp",
159 capture_timestamp,
160 "seqnum",
161 _rtpSender.SequenceNumber());
162 // Sending FEC packet with RED header.
163 int packet_success =
164 _rtpSender.SendToNetwork(red_packet->data(),
165 red_packet->length() - rtp_header_length,
166 rtp_header_length,
167 capture_time_ms,
168 storage,
169 PacedSender::kNormalPriority);
170
171 ret |= packet_success;
172
173 if (packet_success == 0) {
174 fec_overhead_sent += red_packet->length();
175 }
176 delete red_packet;
177 red_packet = NULL;
178 }
179 _videoBitrate.Update(video_sent);
180 _fecOverheadRate.Update(fec_overhead_sent);
181 return ret;
182 }
183 TRACE_EVENT_INSTANT2("webrtc_rtp",
184 "Video::PacketNormal",
185 "timestamp",
186 capture_timestamp,
187 "seqnum",
188 _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
SendRTPIntraRequest()201 int32_t RTPSenderVideo::SendRTPIntraRequest() {
202 // RFC 2032
203 // 5.2.1. Full intra-frame Request (FIR) packet
204
205 uint16_t length = 8;
206 uint8_t data[8];
207 data[0] = 0x80;
208 data[1] = 192;
209 data[2] = 0;
210 data[3] = 1; // length
211
212 RtpUtility::AssignUWord32ToBuffer(data + 4, _rtpSender.SSRC());
213
214 TRACE_EVENT_INSTANT1("webrtc_rtp",
215 "Video::IntraRequest",
216 "seqnum",
217 _rtpSender.SequenceNumber());
218 return _rtpSender.SendToNetwork(
219 data, 0, length, -1, kDontStore, PacedSender::kNormalPriority);
220 }
221
SetGenericFECStatus(const bool enable,const uint8_t payloadTypeRED,const uint8_t payloadTypeFEC)222 int32_t RTPSenderVideo::SetGenericFECStatus(const bool enable,
223 const uint8_t payloadTypeRED,
224 const uint8_t payloadTypeFEC) {
225 _fecEnabled = enable;
226 _payloadTypeRED = payloadTypeRED;
227 _payloadTypeFEC = payloadTypeFEC;
228 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
229 memset(&key_fec_params_, 0, sizeof(key_fec_params_));
230 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
231 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
232 kFecMaskRandom;
233 return 0;
234 }
235
GenericFECStatus(bool & enable,uint8_t & payloadTypeRED,uint8_t & payloadTypeFEC) const236 int32_t RTPSenderVideo::GenericFECStatus(bool& enable,
237 uint8_t& payloadTypeRED,
238 uint8_t& payloadTypeFEC) const {
239 enable = _fecEnabled;
240 payloadTypeRED = _payloadTypeRED;
241 payloadTypeFEC = _payloadTypeFEC;
242 return 0;
243 }
244
FECPacketOverhead() const245 uint16_t RTPSenderVideo::FECPacketOverhead() const {
246 if (_fecEnabled) {
247 // Overhead is FEC headers plus RED for FEC header plus anything in RTP
248 // header beyond the 12 bytes base header (CSRC list, extensions...)
249 // This reason for the header extensions to be included here is that
250 // from an FEC viewpoint, they are part of the payload to be protected.
251 // (The base RTP header is already protected by the FEC header.)
252 return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength +
253 (_rtpSender.RTPHeaderLength() - kRtpHeaderSize);
254 }
255 return 0;
256 }
257
SetFecParameters(const FecProtectionParams * delta_params,const FecProtectionParams * key_params)258 int32_t RTPSenderVideo::SetFecParameters(
259 const FecProtectionParams* delta_params,
260 const FecProtectionParams* key_params) {
261 assert(delta_params);
262 assert(key_params);
263 delta_fec_params_ = *delta_params;
264 key_fec_params_ = *key_params;
265 return 0;
266 }
267
SendVideo(const RtpVideoCodecTypes videoType,const FrameType frameType,const int8_t payloadType,const uint32_t captureTimeStamp,int64_t capture_time_ms,const uint8_t * payloadData,const uint32_t payloadSize,const RTPFragmentationHeader * fragmentation,VideoCodecInformation * codecInfo,const RTPVideoTypeHeader * rtpTypeHdr)268 int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
269 const FrameType frameType,
270 const int8_t payloadType,
271 const uint32_t captureTimeStamp,
272 int64_t capture_time_ms,
273 const uint8_t* payloadData,
274 const uint32_t payloadSize,
275 const RTPFragmentationHeader* fragmentation,
276 VideoCodecInformation* codecInfo,
277 const RTPVideoTypeHeader* rtpTypeHdr) {
278 if (payloadSize == 0) {
279 return -1;
280 }
281
282 if (frameType == kVideoFrameKey) {
283 producer_fec_.SetFecParameters(&key_fec_params_, _numberFirstPartition);
284 } else {
285 producer_fec_.SetFecParameters(&delta_fec_params_, _numberFirstPartition);
286 }
287
288 // Default setting for number of first partition packets:
289 // Will be extracted in SendVP8 for VP8 codec; other codecs use 0
290 _numberFirstPartition = 0;
291
292 return Send(videoType,
293 frameType,
294 payloadType,
295 captureTimeStamp,
296 capture_time_ms,
297 payloadData,
298 payloadSize,
299 fragmentation,
300 rtpTypeHdr)
301 ? 0
302 : -1;
303 }
304
CodecInformationVideo()305 VideoCodecInformation* RTPSenderVideo::CodecInformationVideo() {
306 return _videoCodecInformation;
307 }
308
SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)309 void RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) {
310 _maxBitrate = maxBitrate;
311 }
312
MaxConfiguredBitrateVideo() const313 uint32_t RTPSenderVideo::MaxConfiguredBitrateVideo() const {
314 return _maxBitrate;
315 }
316
Send(const RtpVideoCodecTypes videoType,const FrameType frameType,const int8_t payloadType,const uint32_t captureTimeStamp,int64_t capture_time_ms,const uint8_t * payloadData,const uint32_t payloadSize,const RTPFragmentationHeader * fragmentation,const RTPVideoTypeHeader * rtpTypeHdr)317 bool RTPSenderVideo::Send(const RtpVideoCodecTypes videoType,
318 const FrameType frameType,
319 const int8_t payloadType,
320 const uint32_t captureTimeStamp,
321 int64_t capture_time_ms,
322 const uint8_t* payloadData,
323 const uint32_t payloadSize,
324 const RTPFragmentationHeader* fragmentation,
325 const RTPVideoTypeHeader* rtpTypeHdr) {
326 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength();
327 int32_t payload_bytes_to_send = payloadSize;
328 const uint8_t* data = payloadData;
329 size_t max_payload_length = _rtpSender.MaxDataPayloadLength();
330
331 scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
332 videoType, max_payload_length, rtpTypeHdr, frameType));
333
334 // TODO(changbin): we currently don't support to configure the codec to
335 // output multiple partitions for VP8. Should remove below check after the
336 // issue is fixed.
337 const RTPFragmentationHeader* frag =
338 (videoType == kRtpVideoVp8) ? NULL : fragmentation;
339
340 packetizer->SetPayloadData(data, payload_bytes_to_send, frag);
341
342 bool last = false;
343 while (!last) {
344 uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
345 size_t payload_bytes_in_packet = 0;
346 if (!packetizer->NextPacket(
347 &dataBuffer[rtp_header_length], &payload_bytes_in_packet, &last)) {
348 return false;
349 }
350
351 // Write RTP header.
352 // Set marker bit true if this is the last packet in frame.
353 _rtpSender.BuildRTPheader(
354 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms);
355 if (SendVideoPacket(dataBuffer,
356 payload_bytes_in_packet,
357 rtp_header_length,
358 captureTimeStamp,
359 capture_time_ms,
360 packetizer->GetStorageType(_retransmissionSettings),
361 packetizer->GetProtectionType() == kProtectedPacket)) {
362 LOG(LS_WARNING) << packetizer->ToString()
363 << " failed to send packet number "
364 << _rtpSender.SequenceNumber();
365 }
366 }
367
368 TRACE_EVENT_ASYNC_END1(
369 "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp());
370 return true;
371 }
372
ProcessBitrate()373 void RTPSenderVideo::ProcessBitrate() {
374 _videoBitrate.Process();
375 _fecOverheadRate.Process();
376 }
377
VideoBitrateSent() const378 uint32_t RTPSenderVideo::VideoBitrateSent() const {
379 return _videoBitrate.BitrateLast();
380 }
381
FecOverheadRate() const382 uint32_t RTPSenderVideo::FecOverheadRate() const {
383 return _fecOverheadRate.BitrateLast();
384 }
385
SelectiveRetransmissions() const386 int RTPSenderVideo::SelectiveRetransmissions() const {
387 return _retransmissionSettings;
388 }
389
SetSelectiveRetransmissions(uint8_t settings)390 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
391 _retransmissionSettings = settings;
392 return 0;
393 }
394
395 } // namespace webrtc
396