• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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