Home | History | Annotate | Download | only in source
      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 
     34 RTPSenderVideo::RTPSenderVideo(Clock* clock,
     35                                RTPSenderInterface* rtpSender)
     36     : _rtpSender(*rtpSender),
     37       _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
     38       _videoType(kRtpVideoGeneric),
     39       _videoCodecInformation(NULL),
     40       _maxBitrate(0),
     41       _retransmissionSettings(kRetransmitBaseLayer),
     42 
     43       // Generic FEC
     44       _fec(),
     45       _fecEnabled(false),
     46       _payloadTypeRED(-1),
     47       _payloadTypeFEC(-1),
     48       _numberFirstPartition(0),
     49       delta_fec_params_(),
     50       key_fec_params_(),
     51       producer_fec_(&_fec),
     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 =
     58         kFecMaskRandom;
     59 }
     60 
     61 RTPSenderVideo::~RTPSenderVideo()
     62 {
     63     if(_videoCodecInformation)
     64     {
     65         delete _videoCodecInformation;
     66     }
     67     delete _sendVideoCritsect;
     68 }
     69 
     70 void
     71 RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType)
     72 {
     73     CriticalSectionScoped cs(_sendVideoCritsect);
     74     _videoType = videoType;
     75 }
     76 
     77 RtpVideoCodecTypes
     78 RTPSenderVideo::VideoCodecType() const
     79 {
     80     return _videoType;
     81 }
     82 
     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);
     89 
     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;
     95   } else {
     96     videoType = kRtpVideoGeneric;
     97   }
     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;
    104   return 0;
    105 }
    106 
    107 int32_t
    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,
    113                                 StorageType storage,
    114                                 bool protect) {
    115   if(_fecEnabled) {
    116     int ret = 0;
    117     int fec_overhead_sent = 0;
    118     int video_sent = 0;
    119 
    120     RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer,
    121                                                          payload_length,
    122                                                          rtp_header_length,
    123                                                          _payloadTypeRED);
    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(
    129         red_packet->data(),
    130         red_packet->length() - rtp_header_length,
    131         rtp_header_length,
    132         capture_time_ms,
    133         storage,
    134         PacedSender::kNormalPriority);
    135 
    136     ret |= packet_success;
    137 
    138     if (packet_success == 0) {
    139       video_sent += red_packet->length();
    140     }
    141     delete red_packet;
    142     red_packet = NULL;
    143 
    144     if (protect) {
    145       ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer,
    146                                                      payload_length,
    147                                                      rtp_header_length);
    148       if (ret != 0)
    149         return ret;
    150     }
    151 
    152     while (producer_fec_.FecAvailable()) {
    153       red_packet = producer_fec_.GetFecPacket(
    154           _payloadTypeRED,
    155           _payloadTypeFEC,
    156           _rtpSender.IncrementSequenceNumber(),
    157           rtp_header_length);
    158       StorageType storage = kDontRetransmit;
    159       if (_retransmissionSettings & kRetransmitFECPackets) {
    160         storage = kAllowRetransmission;
    161       }
    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(
    167           red_packet->data(),
    168           red_packet->length() - rtp_header_length,
    169           rtp_header_length,
    170           capture_time_ms,
    171           storage,
    172           PacedSender::kNormalPriority);
    173 
    174       ret |= packet_success;
    175 
    176       if (packet_success == 0) {
    177         fec_overhead_sent += red_packet->length();
    178       }
    179       delete red_packet;
    180       red_packet = NULL;
    181     }
    182     _videoBitrate.Update(video_sent);
    183     _fecOverheadRate.Update(fec_overhead_sent);
    184     return ret;
    185   }
    186   TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal",
    187                        "timestamp", capture_timestamp,
    188                        "seqnum", _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 
    201 int32_t
    202 RTPSenderVideo::SendRTPIntraRequest()
    203 {
    204     // RFC 2032
    205     // 5.2.1.  Full intra-frame Request (FIR) packet
    206 
    207     uint16_t length = 8;
    208     uint8_t data[8];
    209     data[0] = 0x80;
    210     data[1] = 192;
    211     data[2] = 0;
    212     data[3] = 1; // length
    213 
    214     ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC());
    215 
    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);
    221 }
    222 
    223 int32_t
    224 RTPSenderVideo::SetGenericFECStatus(const bool enable,
    225                                     const uint8_t payloadTypeRED,
    226                                     const uint8_t payloadTypeFEC)
    227 {
    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 =
    235           kFecMaskRandom;
    236     return 0;
    237 }
    238 
    239 int32_t
    240 RTPSenderVideo::GenericFECStatus(bool& enable,
    241                                  uint8_t& payloadTypeRED,
    242                                  uint8_t& payloadTypeFEC) const
    243 {
    244     enable = _fecEnabled;
    245     payloadTypeRED = _payloadTypeRED;
    246     payloadTypeFEC = _payloadTypeFEC;
    247     return 0;
    248 }
    249 
    250 uint16_t
    251 RTPSenderVideo::FECPacketOverhead() const
    252 {
    253     if (_fecEnabled)
    254     {
    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);
    262     }
    263     return 0;
    264 }
    265 
    266 int32_t RTPSenderVideo::SetFecParameters(
    267     const FecProtectionParams* delta_params,
    268     const FecProtectionParams* key_params) {
    269   assert(delta_params);
    270   assert(key_params);
    271   delta_fec_params_ = *delta_params;
    272   key_fec_params_ = *key_params;
    273   return 0;
    274 }
    275 
    276 int32_t
    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)
    287 {
    288     if( payloadSize == 0)
    289     {
    290         return -1;
    291     }
    292 
    293     if (frameType == kVideoFrameKey) {
    294       producer_fec_.SetFecParameters(&key_fec_params_,
    295                                      _numberFirstPartition);
    296     } else {
    297       producer_fec_.SetFecParameters(&delta_fec_params_,
    298                                      _numberFirstPartition);
    299     }
    300 
    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;
    304 
    305     int32_t retVal = -1;
    306     switch(videoType)
    307     {
    308     case kRtpVideoGeneric:
    309         retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
    310                              capture_time_ms, payloadData, payloadSize);
    311         break;
    312     case kRtpVideoVp8:
    313         retVal = SendVP8(frameType,
    314                          payloadType,
    315                          captureTimeStamp,
    316                          capture_time_ms,
    317                          payloadData,
    318                          payloadSize,
    319                          fragmentation,
    320                          rtpTypeHdr);
    321         break;
    322     default:
    323         assert(false);
    324         break;
    325     }
    326     if(retVal <= 0)
    327     {
    328         return retVal;
    329     }
    330     return 0;
    331 }
    332 
    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,
    338                                     uint32_t size) {
    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 */);
    343 
    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);
    348 
    349   // Fragment packet into packets of max MaxPayloadLength bytes payload.
    350   uint8_t buffer[IP_PACKET_SIZE];
    351 
    352   uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit;
    353   if (frame_type == kVideoFrameKey) {
    354     generic_header |= RtpFormatVideoGeneric::kKeyFrameBit;
    355   }
    356 
    357   while (size > 0) {
    358     if (size < payload_length) {
    359       payload_length = size;
    360     }
    361     size -= payload_length;
    362 
    363     // MarkerBit is 1 on final packet (bytes_to_send == 0)
    364     if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
    365                                   capture_timestamp,
    366                                   capture_time_ms) != rtp_header_length) {
    367       return -1;
    368     }
    369 
    370     uint8_t* out_ptr = &buffer[rtp_header_length];
    371 
    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;
    376 
    377     // Put payload in packet
    378     memcpy(out_ptr, payload, payload_length);
    379     payload += payload_length;
    380 
    381     if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length,
    382                         capture_timestamp, capture_time_ms,
    383                         kAllowRetransmission, true)) {
    384       return -1;
    385     }
    386   }
    387   return 0;
    388 }
    389 
    390 VideoCodecInformation*
    391 RTPSenderVideo::CodecInformationVideo()
    392 {
    393     return _videoCodecInformation;
    394 }
    395 
    396 void
    397 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)
    398 {
    399     _maxBitrate = maxBitrate;
    400 }
    401 
    402 uint32_t
    403 RTPSenderVideo::MaxConfiguredBitrateVideo() const
    404 {
    405     return _maxBitrate;
    406 }
    407 
    408 int32_t
    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)
    417 {
    418     const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
    419 
    420     int32_t payloadBytesToSend = payloadSize;
    421     const uint8_t* data = payloadData;
    422 
    423     uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength();
    424 
    425     assert(rtpTypeHdr);
    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);
    430 
    431     StorageType storage = kAllowRetransmission;
    432     if (rtpTypeHdr->VP8.temporalIdx == 0 &&
    433         !(_retransmissionSettings & kRetransmitBaseLayer)) {
    434       storage = kDontRetransmit;
    435     }
    436     if (rtpTypeHdr->VP8.temporalIdx > 0 &&
    437         !(_retransmissionSettings & kRetransmitHigherLayers)) {
    438       storage = kDontRetransmit;
    439     }
    440 
    441     bool last = false;
    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);
    446     while (!last)
    447     {
    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)
    458         // {
    459         //     ++_numberFirstPartition;
    460         // }
    461         // else
    462         if (packetStartPartition < 0)
    463         {
    464             return -1;
    465         }
    466 
    467         // Write RTP header.
    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))
    474         {
    475           LOG(LS_WARNING)
    476               << "RTPSenderVideo::SendVP8 failed to send packet number "
    477               << _rtpSender.SequenceNumber();
    478         }
    479     }
    480     TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
    481                            "timestamp", _rtpSender.Timestamp());
    482     return 0;
    483 }
    484 
    485 void RTPSenderVideo::ProcessBitrate() {
    486   _videoBitrate.Process();
    487   _fecOverheadRate.Process();
    488 }
    489 
    490 uint32_t RTPSenderVideo::VideoBitrateSent() const {
    491   return _videoBitrate.BitrateLast();
    492 }
    493 
    494 uint32_t RTPSenderVideo::FecOverheadRate() const {
    495   return _fecOverheadRate.BitrateLast();
    496 }
    497 
    498 int RTPSenderVideo::SelectiveRetransmissions() const {
    499   return _retransmissionSettings;
    500 }
    501 
    502 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
    503   _retransmissionSettings = settings;
    504   return 0;
    505 }
    506 
    507 }  // namespace webrtc
    508