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

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

Issue 1739273002: [Draft] RtpPacket sketched. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase to use landed version of rtp::Packet Created 4 years, 8 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 <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
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
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
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
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