Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(609)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc

Issue 2217383002: Use RtpPacketToSend in RtpSenderVideo (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Ported PlayoutDelay extension support. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_sender_video.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_sender_video.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698