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 <memory> | 16 #include <memory> |
17 #include <vector> | 17 #include <vector> |
| 18 #include <utility> |
18 | 19 |
19 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
21 #include "webrtc/base/trace_event.h" | 22 #include "webrtc/base/trace_event.h" |
22 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
23 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 24 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
24 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" | 25 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" |
25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" | 26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |
26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 27 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
27 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" | 28 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |
| 29 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
| 30 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
28 | 31 |
29 namespace webrtc { | 32 namespace webrtc { |
30 | 33 |
31 enum { REDForFECHeaderLength = 1 }; | 34 enum { REDForFECHeaderLength = 1 }; |
32 | 35 |
33 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender) | 36 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender) |
34 : rtp_sender_(rtp_sender), | 37 : rtp_sender_(rtp_sender), |
35 clock_(clock), | 38 clock_(clock), |
36 // Generic FEC | 39 // Generic FEC |
37 producer_fec_(&fec_), | 40 producer_fec_(&fec_), |
(...skipping 27 matching lines...) Expand all Loading... |
65 video_type = kRtpVideoGeneric; | 68 video_type = kRtpVideoGeneric; |
66 } | 69 } |
67 RtpUtility::Payload* payload = new RtpUtility::Payload(); | 70 RtpUtility::Payload* payload = new RtpUtility::Payload(); |
68 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; | 71 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; |
69 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1); | 72 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1); |
70 payload->typeSpecific.Video.videoCodecType = video_type; | 73 payload->typeSpecific.Video.videoCodecType = video_type; |
71 payload->audio = false; | 74 payload->audio = false; |
72 return payload; | 75 return payload; |
73 } | 76 } |
74 | 77 |
75 void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, | 78 void RTPSenderVideo::SendVideoPacket(std::unique_ptr<RtpPacketToSend> packet, |
76 size_t payload_length, | |
77 size_t rtp_header_length, | |
78 uint16_t seq_num, | |
79 uint32_t rtp_timestamp, | |
80 int64_t capture_time_ms, | |
81 StorageType storage) { | 79 StorageType storage) { |
82 if (!rtp_sender_->SendToNetwork(data_buffer, payload_length, | 80 // Remember some values about the packet before sending it away. |
83 rtp_header_length, capture_time_ms, storage, | 81 size_t packet_size = packet->size(); |
| 82 uint16_t seq_num = packet->SequenceNumber(); |
| 83 uint32_t rtp_timestamp = packet->Timestamp(); |
| 84 if (!rtp_sender_->SendToNetwork(std::move(packet), storage, |
84 RtpPacketSender::kLowPriority)) { | 85 RtpPacketSender::kLowPriority)) { |
85 LOG(LS_WARNING) << "Failed to send video packet " << seq_num; | 86 LOG(LS_WARNING) << "Failed to send video packet " << seq_num; |
86 return; | 87 return; |
87 } | 88 } |
88 rtc::CritScope cs(&stats_crit_); | 89 rtc::CritScope cs(&stats_crit_); |
89 video_bitrate_.Update(payload_length + rtp_header_length, | 90 video_bitrate_.Update(packet_size, clock_->TimeInMilliseconds()); |
90 clock_->TimeInMilliseconds()); | |
91 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 91 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
92 "Video::PacketNormal", "timestamp", rtp_timestamp, | 92 "Video::PacketNormal", "timestamp", rtp_timestamp, |
93 "seqnum", seq_num); | 93 "seqnum", seq_num); |
94 } | 94 } |
95 | 95 |
96 void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer, | 96 void RTPSenderVideo::SendVideoPacketAsRed( |
97 size_t payload_length, | 97 std::unique_ptr<RtpPacketToSend> packet, |
98 size_t rtp_header_length, | 98 StorageType media_packet_storage, |
99 uint16_t media_seq_num, | 99 bool protect) { |
100 uint32_t rtp_timestamp, | 100 uint32_t rtp_timestamp = packet->Timestamp(); |
101 int64_t capture_time_ms, | 101 uint16_t media_seq_num = packet->SequenceNumber(); |
102 StorageType media_packet_storage, | 102 |
103 bool protect) { | 103 std::unique_ptr<RtpPacketToSend> red_packet; |
104 std::unique_ptr<RedPacket> red_packet; | |
105 std::vector<std::unique_ptr<RedPacket>> fec_packets; | 104 std::vector<std::unique_ptr<RedPacket>> fec_packets; |
106 StorageType fec_storage = kDontRetransmit; | 105 StorageType fec_storage = kDontRetransmit; |
107 uint16_t next_fec_sequence_number = 0; | |
108 { | 106 { |
109 // Only protect while creating RED and FEC packets, not when sending. | 107 // Only protect while creating RED and FEC packets, not when sending. |
| 108 red_packet = rtp_sender_->AllocatePacket(); |
110 rtc::CritScope cs(&crit_); | 109 rtc::CritScope cs(&crit_); |
111 red_packet = ProducerFec::BuildRedPacket( | 110 producer_fec_.BuildRedPacket(red_payload_type_, *packet, red_packet.get()); |
112 data_buffer, payload_length, rtp_header_length, red_payload_type_); | |
113 if (protect) { | 111 if (protect) { |
114 producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length, | 112 producer_fec_.AddRtpPacketAndGenerateFec( |
115 rtp_header_length); | 113 packet->data(), packet->payload_size(), packet->headers_size()); |
116 } | 114 } |
117 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets(); | 115 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets(); |
118 if (num_fec_packets > 0) { | 116 if (num_fec_packets > 0) { |
119 next_fec_sequence_number = | 117 uint16_t first_fec_sequence_number = |
120 rtp_sender_->AllocateSequenceNumber(num_fec_packets); | 118 rtp_sender_->AllocateSequenceNumber(num_fec_packets); |
121 fec_packets = producer_fec_.GetFecPacketsAsRed( | 119 fec_packets = producer_fec_.GetFecPacketsAsRed( |
122 red_payload_type_, fec_payload_type_, next_fec_sequence_number, | 120 red_payload_type_, fec_payload_type_, first_fec_sequence_number, |
123 rtp_header_length); | 121 packet->headers_size()); |
124 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); | 122 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); |
125 if (retransmission_settings_ & kRetransmitFECPackets) | 123 if (retransmission_settings_ & kRetransmitFECPackets) |
126 fec_storage = kAllowRetransmission; | 124 fec_storage = kAllowRetransmission; |
127 } | 125 } |
128 } | 126 } |
129 if (rtp_sender_->SendToNetwork( | 127 // Send |red_packet| instead of |packet| for allocated sequence number. |
130 red_packet->data(), red_packet->length() - rtp_header_length, | 128 size_t red_packet_size = red_packet->size(); |
131 rtp_header_length, capture_time_ms, media_packet_storage, | 129 if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage, |
132 RtpPacketSender::kLowPriority)) { | 130 RtpPacketSender::kLowPriority)) { |
133 rtc::CritScope cs(&stats_crit_); | 131 rtc::CritScope cs(&stats_crit_); |
134 video_bitrate_.Update(red_packet->length(), clock_->TimeInMilliseconds()); | 132 video_bitrate_.Update(red_packet_size, clock_->TimeInMilliseconds()); |
135 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 133 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
136 "Video::PacketRed", "timestamp", rtp_timestamp, | 134 "Video::PacketRed", "timestamp", rtp_timestamp, |
137 "seqnum", media_seq_num); | 135 "seqnum", media_seq_num); |
138 } else { | 136 } else { |
139 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num; | 137 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num; |
140 } | 138 } |
141 for (const auto& fec_packet : fec_packets) { | 139 for (const auto& fec_packet : fec_packets) { |
142 if (rtp_sender_->SendToNetwork( | 140 // TODO(danilchap): Make producer_fec_ generate rtp::Packets to avoid |
143 fec_packet->data(), fec_packet->length() - rtp_header_length, | 141 // reparsing them. |
144 rtp_header_length, capture_time_ms, fec_storage, | 142 std::unique_ptr<RtpPacketToSend> rtp_packet = rtp_sender_->AllocatePacket(); |
145 RtpPacketSender::kLowPriority)) { | 143 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length())); |
| 144 rtp_packet->set_capture_time_ms(packet->capture_time_ms()); |
| 145 uint16_t fec_sequence_number = rtp_packet->SequenceNumber(); |
| 146 if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage, |
| 147 RtpPacketSender::kLowPriority)) { |
146 rtc::CritScope cs(&stats_crit_); | 148 rtc::CritScope cs(&stats_crit_); |
147 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds()); | 149 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds()); |
148 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 150 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
149 "Video::PacketFec", "timestamp", rtp_timestamp, | 151 "Video::PacketFec", "timestamp", rtp_timestamp, |
150 "seqnum", next_fec_sequence_number); | 152 "seqnum", fec_sequence_number); |
151 } else { | 153 } else { |
152 LOG(LS_WARNING) << "Failed to send FEC packet " | 154 LOG(LS_WARNING) << "Failed to send FEC packet " << fec_sequence_number; |
153 << next_fec_sequence_number; | |
154 } | 155 } |
155 ++next_fec_sequence_number; | |
156 } | 156 } |
157 } | 157 } |
158 | 158 |
159 void RTPSenderVideo::SetGenericFECStatus(bool enable, | 159 void RTPSenderVideo::SetGenericFECStatus(bool enable, |
160 uint8_t payload_type_red, | 160 uint8_t payload_type_red, |
161 uint8_t payload_type_fec) { | 161 uint8_t payload_type_fec) { |
162 RTC_DCHECK(!enable || payload_type_red > 0); | 162 RTC_DCHECK(!enable || payload_type_red > 0); |
163 rtc::CritScope cs(&crit_); | 163 rtc::CritScope cs(&crit_); |
164 fec_enabled_ = enable; | 164 fec_enabled_ = enable; |
165 red_payload_type_ = payload_type_red; | 165 red_payload_type_ = payload_type_red; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 int8_t payload_type, | 210 int8_t payload_type, |
211 uint32_t rtp_timestamp, | 211 uint32_t rtp_timestamp, |
212 int64_t capture_time_ms, | 212 int64_t capture_time_ms, |
213 const uint8_t* payload_data, | 213 const uint8_t* payload_data, |
214 size_t payload_size, | 214 size_t payload_size, |
215 const RTPFragmentationHeader* fragmentation, | 215 const RTPFragmentationHeader* fragmentation, |
216 const RTPVideoHeader* video_header) { | 216 const RTPVideoHeader* video_header) { |
217 if (payload_size == 0) | 217 if (payload_size == 0) |
218 return false; | 218 return false; |
219 | 219 |
| 220 size_t packet_capacity = rtp_sender_->MaxPayloadLength() - |
| 221 FECPacketOverhead() - |
| 222 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0); |
| 223 std::unique_ptr<RtpPacketToSend> packet = rtp_sender_->AllocatePacket(); |
| 224 if (!packet) |
| 225 return false; |
| 226 |
| 227 RTC_DCHECK_LE(packet_capacity, packet->capacity()); |
| 228 packet->SetPayloadType(payload_type); |
| 229 packet->SetTimestamp(rtp_timestamp); |
| 230 packet->set_capture_time_ms(capture_time_ms); |
| 231 // According to |
| 232 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ |
| 233 // ts_126114v120700p.pdf Section 7.4.5: |
| 234 // The MTSI client shall add the payload bytes as defined in this clause |
| 235 // onto the last RTP packet in each group of packets which make up a key |
| 236 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 |
| 237 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP |
| 238 // packet in each group of packets which make up another type of frame |
| 239 // (e.g. a P-Frame) only if the current value is different from the previous |
| 240 // value sent. |
| 241 // Here we are adding it to every packet of every frame at this point. |
| 242 if (video_header && video_header->rotation != kVideoRotation_0) |
| 243 packet->SetExtension<VideoOrientation>(video_header->rotation); |
| 244 |
| 245 size_t max_data_payload_length = packet_capacity - packet->headers_size(); |
| 246 |
220 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 247 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
221 video_type, rtp_sender_->MaxDataPayloadLength(), | 248 video_type, max_data_payload_length, |
222 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 249 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |
223 | 250 |
224 StorageType storage; | 251 StorageType storage; |
225 int red_payload_type; | 252 int red_payload_type; |
226 bool first_frame = first_frame_sent_(); | 253 bool first_frame = first_frame_sent_(); |
227 { | 254 { |
228 rtc::CritScope cs(&crit_); | 255 rtc::CritScope cs(&crit_); |
229 FecProtectionParams* fec_params = | 256 FecProtectionParams* fec_params = |
230 frame_type == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; | 257 frame_type == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; |
231 // We currently do not use unequal protection in the FEC. | 258 // We currently do not use unequal protection in the FEC. |
232 // This is signalled both here (by setting the number of important | 259 // This is signalled both here (by setting the number of important |
233 // packets to zero), as well as in ProducerFec::AddRtpPacketAndGenerateFec. | 260 // packets to zero), as well as in ProducerFec::AddRtpPacketAndGenerateFec. |
234 constexpr int kNumImportantPackets = 0; | 261 constexpr int kNumImportantPackets = 0; |
235 producer_fec_.SetFecParameters(fec_params, kNumImportantPackets); | 262 producer_fec_.SetFecParameters(fec_params, kNumImportantPackets); |
236 storage = packetizer->GetStorageType(retransmission_settings_); | 263 storage = packetizer->GetStorageType(retransmission_settings_); |
237 red_payload_type = red_payload_type_; | 264 red_payload_type = red_payload_type_; |
238 } | 265 } |
239 | 266 |
240 // Register CVO rtp header extension at the first time when we receive a frame | |
241 // with pending rotation. | |
242 bool video_rotation_active = false; | |
243 if (video_header && video_header->rotation != kVideoRotation_0) { | |
244 video_rotation_active = rtp_sender_->ActivateCVORtpHeaderExtension(); | |
245 } | |
246 | |
247 int rtp_header_length = rtp_sender_->RtpHeaderLength(); | |
248 size_t payload_bytes_to_send = payload_size; | |
249 const uint8_t* data = payload_data; | |
250 | |
251 // TODO(changbin): we currently don't support to configure the codec to | 267 // TODO(changbin): we currently don't support to configure the codec to |
252 // output multiple partitions for VP8. Should remove below check after the | 268 // output multiple partitions for VP8. Should remove below check after the |
253 // issue is fixed. | 269 // issue is fixed. |
254 const RTPFragmentationHeader* frag = | 270 const RTPFragmentationHeader* frag = |
255 (video_type == kRtpVideoVp8) ? NULL : fragmentation; | 271 (video_type == kRtpVideoVp8) ? NULL : fragmentation; |
256 | 272 |
257 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); | 273 packetizer->SetPayloadData(payload_data, payload_size, frag); |
258 | 274 |
259 bool first = true; | 275 bool first = true; |
260 bool last = false; | 276 bool last = false; |
261 while (!last) { | 277 while (!last) { |
262 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; | |
263 size_t payload_bytes_in_packet = 0; | 278 size_t payload_bytes_in_packet = 0; |
264 | 279 if (!packetizer->NextPacket( |
265 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length], | 280 packet->AllocatePayload(max_data_payload_length), |
266 &payload_bytes_in_packet, &last)) { | 281 &payload_bytes_in_packet, &last)) { |
267 return false; | 282 return false; |
268 } | 283 } |
269 | 284 packet->SetPayloadSize(payload_bytes_in_packet); |
270 // Write RTP header. | 285 packet->SetMarker(last); |
271 int32_t header_length = rtp_sender_->BuildRtpHeader( | 286 if (!rtp_sender_->AssignSequenceNumber(packet.get())) |
272 dataBuffer, payload_type, last, rtp_timestamp, capture_time_ms); | |
273 if (header_length <= 0) | |
274 return false; | 287 return false; |
275 | 288 |
276 // According to | 289 std::unique_ptr<RtpPacketToSend> packet_to_send = std::move(packet); |
277 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ | 290 if (!last) { |
278 // ts_126114v120700p.pdf Section 7.4.5: | 291 // Allocate next packet and copy all headers. |
279 // The MTSI client shall add the payload bytes as defined in this clause | 292 packet = rtp_sender_->AllocatePacket(); |
280 // onto the last RTP packet in each group of packets which make up a key | 293 // Copy Rtp header including all extensions. |
281 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 | 294 packet->CopyHeaderFrom(*packet_to_send); |
282 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP | 295 packet->set_capture_time_ms(capture_time_ms); |
283 // 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 | |
285 // value sent. | |
286 // Here we are adding it to every packet of every frame at this point. | |
287 if (!video_header) { | |
288 RTC_DCHECK(!rtp_sender_->IsRtpHeaderExtensionRegistered( | |
289 kRtpExtensionVideoRotation)); | |
290 } else if (video_rotation_active) { | |
291 // Checking whether CVO header extension is registered will require taking | |
292 // 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 | |
294 // the RTP header length is consistent, although the receiver side will | |
295 // only exam the packets with marker bit set. | |
296 size_t packetSize = payload_size + rtp_header_length; | |
297 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize); | |
298 RTPHeader rtp_header; | |
299 rtp_parser.Parse(&rtp_header); | |
300 rtp_sender_->UpdateVideoRotation(dataBuffer, packetSize, rtp_header, | |
301 video_header->rotation); | |
302 } | 296 } |
| 297 |
303 if (red_payload_type != 0) { | 298 if (red_payload_type != 0) { |
304 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet, | 299 SendVideoPacketAsRed(std::move(packet_to_send), storage, |
305 rtp_header_length, rtp_sender_->SequenceNumber(), | |
306 rtp_timestamp, capture_time_ms, storage, | |
307 packetizer->GetProtectionType() == kProtectedPacket); | 300 packetizer->GetProtectionType() == kProtectedPacket); |
308 } else { | 301 } else { |
309 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length, | 302 SendVideoPacket(std::move(packet_to_send), storage); |
310 rtp_sender_->SequenceNumber(), rtp_timestamp, | |
311 capture_time_ms, storage); | |
312 } | 303 } |
313 | 304 |
314 if (first_frame) { | 305 if (first_frame) { |
315 if (first) { | 306 if (first) { |
316 LOG(LS_INFO) | 307 LOG(LS_INFO) |
317 << "Sent first RTP packet of the first video frame (pre-pacer)"; | 308 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
318 } | 309 } |
319 if (last) { | 310 if (last) { |
320 LOG(LS_INFO) | 311 LOG(LS_INFO) |
321 << "Sent last RTP packet of the first video frame (pre-pacer)"; | 312 << "Sent last RTP packet of the first video frame (pre-pacer)"; |
(...skipping 21 matching lines...) Expand all Loading... |
343 rtc::CritScope cs(&crit_); | 334 rtc::CritScope cs(&crit_); |
344 return retransmission_settings_; | 335 return retransmission_settings_; |
345 } | 336 } |
346 | 337 |
347 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 338 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
348 rtc::CritScope cs(&crit_); | 339 rtc::CritScope cs(&crit_); |
349 retransmission_settings_ = settings; | 340 retransmission_settings_ = settings; |
350 } | 341 } |
351 | 342 |
352 } // namespace webrtc | 343 } // namespace webrtc |
OLD | NEW |