| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |    2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
|    3  * |    3  * | 
|    4  *  Use of this source code is governed by a BSD-style license |    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 |    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 |    6  *  tree. An additional intellectual property rights grant can be found | 
|    7  *  in the file PATENTS.  All contributing project authors may |    7  *  in the file PATENTS.  All contributing project authors may | 
|    8  *  be found in the AUTHORS file in the root of the source tree. |    8  *  be found in the AUTHORS file in the root of the source tree. | 
|    9  */ |    9  */ | 
|   10  |   10  | 
|   11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" |   11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" | 
|   12  |   12  | 
|   13 #include <stdlib.h> |   13 #include <stdlib.h> | 
|   14 #include <string.h> |   14 #include <string.h> | 
|   15  |   15  | 
 |   16 #include <limits> | 
|   16 #include <memory> |   17 #include <memory> | 
 |   18 #include <utility> | 
|   17 #include <vector> |   19 #include <vector> | 
|   18 #include <utility> |  | 
|   19  |   20  | 
|   20 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |   21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 
|   21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |   22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 
|   22 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |   23 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" | 
|   23 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |   24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 
|   24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |   25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" | 
|   25 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |   26 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | 
|   26 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |   27 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 
|   27 #include "webrtc/rtc_base/checks.h" |   28 #include "webrtc/rtc_base/checks.h" | 
|   28 #include "webrtc/rtc_base/logging.h" |   29 #include "webrtc/rtc_base/logging.h" | 
|   29 #include "webrtc/rtc_base/ptr_util.h" |   30 #include "webrtc/rtc_base/ptr_util.h" | 
|   30 #include "webrtc/rtc_base/trace_event.h" |   31 #include "webrtc/rtc_base/trace_event.h" | 
|   31  |   32  | 
|   32 namespace webrtc { |   33 namespace webrtc { | 
|   33  |   34  | 
|   34 namespace { |   35 namespace { | 
|   35 constexpr size_t kRedForFecHeaderLength = 1; |   36 constexpr size_t kRedForFecHeaderLength = 1; | 
 |   37 constexpr int64_t kMaxUnretransmittableFrameIntervalMs = 33 * 4; | 
|   36  |   38  | 
|   37 void BuildRedPayload(const RtpPacketToSend& media_packet, |   39 void BuildRedPayload(const RtpPacketToSend& media_packet, | 
|   38                      RtpPacketToSend* red_packet) { |   40                      RtpPacketToSend* red_packet) { | 
|   39   uint8_t* red_payload = red_packet->AllocatePayload( |   41   uint8_t* red_payload = red_packet->AllocatePayload( | 
|   40       kRedForFecHeaderLength + media_packet.payload_size()); |   42       kRedForFecHeaderLength + media_packet.payload_size()); | 
|   41   RTC_DCHECK(red_payload); |   43   RTC_DCHECK(red_payload); | 
|   42   red_payload[0] = media_packet.PayloadType(); |   44   red_payload[0] = media_packet.PayloadType(); | 
|   43  |   45  | 
|   44   auto media_payload = media_packet.payload(); |   46   auto media_payload = media_packet.payload(); | 
|   45   memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(), |   47   memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(), | 
|   46          media_payload.size()); |   48          media_payload.size()); | 
|   47 } |   49 } | 
|   48 }  // namespace |   50 }  // namespace | 
|   49  |   51  | 
|   50 RTPSenderVideo::RTPSenderVideo(Clock* clock, |   52 RTPSenderVideo::RTPSenderVideo(Clock* clock, | 
|   51                                RTPSender* rtp_sender, |   53                                RTPSender* rtp_sender, | 
|   52                                FlexfecSender* flexfec_sender) |   54                                FlexfecSender* flexfec_sender) | 
|   53     : rtp_sender_(rtp_sender), |   55     : rtp_sender_(rtp_sender), | 
|   54       clock_(clock), |   56       clock_(clock), | 
|   55       video_type_(kRtpVideoGeneric), |   57       video_type_(kRtpVideoGeneric), | 
|   56       retransmission_settings_(kRetransmitBaseLayer), |   58       retransmission_settings_(kRetransmitBaseLayer | | 
 |   59                                kConditionallyRetransmitHigherLayers), | 
|   57       last_rotation_(kVideoRotation_0), |   60       last_rotation_(kVideoRotation_0), | 
|   58       red_payload_type_(-1), |   61       red_payload_type_(-1), | 
|   59       ulpfec_payload_type_(-1), |   62       ulpfec_payload_type_(-1), | 
|   60       flexfec_sender_(flexfec_sender), |   63       flexfec_sender_(flexfec_sender), | 
|   61       delta_fec_params_{0, 1, kFecMaskRandom}, |   64       delta_fec_params_{0, 1, kFecMaskRandom}, | 
|   62       key_fec_params_{0, 1, kFecMaskRandom}, |   65       key_fec_params_{0, 1, kFecMaskRandom}, | 
|   63       fec_bitrate_(1000, RateStatistics::kBpsScale), |   66       fec_bitrate_(1000, RateStatistics::kBpsScale), | 
|   64       video_bitrate_(1000, RateStatistics::kBpsScale) {} |   67       video_bitrate_(1000, RateStatistics::kBpsScale) {} | 
|   65  |   68  | 
|   66 RTPSenderVideo::~RTPSenderVideo() {} |   69 RTPSenderVideo::~RTPSenderVideo() {} | 
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  285 } |  288 } | 
|  286  |  289  | 
|  287 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, |  290 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, | 
|  288                                FrameType frame_type, |  291                                FrameType frame_type, | 
|  289                                int8_t payload_type, |  292                                int8_t payload_type, | 
|  290                                uint32_t rtp_timestamp, |  293                                uint32_t rtp_timestamp, | 
|  291                                int64_t capture_time_ms, |  294                                int64_t capture_time_ms, | 
|  292                                const uint8_t* payload_data, |  295                                const uint8_t* payload_data, | 
|  293                                size_t payload_size, |  296                                size_t payload_size, | 
|  294                                const RTPFragmentationHeader* fragmentation, |  297                                const RTPFragmentationHeader* fragmentation, | 
|  295                                const RTPVideoHeader* video_header) { |  298                                const RTPVideoHeader* video_header, | 
 |  299                                int64_t expected_retransmission_time_ms) { | 
|  296   if (payload_size == 0) |  300   if (payload_size == 0) | 
|  297     return false; |  301     return false; | 
|  298  |  302  | 
|  299   // Create header that will be reused in all packets. |  303   // Create header that will be reused in all packets. | 
|  300   std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); |  304   std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); | 
|  301   rtp_header->SetPayloadType(payload_type); |  305   rtp_header->SetPayloadType(payload_type); | 
|  302   rtp_header->SetTimestamp(rtp_timestamp); |  306   rtp_header->SetTimestamp(rtp_timestamp); | 
|  303   rtp_header->set_capture_time_ms(capture_time_ms); |  307   rtp_header->set_capture_time_ms(capture_time_ms); | 
|  304   auto last_packet = rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |  308   auto last_packet = rtc::MakeUnique<RtpPacketToSend>(*rtp_header); | 
|  305  |  309  | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  358   RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); |  362   RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); | 
|  359   RTC_DCHECK_GT(packet_capacity, last_packet->headers_size()); |  363   RTC_DCHECK_GT(packet_capacity, last_packet->headers_size()); | 
|  360   size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); |  364   size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); | 
|  361   RTC_DCHECK_GE(last_packet->headers_size(), rtp_header->headers_size()); |  365   RTC_DCHECK_GE(last_packet->headers_size(), rtp_header->headers_size()); | 
|  362   size_t last_packet_reduction_len = |  366   size_t last_packet_reduction_len = | 
|  363       last_packet->headers_size() - rtp_header->headers_size(); |  367       last_packet->headers_size() - rtp_header->headers_size(); | 
|  364  |  368  | 
|  365   std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |  369   std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 
|  366       video_type, max_data_payload_length, last_packet_reduction_len, |  370       video_type, max_data_payload_length, last_packet_reduction_len, | 
|  367       video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |  371       video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 
|  368   // Media packet storage. |  372  | 
|  369   StorageType storage = packetizer->GetStorageType(retransmission_settings); |  373   const uint8_t temporal_id = | 
 |  374       video_header ? GetTemporalId(*video_header) : kNoTemporalIdx; | 
 |  375   StorageType storage = GetStorageType(temporal_id, retransmission_settings, | 
 |  376                                        expected_retransmission_time_ms); | 
|  370  |  377  | 
|  371   // TODO(changbin): we currently don't support to configure the codec to |  378   // TODO(changbin): we currently don't support to configure the codec to | 
|  372   // output multiple partitions for VP8. Should remove below check after the |  379   // output multiple partitions for VP8. Should remove below check after the | 
|  373   // issue is fixed. |  380   // issue is fixed. | 
|  374   const RTPFragmentationHeader* frag = |  381   const RTPFragmentationHeader* frag = | 
|  375       (video_type == kRtpVideoVp8) ? nullptr : fragmentation; |  382       (video_type == kRtpVideoVp8) ? nullptr : fragmentation; | 
|  376   size_t num_packets = |  383   size_t num_packets = | 
|  377       packetizer->SetPayloadData(payload_data, payload_size, frag); |  384       packetizer->SetPayloadData(payload_data, payload_size, frag); | 
|  378  |  385  | 
|  379   if (num_packets == 0) |  386   if (num_packets == 0) | 
|  380     return false; |  387     return false; | 
|  381  |  388  | 
|  382   bool first_frame = first_frame_sent_(); |  389   bool first_frame = first_frame_sent_(); | 
|  383   for (size_t i = 0; i < num_packets; ++i) { |  390   for (size_t i = 0; i < num_packets; ++i) { | 
|  384     bool last = (i + 1) == num_packets; |  391     bool last = (i + 1) == num_packets; | 
|  385     auto packet = last ? std::move(last_packet) |  392     auto packet = last ? std::move(last_packet) | 
|  386                        : rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |  393                        : rtc::MakeUnique<RtpPacketToSend>(*rtp_header); | 
|  387     if (!packetizer->NextPacket(packet.get())) |  394     if (!packetizer->NextPacket(packet.get())) | 
|  388       return false; |  395       return false; | 
|  389     RTC_DCHECK_LE(packet->payload_size(), |  396     RTC_DCHECK_LE(packet->payload_size(), | 
|  390                   last ? max_data_payload_length - last_packet_reduction_len |  397                   last ? max_data_payload_length - last_packet_reduction_len | 
|  391                        : max_data_payload_length); |  398                        : max_data_payload_length); | 
|  392     if (!rtp_sender_->AssignSequenceNumber(packet.get())) |  399     if (!rtp_sender_->AssignSequenceNumber(packet.get())) | 
|  393       return false; |  400       return false; | 
|  394  |  401  | 
|  395     bool protect_packet = (packetizer->GetProtectionType() == kProtectedPacket); |  402     // No FEC protection for upper temporal layers, if used. | 
 |  403     bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx; | 
 |  404  | 
|  396     // Put packetization finish timestamp into extension. |  405     // Put packetization finish timestamp into extension. | 
|  397     if (packet->HasExtension<VideoTimingExtension>()) { |  406     if (packet->HasExtension<VideoTimingExtension>()) { | 
|  398       packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds()); |  407       packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds()); | 
|  399       // TODO(ilnik): Due to webrtc:7859, packets with timing extensions are not |  408       // TODO(ilnik): Due to webrtc:7859, packets with timing extensions are not | 
|  400       // protected by FEC. It reduces FEC efficiency a bit. When FEC is moved |  409       // protected by FEC. It reduces FEC efficiency a bit. When FEC is moved | 
|  401       // below the pacer, it can be re-enabled for these packets. |  410       // below the pacer, it can be re-enabled for these packets. | 
|  402       // NOTE: Any RTP stream processor in the network, modifying 'network' |  411       // NOTE: Any RTP stream processor in the network, modifying 'network' | 
|  403       // timestamps in the timing frames extension have to be an end-point for |  412       // timestamps in the timing frames extension have to be an end-point for | 
|  404       // FEC, otherwise recovered by FEC packets will be corrupted. |  413       // FEC, otherwise recovered by FEC packets will be corrupted. | 
|  405       protect_packet = false; |  414       protect_packet = false; | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  446 int RTPSenderVideo::SelectiveRetransmissions() const { |  455 int RTPSenderVideo::SelectiveRetransmissions() const { | 
|  447   rtc::CritScope cs(&crit_); |  456   rtc::CritScope cs(&crit_); | 
|  448   return retransmission_settings_; |  457   return retransmission_settings_; | 
|  449 } |  458 } | 
|  450  |  459  | 
|  451 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |  460 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 
|  452   rtc::CritScope cs(&crit_); |  461   rtc::CritScope cs(&crit_); | 
|  453   retransmission_settings_ = settings; |  462   retransmission_settings_ = settings; | 
|  454 } |  463 } | 
|  455  |  464  | 
 |  465 StorageType RTPSenderVideo::GetStorageType( | 
 |  466     uint8_t temporal_id, | 
 |  467     int32_t retransmission_settings, | 
 |  468     int64_t expected_retransmission_time_ms) { | 
 |  469   if (retransmission_settings == kRetransmitOff) | 
 |  470     return StorageType::kDontRetransmit; | 
 |  471   if (retransmission_settings == kRetransmitAllPackets) | 
 |  472     return StorageType::kAllowRetransmission; | 
 |  473  | 
 |  474   rtc::CritScope cs(&stats_crit_); | 
 |  475   // Media packet storage. | 
 |  476   if ((retransmission_settings & kConditionallyRetransmitHigherLayers) && | 
 |  477       UpdateConditionalRetransmit(temporal_id, | 
 |  478                                   expected_retransmission_time_ms)) { | 
 |  479     retransmission_settings |= kRetransmitHigherLayers; | 
 |  480   } | 
 |  481  | 
 |  482   if (temporal_id == kNoTemporalIdx) | 
 |  483     return kAllowRetransmission; | 
 |  484  | 
 |  485   if ((retransmission_settings & kRetransmitBaseLayer) && temporal_id == 0) | 
 |  486     return kAllowRetransmission; | 
 |  487  | 
 |  488   if ((retransmission_settings & kRetransmitHigherLayers) && temporal_id > 0) | 
 |  489     return kAllowRetransmission; | 
 |  490  | 
 |  491   return kDontRetransmit; | 
 |  492 } | 
 |  493  | 
 |  494 uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) { | 
 |  495   switch (header.codec) { | 
 |  496     case kRtpVideoVp8: | 
 |  497       return header.codecHeader.VP8.temporalIdx; | 
 |  498     case kRtpVideoVp9: | 
 |  499       return header.codecHeader.VP9.temporal_idx; | 
 |  500     default: | 
 |  501       return kNoTemporalIdx; | 
 |  502   } | 
 |  503 } | 
 |  504  | 
 |  505 bool RTPSenderVideo::UpdateConditionalRetransmit( | 
 |  506     uint8_t temporal_id, | 
 |  507     int64_t expected_retransmission_time_ms) { | 
 |  508   int64_t now_ms = clock_->TimeInMilliseconds(); | 
 |  509   // Update stats for any temporal layer. | 
 |  510   TemporalLayerStats* current_layer_stats = | 
 |  511       &frame_stats_by_temporal_layer_[temporal_id]; | 
 |  512   current_layer_stats->frame_rate_fp1000s.Update(1, now_ms); | 
 |  513   int64_t tl_frame_interval = now_ms - current_layer_stats->last_frame_time_ms; | 
 |  514   current_layer_stats->last_frame_time_ms = now_ms; | 
 |  515  | 
 |  516   // Conditional retransmit only applies to upper layers. | 
 |  517   if (temporal_id != kNoTemporalIdx && temporal_id > 0) { | 
 |  518     if (tl_frame_interval >= kMaxUnretransmittableFrameIntervalMs) { | 
 |  519       // Too long since a retransmittable frame in this layer, enable NACK | 
 |  520       // protection. | 
 |  521       return true; | 
 |  522     } else { | 
 |  523       // Estimate when the next frame of any lower layer will be sent. | 
 |  524       const int64_t kUndefined = std::numeric_limits<int64_t>::max(); | 
 |  525       int64_t expected_next_frame_time = kUndefined; | 
 |  526       for (int i = temporal_id - 1; i >= 0; --i) { | 
 |  527         TemporalLayerStats* stats = &frame_stats_by_temporal_layer_[i]; | 
 |  528         rtc::Optional<uint32_t> rate = stats->frame_rate_fp1000s.Rate(now_ms); | 
 |  529         if (rate) { | 
 |  530           int64_t tl_next = stats->last_frame_time_ms + 1000000 / *rate; | 
 |  531           if (tl_next - now_ms > -expected_retransmission_time_ms && | 
 |  532               tl_next < expected_next_frame_time) { | 
 |  533             expected_next_frame_time = tl_next; | 
 |  534           } | 
 |  535         } | 
 |  536       } | 
 |  537  | 
 |  538       if (expected_next_frame_time == kUndefined || | 
 |  539           expected_next_frame_time - now_ms > expected_retransmission_time_ms) { | 
 |  540         // The next frame in a lower layer is expected at a later time (or | 
 |  541         // unable to tell due to lack of data) than a retransmission is | 
 |  542         // estimated to be able to arrive, so allow this packet to be nacked. | 
 |  543         return true; | 
 |  544       } | 
 |  545     } | 
 |  546   } | 
 |  547  | 
 |  548   return false; | 
 |  549 } | 
 |  550  | 
|  456 }  // namespace webrtc |  551 }  // namespace webrtc | 
| OLD | NEW |