| 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 <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "webrtc/base/checks.h" | 18 #include "webrtc/base/checks.h" |
| 19 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
| 20 #include "webrtc/base/trace_event.h" | 20 #include "webrtc/base/trace_event.h" |
| 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
| 23 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" | 23 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" |
| 24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" | 24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |
| 25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
| 26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" | 26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |
| 27 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| 27 | 28 |
| 28 namespace webrtc { | 29 namespace webrtc { |
| 29 enum { REDForFECHeaderLength = 1 }; | 30 enum { REDForFECHeaderLength = 1 }; |
| 30 | 31 |
| 31 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender) | 32 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtpSender) |
| 32 : _rtpSender(*rtpSender), | 33 : _rtpSender(*rtpSender), |
| 33 _videoType(kRtpVideoGeneric), | 34 _videoType(kRtpVideoGeneric), |
| 34 _retransmissionSettings(kRetransmitBaseLayer), | 35 _retransmissionSettings(kRetransmitBaseLayer), |
| 35 // Generic FEC | 36 // Generic FEC |
| 36 fec_(), | 37 fec_(), |
| 37 fec_enabled_(false), | 38 fec_enabled_(false), |
| 38 red_payload_type_(-1), | 39 red_payload_type_(-1), |
| 39 fec_payload_type_(-1), | 40 fec_payload_type_(-1), |
| 40 delta_fec_params_(), | 41 delta_fec_params_(), |
| 41 key_fec_params_(), | 42 key_fec_params_(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 videoType = kRtpVideoGeneric; | 78 videoType = kRtpVideoGeneric; |
| 78 } | 79 } |
| 79 RtpUtility::Payload* payload = new RtpUtility::Payload(); | 80 RtpUtility::Payload* payload = new RtpUtility::Payload(); |
| 80 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | 81 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; |
| 81 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); | 82 strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); |
| 82 payload->typeSpecific.Video.videoCodecType = videoType; | 83 payload->typeSpecific.Video.videoCodecType = videoType; |
| 83 payload->audio = false; | 84 payload->audio = false; |
| 84 return payload; | 85 return payload; |
| 85 } | 86 } |
| 86 | 87 |
| 87 void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, | 88 void RTPSenderVideo::SendVideoPacket(std::unique_ptr<RtpPacketToSend> packet, |
| 88 const size_t payload_length, | |
| 89 const size_t rtp_header_length, | |
| 90 uint16_t seq_num, | |
| 91 const uint32_t capture_timestamp, | |
| 92 int64_t capture_time_ms, | |
| 93 StorageType storage) { | 89 StorageType storage) { |
| 94 if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length, | 90 size_t packet_size = packet->size(); |
| 95 capture_time_ms, storage, | 91 size_t payload_size = packet->payload_size(); |
| 96 RtpPacketSender::kLowPriority) == 0) { | 92 uint16_t seq_num = packet->SequenceNumber(); |
| 97 _videoBitrate.Update(payload_length + rtp_header_length); | 93 uint32_t capture_timestamp = packet->Timestamp(); |
| 94 int64_t capture_time_ms = packet->capture_time_ms(); |
| 95 if (_rtpSender.SendToNetwork(std::move(packet), payload_size, capture_time_ms, |
| 96 storage, RtpPacketSender::kLowPriority) == 0) { |
| 97 _videoBitrate.Update(packet_size); |
| 98 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 98 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 99 "Video::PacketNormal", "timestamp", capture_timestamp, | 99 "Video::PacketNormal", "timestamp", capture_timestamp, |
| 100 "seqnum", seq_num); | 100 "seqnum", seq_num); |
| 101 } else { | 101 } else { |
| 102 LOG(LS_WARNING) << "Failed to send video packet " << seq_num; | 102 LOG(LS_WARNING) << "Failed to send video packet " << seq_num; |
| 103 } | 103 } |
| 104 } | 104 } |
| 105 | 105 |
| 106 void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, | 106 void RTPSenderVideo::SendVideoPacketAsRed( |
| 107 const size_t payload_length, | 107 std::unique_ptr<RtpPacketToSend> packet, |
| 108 const size_t rtp_header_length, | 108 StorageType media_packet_storage, |
| 109 uint16_t media_seq_num, | 109 bool protect) { |
| 110 const uint32_t capture_timestamp, | 110 uint16_t media_seq_num = packet->SequenceNumber(); |
| 111 int64_t capture_time_ms, | 111 uint32_t capture_timestamp = packet->Timestamp(); |
| 112 StorageType media_packet_storage, | 112 int64_t capture_time_ms = packet->capture_time_ms(); |
| 113 bool protect) { | |
| 114 rtc::scoped_ptr<RedPacket> red_packet; | 113 rtc::scoped_ptr<RedPacket> red_packet; |
| 115 std::vector<RedPacket*> fec_packets; | 114 std::vector<RedPacket*> fec_packets; |
| 116 StorageType fec_storage = kDontRetransmit; | 115 StorageType fec_storage = kDontRetransmit; |
| 117 uint16_t next_fec_sequence_number = 0; | 116 uint16_t next_fec_sequence_number = 0; |
| 118 { | 117 { |
| 119 // Only protect while creating RED and FEC packets, not when sending. | 118 // Only protect while creating RED and FEC packets, not when sending. |
| 120 rtc::CritScope cs(&crit_); | 119 rtc::CritScope cs(&crit_); |
| 121 red_packet.reset(producer_fec_.BuildRedPacket( | 120 red_packet.reset(producer_fec_.BuildRedPacket( |
| 122 data_buffer, payload_length, rtp_header_length, red_payload_type_)); | 121 packet->data(), packet->payload_size(), packet->headers_size(), |
| 122 red_payload_type_)); |
| 123 if (protect) { | 123 if (protect) { |
| 124 producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length, | 124 producer_fec_.AddRtpPacketAndGenerateFec( |
| 125 rtp_header_length); | 125 packet->data(), packet->payload_size(), packet->headers_size()); |
| 126 } | 126 } |
| 127 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets(); | 127 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets(); |
| 128 if (num_fec_packets > 0) { | 128 if (num_fec_packets > 0) { |
| 129 next_fec_sequence_number = | 129 next_fec_sequence_number = |
| 130 _rtpSender.AllocateSequenceNumber(num_fec_packets); | 130 _rtpSender.AllocateSequenceNumber(num_fec_packets); |
| 131 fec_packets = producer_fec_.GetFecPackets( | 131 fec_packets = producer_fec_.GetFecPackets( |
| 132 red_payload_type_, fec_payload_type_, next_fec_sequence_number, | 132 red_payload_type_, fec_payload_type_, next_fec_sequence_number, |
| 133 rtp_header_length); | 133 packet->headers_size()); |
| 134 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); | 134 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); |
| 135 if (_retransmissionSettings & kRetransmitFECPackets) | 135 if (_retransmissionSettings & kRetransmitFECPackets) |
| 136 fec_storage = kAllowRetransmission; | 136 fec_storage = kAllowRetransmission; |
| 137 } | 137 } |
| 138 } | 138 } |
| 139 if (_rtpSender.SendToNetwork( | 139 std::unique_ptr<RtpPacketToSend> rtp_packet = _rtpSender.CreatePacket(); |
| 140 red_packet->data(), red_packet->length() - rtp_header_length, | 140 rtp_packet->Parse(red_packet->data(), red_packet->length()); |
| 141 rtp_header_length, capture_time_ms, media_packet_storage, | 141 size_t red_payload_size = rtp_packet->size() - packet->headers_size(); |
| 142 RtpPacketSender::kLowPriority) == 0) { | 142 if (_rtpSender.SendToNetwork(std::move(rtp_packet), red_payload_size, |
| 143 capture_time_ms, media_packet_storage, |
| 144 RtpPacketSender::kLowPriority) == 0) { |
| 143 _videoBitrate.Update(red_packet->length()); | 145 _videoBitrate.Update(red_packet->length()); |
| 144 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 146 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 145 "Video::PacketRed", "timestamp", capture_timestamp, | 147 "Video::PacketRed", "timestamp", capture_timestamp, |
| 146 "seqnum", media_seq_num); | 148 "seqnum", media_seq_num); |
| 147 } else { | 149 } else { |
| 148 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num; | 150 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num; |
| 149 } | 151 } |
| 150 for (RedPacket* fec_packet : fec_packets) { | 152 for (RedPacket* fec_packet : fec_packets) { |
| 151 if (_rtpSender.SendToNetwork( | 153 rtp_packet = _rtpSender.CreatePacket(); |
| 152 fec_packet->data(), fec_packet->length() - rtp_header_length, | 154 rtp_packet->Parse(fec_packet->data(), fec_packet->length()); |
| 153 rtp_header_length, capture_time_ms, fec_storage, | 155 size_t fec_payload_size = rtp_packet->size() - packet->headers_size(); |
| 154 RtpPacketSender::kLowPriority) == 0) { | 156 if (_rtpSender.SendToNetwork(std::move(rtp_packet), fec_payload_size, |
| 157 capture_time_ms, fec_storage, |
| 158 RtpPacketSender::kLowPriority) == 0) { |
| 155 _fecOverheadRate.Update(fec_packet->length()); | 159 _fecOverheadRate.Update(fec_packet->length()); |
| 156 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 160 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
| 157 "Video::PacketFec", "timestamp", capture_timestamp, | 161 "Video::PacketFec", "timestamp", capture_timestamp, |
| 158 "seqnum", next_fec_sequence_number); | 162 "seqnum", next_fec_sequence_number); |
| 159 } else { | 163 } else { |
| 160 LOG(LS_WARNING) << "Failed to send FEC packet " | 164 LOG(LS_WARNING) << "Failed to send FEC packet " |
| 161 << next_fec_sequence_number; | 165 << next_fec_sequence_number; |
| 162 } | 166 } |
| 163 delete fec_packet; | 167 delete fec_packet; |
| 164 ++next_fec_sequence_number; | 168 ++next_fec_sequence_number; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 const uint32_t captureTimeStamp, | 221 const uint32_t captureTimeStamp, |
| 218 int64_t capture_time_ms, | 222 int64_t capture_time_ms, |
| 219 const uint8_t* payloadData, | 223 const uint8_t* payloadData, |
| 220 const size_t payloadSize, | 224 const size_t payloadSize, |
| 221 const RTPFragmentationHeader* fragmentation, | 225 const RTPFragmentationHeader* fragmentation, |
| 222 const RTPVideoHeader* video_header) { | 226 const RTPVideoHeader* video_header) { |
| 223 if (payloadSize == 0) { | 227 if (payloadSize == 0) { |
| 224 return -1; | 228 return -1; |
| 225 } | 229 } |
| 226 | 230 |
| 231 // Register CVO rtp header extension at the first time when we receive a frame |
| 232 // with pending rotation. |
| 233 RTPSenderInterface::CVOMode cvo_mode = RTPSenderInterface::kCVONone; |
| 234 if (video_header && video_header->rotation != kVideoRotation_0) { |
| 235 cvo_mode = _rtpSender.ActivateCVORtpHeaderExtension(); |
| 236 } |
| 237 |
| 238 size_t max_data_payload_size = _rtpSender.MaxDataPayloadLength(); |
| 239 |
| 227 rtc::scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 240 rtc::scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
| 228 videoType, _rtpSender.MaxDataPayloadLength(), | 241 videoType, max_data_payload_size, |
| 229 video_header ? &(video_header->codecHeader) : nullptr, frameType)); | 242 video_header ? &(video_header->codecHeader) : nullptr, frameType)); |
| 230 | 243 |
| 231 StorageType storage; | 244 StorageType storage; |
| 232 bool fec_enabled; | 245 bool fec_enabled; |
| 233 bool first_frame = first_frame_sent_(); | 246 bool first_frame = first_frame_sent_(); |
| 234 { | 247 { |
| 235 rtc::CritScope cs(&crit_); | 248 rtc::CritScope cs(&crit_); |
| 236 FecProtectionParams* fec_params = | 249 FecProtectionParams* fec_params = |
| 237 frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; | 250 frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; |
| 238 producer_fec_.SetFecParameters(fec_params, 0); | 251 producer_fec_.SetFecParameters(fec_params, 0); |
| 239 storage = packetizer->GetStorageType(_retransmissionSettings); | 252 storage = packetizer->GetStorageType(_retransmissionSettings); |
| 240 fec_enabled = fec_enabled_; | 253 fec_enabled = fec_enabled_; |
| 241 } | 254 } |
| 242 | 255 |
| 243 // Register CVO rtp header extension at the first time when we receive a frame | |
| 244 // with pending rotation. | |
| 245 RTPSenderInterface::CVOMode cvo_mode = RTPSenderInterface::kCVONone; | |
| 246 if (video_header && video_header->rotation != kVideoRotation_0) { | |
| 247 cvo_mode = _rtpSender.ActivateCVORtpHeaderExtension(); | |
| 248 } | |
| 249 | |
| 250 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); | |
| 251 size_t payload_bytes_to_send = payloadSize; | 256 size_t payload_bytes_to_send = payloadSize; |
| 252 const uint8_t* data = payloadData; | 257 const uint8_t* data = payloadData; |
| 253 | 258 |
| 254 // TODO(changbin): we currently don't support to configure the codec to | 259 // TODO(changbin): we currently don't support to configure the codec to |
| 255 // output multiple partitions for VP8. Should remove below check after the | 260 // output multiple partitions for VP8. Should remove below check after the |
| 256 // issue is fixed. | 261 // issue is fixed. |
| 257 const RTPFragmentationHeader* frag = | 262 const RTPFragmentationHeader* frag = |
| 258 (videoType == kRtpVideoVp8) ? NULL : fragmentation; | 263 (videoType == kRtpVideoVp8) ? NULL : fragmentation; |
| 259 | 264 |
| 260 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); | 265 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); |
| 261 | 266 |
| 262 bool first = true; | 267 bool first = true; |
| 263 bool last = false; | 268 bool last = false; |
| 264 while (!last) { | 269 while (!last) { |
| 265 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; | 270 std::unique_ptr<RtpPacketToSend> packet = _rtpSender.CreatePacket(); |
| 266 size_t payload_bytes_in_packet = 0; | 271 _rtpSender.BuildRtpHeader(packet.get(), captureTimeStamp, true); |
| 267 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length], | 272 packet->SetPayloadType(payloadType); |
| 268 &payload_bytes_in_packet, &last)) { | 273 packet->set_capture_time_ms(capture_time_ms); |
| 269 return -1; | |
| 270 } | |
| 271 | 274 |
| 272 // Write RTP header. | |
| 273 // Set marker bit true if this is the last packet in frame. | |
| 274 _rtpSender.BuildRTPheader( | |
| 275 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms); | |
| 276 // According to | 275 // According to |
| 277 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ | 276 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ |
| 278 // ts_126114v120700p.pdf Section 7.4.5: | 277 // ts_126114v120700p.pdf Section 7.4.5: |
| 279 // The MTSI client shall add the payload bytes as defined in this clause | 278 // The MTSI client shall add the payload bytes as defined in this clause |
| 280 // onto the last RTP packet in each group of packets which make up a key | 279 // onto the last RTP packet in each group of packets which make up a key |
| 281 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 | 280 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 |
| 282 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP | 281 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP |
| 283 // packet in each group of packets which make up another type of frame | 282 // packet in each group of packets which make up another type of frame |
| 284 // (e.g. a P-Frame) only if the current value is different from the previous | 283 // (e.g. a P-Frame) only if the current value is different from the previous |
| 285 // value sent. | 284 // value sent. |
| 286 // Here we are adding it to every packet of every frame at this point. | 285 // Here we are adding it to every packet of every frame at this point. |
| 287 if (!video_header) { | 286 if (!video_header) { |
| 288 RTC_DCHECK(!_rtpSender.IsRtpHeaderExtensionRegistered( | 287 RTC_DCHECK(!_rtpSender.IsRtpHeaderExtensionRegistered( |
| 289 kRtpExtensionVideoRotation)); | 288 kRtpExtensionVideoRotation)); |
| 290 } else if (cvo_mode == RTPSenderInterface::kCVOActivated) { | 289 } else if (cvo_mode == RTPSenderInterface::kCVOActivated) { |
| 291 // Checking whether CVO header extension is registered will require taking | 290 // Checking whether CVO header extension is registered will require taking |
| 292 // a lock. It'll be a no-op if it's not registered. | 291 // a lock. It'll be a no-op if it's not registered. |
| 293 // TODO(guoweis): For now, all packets sent will carry the CVO such that | 292 // TODO(guoweis): For now, all packets sent will carry the CVO such that |
| 294 // the RTP header length is consistent, although the receiver side will | 293 // the RTP header length is consistent, although the receiver side will |
| 295 // only exam the packets with marker bit set. | 294 // only exam the packets with marker bit set. |
| 296 size_t packetSize = payloadSize + rtp_header_length; | 295 packet->SetExtension<VideoOrientation>(video_header->rotation); |
| 297 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); | |
| 298 RTPHeader rtp_header; | |
| 299 rtp_parser.Parse(&rtp_header); | |
| 300 _rtpSender.UpdateVideoRotation(dataBuffer, packetSize, rtp_header, | |
| 301 video_header->rotation); | |
| 302 } | 296 } |
| 297 |
| 298 uint8_t* payload = packet->AllocatePayload(max_data_payload_size); |
| 299 size_t payload_bytes_in_packet = 0; |
| 300 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last)) { |
| 301 return -1; |
| 302 } |
| 303 RTC_DCHECK_LE(payload_bytes_in_packet, max_data_payload_size); |
| 304 packet->SetPayloadSize(payload_bytes_in_packet); |
| 305 // Set marker bit true if this is the last packet in frame. |
| 306 if (last) { |
| 307 packet->SetMarker(true); |
| 308 } |
| 309 |
| 303 if (fec_enabled) { | 310 if (fec_enabled) { |
| 304 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet, | 311 SendVideoPacketAsRed(std::move(packet), storage, |
| 305 rtp_header_length, _rtpSender.SequenceNumber(), | |
| 306 captureTimeStamp, capture_time_ms, storage, | |
| 307 packetizer->GetProtectionType() == kProtectedPacket); | 312 packetizer->GetProtectionType() == kProtectedPacket); |
| 308 } else { | 313 } else { |
| 309 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length, | 314 SendVideoPacket(std::move(packet), storage); |
| 310 _rtpSender.SequenceNumber(), captureTimeStamp, | |
| 311 capture_time_ms, storage); | |
| 312 } | 315 } |
| 313 | 316 |
| 314 if (first_frame) { | 317 if (first_frame) { |
| 315 if (first) { | 318 if (first) { |
| 316 LOG(LS_INFO) | 319 LOG(LS_INFO) |
| 317 << "Sent first RTP packet of the first video frame (pre-pacer)"; | 320 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
| 318 } | 321 } |
| 319 if (last) { | 322 if (last) { |
| 320 LOG(LS_INFO) | 323 LOG(LS_INFO) |
| 321 << "Sent last RTP packet of the first video frame (pre-pacer)"; | 324 << "Sent last RTP packet of the first video frame (pre-pacer)"; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 346 rtc::CritScope cs(&crit_); | 349 rtc::CritScope cs(&crit_); |
| 347 return _retransmissionSettings; | 350 return _retransmissionSettings; |
| 348 } | 351 } |
| 349 | 352 |
| 350 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 353 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
| 351 rtc::CritScope cs(&crit_); | 354 rtc::CritScope cs(&crit_); |
| 352 _retransmissionSettings = settings; | 355 _retransmissionSettings = settings; |
| 353 } | 356 } |
| 354 | 357 |
| 355 } // namespace webrtc | 358 } // namespace webrtc |
| OLD | NEW |