blob: 4a007c53eb476e798785e9b6eb4ef4566bbe8815 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:251/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:592 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:253 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:3811#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
niklase@google.com470e71d2011-07-07 08:21:2512
pbos@webrtc.orga048d7c2013-05-29 14:27:3813#include <stdlib.h>
14#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:2515
kwiberg84be5112016-04-27 08:19:5816#include <memory>
mflodmanfcf54bd2015-04-14 19:28:0817#include <vector>
danilchap74110612016-10-02 17:54:2918#include <utility>
mflodmanfcf54bd2015-04-14 19:28:0819
20#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 15:39:3321#include "webrtc/base/logging.h"
tommie4f96502015-10-21 06:00:4822#include "webrtc/base/trace_event.h"
Henrik Kjellanderff761fb2015-11-04 07:31:5223#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
sprang@webrtc.org779c3d12015-03-17 16:42:4924#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:3825#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
26#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
asaperssona9455ab2015-07-31 13:10:0927#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
danilchap74110612016-10-02 17:54:2928#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
29#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h"
niklase@google.com470e71d2011-07-07 08:21:2530
31namespace webrtc {
Sergey Ulanovec4f0682016-07-28 22:19:1032
brandtr6631e8a2016-09-13 10:23:2933namespace {
34constexpr size_t kRedForFecHeaderLength = 1;
danilchap74110612016-10-02 17:54:2935
36void BuildRedPayload(const RtpPacketToSend& media_packet,
37 RtpPacketToSend* red_packet) {
38 uint8_t* red_payload = red_packet->AllocatePayload(
39 kRedForFecHeaderLength + media_packet.payload_size());
40 RTC_DCHECK(red_payload);
41 red_payload[0] = media_packet.PayloadType();
42 memcpy(&red_payload[kRedForFecHeaderLength], media_packet.payload(),
43 media_packet.payload_size());
44}
brandtr6631e8a2016-09-13 10:23:2945} // namespace
niklase@google.com470e71d2011-07-07 08:21:2546
brandtrdbdb3f12016-11-10 13:04:4847RTPSenderVideo::RTPSenderVideo(Clock* clock,
48 RTPSender* rtp_sender,
49 FlexfecSender* flexfec_sender)
Sergey Ulanovec4f0682016-07-28 22:19:1050 : rtp_sender_(rtp_sender),
sprangcd349d92016-07-13 16:11:2851 clock_(clock),
brandtrd8048952016-11-07 10:08:5152 video_type_(kRtpVideoGeneric),
53 retransmission_settings_(kRetransmitBaseLayer),
54 last_rotation_(kVideoRotation_0),
brandtrd8048952016-11-07 10:08:5155 red_payload_type_(-1),
brandtrf1bb4762016-11-07 11:05:0656 ulpfec_payload_type_(-1),
brandtrdbdb3f12016-11-10 13:04:4857 flexfec_sender_(flexfec_sender),
brandtrd8048952016-11-07 10:08:5158 delta_fec_params_{0, 1, kFecMaskRandom},
59 key_fec_params_{0, 1, kFecMaskRandom},
sprangcd349d92016-07-13 16:11:2860 fec_bitrate_(1000, RateStatistics::kBpsScale),
danilchapc1600c52016-10-26 10:33:1161 video_bitrate_(1000, RateStatistics::kBpsScale) {
62 encoder_checker_.Detach();
63}
niklase@google.com470e71d2011-07-07 08:21:2564
Sergey Ulanovec4f0682016-07-28 22:19:1065RTPSenderVideo::~RTPSenderVideo() {}
niklase@google.com470e71d2011-07-07 08:21:2566
Sergey Ulanovec4f0682016-07-28 22:19:1067void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) {
68 video_type_ = video_type;
niklase@google.com470e71d2011-07-07 08:21:2569}
70
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:5571RtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const {
Sergey Ulanovec4f0682016-07-28 22:19:1072 return video_type_;
niklase@google.com470e71d2011-07-07 08:21:2573}
74
mflodmanfcf54bd2015-04-14 19:28:0875// Static.
76RtpUtility::Payload* RTPSenderVideo::CreateVideoPayload(
Sergey Ulanovec4f0682016-07-28 22:19:1077 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
78 int8_t payload_type) {
79 RtpVideoCodecTypes video_type = kRtpVideoGeneric;
80 if (RtpUtility::StringCompare(payload_name, "VP8", 3)) {
81 video_type = kRtpVideoVp8;
82 } else if (RtpUtility::StringCompare(payload_name, "VP9", 3)) {
83 video_type = kRtpVideoVp9;
84 } else if (RtpUtility::StringCompare(payload_name, "H264", 4)) {
85 video_type = kRtpVideoH264;
86 } else if (RtpUtility::StringCompare(payload_name, "I420", 4)) {
87 video_type = kRtpVideoGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:0688 } else {
Sergey Ulanovec4f0682016-07-28 22:19:1089 video_type = kRtpVideoGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:0690 }
mflodmanfcf54bd2015-04-14 19:28:0891 RtpUtility::Payload* payload = new RtpUtility::Payload();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:5992 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
Sergey Ulanovec4f0682016-07-28 22:19:1093 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
94 payload->typeSpecific.Video.videoCodecType = video_type;
pwestin@webrtc.org95cf4792012-01-20 06:59:0695 payload->audio = false;
mflodmanfcf54bd2015-04-14 19:28:0896 return payload;
niklase@google.com470e71d2011-07-07 08:21:2597}
98
danilchap74110612016-10-02 17:54:2999void RTPSenderVideo::SendVideoPacket(std::unique_ptr<RtpPacketToSend> packet,
mflodmanfcf54bd2015-04-14 19:28:08100 StorageType storage) {
danilchap74110612016-10-02 17:54:29101 // Remember some values about the packet before sending it away.
102 size_t packet_size = packet->size();
103 uint16_t seq_num = packet->SequenceNumber();
104 uint32_t rtp_timestamp = packet->Timestamp();
105 if (!rtp_sender_->SendToNetwork(std::move(packet), storage,
Sergey Ulanov525df3f2016-08-03 00:46:41106 RtpPacketSender::kLowPriority)) {
mflodmanfcf54bd2015-04-14 19:28:08107 LOG(LS_WARNING) << "Failed to send video packet " << seq_num;
Sergey Ulanov525df3f2016-08-03 00:46:41108 return;
mflodmanfcf54bd2015-04-14 19:28:08109 }
Sergey Ulanov525df3f2016-08-03 00:46:41110 rtc::CritScope cs(&stats_crit_);
danilchap74110612016-10-02 17:54:29111 video_bitrate_.Update(packet_size, clock_->TimeInMilliseconds());
Sergey Ulanov525df3f2016-08-03 00:46:41112 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
danilchape5b41412016-08-22 10:39:23113 "Video::PacketNormal", "timestamp", rtp_timestamp,
Sergey Ulanov525df3f2016-08-03 00:46:41114 "seqnum", seq_num);
mflodmanfcf54bd2015-04-14 19:28:08115}
niklase@google.com470e71d2011-07-07 08:21:25116
brandtr131bc492016-11-10 13:01:11117void RTPSenderVideo::SendVideoPacketAsRedMaybeWithUlpfec(
danilchap74110612016-10-02 17:54:29118 std::unique_ptr<RtpPacketToSend> media_packet,
119 StorageType media_packet_storage,
brandtr131bc492016-11-10 13:01:11120 bool protect_media_packet) {
danilchap74110612016-10-02 17:54:29121 uint32_t rtp_timestamp = media_packet->Timestamp();
122 uint16_t media_seq_num = media_packet->SequenceNumber();
123
124 std::unique_ptr<RtpPacketToSend> red_packet(
125 new RtpPacketToSend(*media_packet));
126 BuildRedPayload(*media_packet, red_packet.get());
127
brandtr74811e52016-08-10 07:51:50128 std::vector<std::unique_ptr<RedPacket>> fec_packets;
mflodmanfcf54bd2015-04-14 19:28:08129 StorageType fec_storage = kDontRetransmit;
mflodmanfcf54bd2015-04-14 19:28:08130 {
131 // Only protect while creating RED and FEC packets, not when sending.
danilchap7c9426c2016-04-14 10:05:31132 rtc::CritScope cs(&crit_);
danilchap74110612016-10-02 17:54:29133 red_packet->SetPayloadType(red_payload_type_);
brandtr131bc492016-11-10 13:01:11134 if (ulpfec_enabled()) {
135 if (protect_media_packet) {
136 ulpfec_generator_.AddRtpPacketAndGenerateFec(
137 media_packet->data(), media_packet->payload_size(),
138 media_packet->headers_size());
139 }
140 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets();
141 if (num_fec_packets > 0) {
142 uint16_t first_fec_sequence_number =
143 rtp_sender_->AllocateSequenceNumber(num_fec_packets);
144 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
145 red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number,
146 media_packet->headers_size());
147 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
148 if (retransmission_settings_ & kRetransmitFECPackets)
149 fec_storage = kAllowRetransmission;
150 }
mflodmanfcf54bd2015-04-14 19:28:08151 }
152 }
danilchap74110612016-10-02 17:54:29153 // Send |red_packet| instead of |packet| for allocated sequence number.
154 size_t red_packet_size = red_packet->size();
155 if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage,
156 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28157 rtc::CritScope cs(&stats_crit_);
danilchap74110612016-10-02 17:54:29158 video_bitrate_.Update(red_packet_size, clock_->TimeInMilliseconds());
sprang@webrtc.org0200f702015-02-16 12:06:00159 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
danilchape5b41412016-08-22 10:39:23160 "Video::PacketRed", "timestamp", rtp_timestamp,
mflodmanfcf54bd2015-04-14 19:28:08161 "seqnum", media_seq_num);
162 } else {
163 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num;
164 }
brandtr74811e52016-08-10 07:51:50165 for (const auto& fec_packet : fec_packets) {
brandtr869e7cd2016-10-31 12:27:07166 // TODO(danilchap): Make ulpfec_generator_ generate RtpPacketToSend to avoid
danilchap74110612016-10-02 17:54:29167 // reparsing them.
168 std::unique_ptr<RtpPacketToSend> rtp_packet(
169 new RtpPacketToSend(*media_packet));
170 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length()));
171 rtp_packet->set_capture_time_ms(media_packet->capture_time_ms());
172 uint16_t fec_sequence_number = rtp_packet->SequenceNumber();
173 if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage,
174 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28175 rtc::CritScope cs(&stats_crit_);
176 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
sprang@webrtc.org0200f702015-02-16 12:06:00177 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
brandtr131bc492016-11-10 13:01:11178 "Video::PacketUlpfec", "timestamp", rtp_timestamp,
danilchap74110612016-10-02 17:54:29179 "seqnum", fec_sequence_number);
mflodmanfcf54bd2015-04-14 19:28:08180 } else {
brandtr131bc492016-11-10 13:01:11181 LOG(LS_WARNING) << "Failed to send ULPFEC packet " << fec_sequence_number;
182 }
183 }
184}
185
186void RTPSenderVideo::SendVideoPacketWithFlexfec(
187 std::unique_ptr<RtpPacketToSend> media_packet,
188 StorageType media_packet_storage,
189 bool protect_media_packet) {
190 RTC_DCHECK(flexfec_sender_);
191
192 if (protect_media_packet)
193 flexfec_sender_->AddRtpPacketAndGenerateFec(*media_packet);
194
195 SendVideoPacket(std::move(media_packet), media_packet_storage);
196
197 if (flexfec_sender_->FecAvailable()) {
198 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
199 flexfec_sender_->GetFecPackets();
200 for (auto& fec_packet : fec_packets) {
201 uint32_t timestamp = fec_packet->Timestamp();
202 uint16_t seq_num = fec_packet->SequenceNumber();
203 if (rtp_sender_->SendToNetwork(std::move(fec_packet), kDontRetransmit,
204 RtpPacketSender::kLowPriority)) {
205 // TODO(brandtr): Wire up stats here.
206 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
207 "Video::PacketFlexfec", "timestamp", timestamp,
208 "seqnum", seq_num);
209 } else {
210 LOG(LS_WARNING) << "Failed to send FlexFEC packet " << seq_num;
211 }
stefan@webrtc.orgfbea4e52011-10-27 16:08:29212 }
stefan@webrtc.orge0d6fa42012-03-20 22:10:56213 }
niklase@google.com470e71d2011-07-07 08:21:25214}
215
brandtrf1bb4762016-11-07 11:05:06216void RTPSenderVideo::SetUlpfecConfig(int red_payload_type,
brandtrd8048952016-11-07 10:08:51217 int ulpfec_payload_type) {
brandtrf1bb4762016-11-07 11:05:06218 // Sanity check. Per the definition of UlpfecConfig (see config.h),
219 // a payload type of -1 means that the corresponding feature is
220 // turned off.
221 RTC_DCHECK_GE(red_payload_type, -1);
brandtrd8048952016-11-07 10:08:51222 RTC_DCHECK_LE(red_payload_type, 127);
brandtrf1bb4762016-11-07 11:05:06223 RTC_DCHECK_GE(ulpfec_payload_type, -1);
brandtrd8048952016-11-07 10:08:51224 RTC_DCHECK_LE(ulpfec_payload_type, 127);
225
danilchap7c9426c2016-04-14 10:05:31226 rtc::CritScope cs(&crit_);
brandtrd8048952016-11-07 10:08:51227 red_payload_type_ = red_payload_type;
brandtrf1bb4762016-11-07 11:05:06228 ulpfec_payload_type_ = ulpfec_payload_type;
229
230 // Must not enable ULPFEC without RED.
231 // TODO(brandtr): We currently support enabling RED without ULPFEC. Change
232 // this when we have removed the RED/RTX send-side workaround, so that we
233 // ensure that RED and ULPFEC are only enabled together.
234 RTC_DCHECK(red_enabled() || !ulpfec_enabled());
brandtrd8048952016-11-07 10:08:51235
brandtr131bc492016-11-10 13:01:11236 // Reset FEC parameters.
Sergey Ulanovec4f0682016-07-28 22:19:10237 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
238 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
niklase@google.com470e71d2011-07-07 08:21:25239}
240
brandtrf1bb4762016-11-07 11:05:06241void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type,
brandtrd8048952016-11-07 10:08:51242 int* ulpfec_payload_type) const {
danilchap7c9426c2016-04-14 10:05:31243 rtc::CritScope cs(&crit_);
brandtrd8048952016-11-07 10:08:51244 *red_payload_type = red_payload_type_;
brandtrf1bb4762016-11-07 11:05:06245 *ulpfec_payload_type = ulpfec_payload_type_;
niklase@google.com470e71d2011-07-07 08:21:25246}
247
brandtr6631e8a2016-09-13 10:23:29248size_t RTPSenderVideo::FecPacketOverhead() const {
brandtr131bc492016-11-10 13:01:11249 if (flexfec_enabled())
250 return flexfec_sender_->MaxPacketOverhead();
251
danilchap7c9426c2016-04-14 10:05:31252 rtc::CritScope cs(&crit_);
stefan8f4c77f2016-06-03 07:16:45253 size_t overhead = 0;
brandtrf1bb4762016-11-07 11:05:06254 if (red_enabled()) {
brandtr131bc492016-11-10 13:01:11255 // The RED overhead is due to a small header.
256 overhead += kRedForFecHeaderLength;
257 }
258 if (ulpfec_enabled()) {
259 // For ULPFEC, the overhead is the FEC headers plus RED for FEC header
260 // (see above) plus anything in RTP header beyond the 12 bytes base header
261 // (CSRC list, extensions...)
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55262 // This reason for the header extensions to be included here is that
263 // from an FEC viewpoint, they are part of the payload to be protected.
264 // (The base RTP header is already protected by the FEC header.)
brandtr131bc492016-11-10 13:01:11265 overhead += ulpfec_generator_.MaxPacketOverhead() +
266 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55267 }
stefan8f4c77f2016-06-03 07:16:45268 return overhead;
niklase@google.com470e71d2011-07-07 08:21:25269}
270
brandtr1743a192016-11-07 11:36:05271void RTPSenderVideo::SetFecParameters(const FecProtectionParams& delta_params,
272 const FecProtectionParams& key_params) {
danilchap7c9426c2016-04-14 10:05:31273 rtc::CritScope cs(&crit_);
brandtr131bc492016-11-10 13:01:11274 delta_fec_params_ = delta_params;
275 key_fec_params_ = key_params;
marpan@google.com80c5d7a2011-07-15 21:32:40276}
277
Sergey Ulanov525df3f2016-08-03 00:46:41278bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
279 FrameType frame_type,
280 int8_t payload_type,
danilchape5b41412016-08-22 10:39:23281 uint32_t rtp_timestamp,
Sergey Ulanov525df3f2016-08-03 00:46:41282 int64_t capture_time_ms,
283 const uint8_t* payload_data,
284 size_t payload_size,
285 const RTPFragmentationHeader* fragmentation,
286 const RTPVideoHeader* video_header) {
danilchapc1600c52016-10-26 10:33:11287 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_checker_);
Sergey Ulanov525df3f2016-08-03 00:46:41288 if (payload_size == 0)
289 return false;
niklase@google.com470e71d2011-07-07 08:21:25290
danilchap74110612016-10-02 17:54:29291 // Create header that will be reused in all packets.
292 std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket();
293 rtp_header->SetPayloadType(payload_type);
294 rtp_header->SetTimestamp(rtp_timestamp);
295 rtp_header->set_capture_time_ms(capture_time_ms);
296 // According to
297 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
298 // ts_126114v120700p.pdf Section 7.4.5:
299 // The MTSI client shall add the payload bytes as defined in this clause
300 // onto the last RTP packet in each group of packets which make up a key
301 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
302 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP
303 // packet in each group of packets which make up another type of frame
304 // (e.g. a P-Frame) only if the current value is different from the previous
305 // value sent.
danilchapc1600c52016-10-26 10:33:11306 if (video_header) {
307 // Set rotation when key frame or when changed (to follow standard).
308 // Or when different from 0 (to follow current receiver implementation).
309 VideoRotation current_rotation = video_header->rotation;
310 if (frame_type == kVideoFrameKey || current_rotation != last_rotation_ ||
311 current_rotation != kVideoRotation_0)
312 rtp_header->SetExtension<VideoOrientation>(current_rotation);
313 last_rotation_ = current_rotation;
314 }
danilchap74110612016-10-02 17:54:29315
316 size_t packet_capacity = rtp_sender_->MaxPayloadLength() -
317 FecPacketOverhead() -
318 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0);
319 RTC_DCHECK_LE(packet_capacity, rtp_header->capacity());
320 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size());
321 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size();
322
kwiberg84be5112016-04-27 08:19:58323 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
danilchap74110612016-10-02 17:54:29324 video_type, max_data_payload_length,
Sergey Ulanovec4f0682016-07-28 22:19:10325 video_header ? &(video_header->codecHeader) : nullptr, frame_type));
mflodmanfcf54bd2015-04-14 19:28:08326
Peter Boströme23e7372015-10-08 09:44:14327 StorageType storage;
brandtrf1bb4762016-11-07 11:05:06328 bool red_enabled;
skvlad98bb6642016-04-07 22:36:45329 bool first_frame = first_frame_sent_();
mflodmanfcf54bd2015-04-14 19:28:08330 {
danilchap7c9426c2016-04-14 10:05:31331 rtc::CritScope cs(&crit_);
brandtr131bc492016-11-10 13:01:11332
333 // Media packet storage.
334 storage = packetizer->GetStorageType(retransmission_settings_);
335
336 // FEC settings.
brandtr1743a192016-11-07 11:36:05337 const FecProtectionParams& fec_params =
338 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_;
brandtr131bc492016-11-10 13:01:11339 if (flexfec_enabled())
340 flexfec_sender_->SetFecParameters(fec_params);
brandtrf1bb4762016-11-07 11:05:06341 red_enabled = this->red_enabled();
brandtr131bc492016-11-10 13:01:11342 if (ulpfec_enabled())
343 ulpfec_generator_.SetFecParameters(fec_params);
stefan@webrtc.org2ec56062014-07-31 14:59:24344 }
niklase@google.com470e71d2011-07-07 08:21:25345
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55346 // TODO(changbin): we currently don't support to configure the codec to
347 // output multiple partitions for VP8. Should remove below check after the
348 // issue is fixed.
349 const RTPFragmentationHeader* frag =
Sergey Ulanovec4f0682016-07-28 22:19:10350 (video_type == kRtpVideoVp8) ? NULL : fragmentation;
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55351
danilchap74110612016-10-02 17:54:29352 packetizer->SetPayloadData(payload_data, payload_size, frag);
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55353
skvlad98bb6642016-04-07 22:36:45354 bool first = true;
stefan@webrtc.org2ec56062014-07-31 14:59:24355 bool last = false;
stefan@webrtc.org2ec56062014-07-31 14:59:24356 while (!last) {
danilchap74110612016-10-02 17:54:29357 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header));
358 uint8_t* payload = packet->AllocatePayload(max_data_payload_length);
359 RTC_DCHECK(payload);
360
stefan@webrtc.org2ec56062014-07-31 14:59:24361 size_t payload_bytes_in_packet = 0;
danilchap74110612016-10-02 17:54:29362 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last))
Sergey Ulanov525df3f2016-08-03 00:46:41363 return false;
isheriff6b4b5f32016-06-08 07:24:21364
danilchap74110612016-10-02 17:54:29365 packet->SetPayloadSize(payload_bytes_in_packet);
366 packet->SetMarker(last);
367 if (!rtp_sender_->AssignSequenceNumber(packet.get()))
368 return false;
369
brandtr131bc492016-11-10 13:01:11370 const bool protect_packet =
371 (packetizer->GetProtectionType() == kProtectedPacket);
372 if (flexfec_enabled()) {
373 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender
374 // is wired up to PacedSender instead.
375 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet);
376 } else if (red_enabled) {
377 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage,
378 protect_packet);
mflodmanfcf54bd2015-04-14 19:28:08379 } else {
danilchap74110612016-10-02 17:54:29380 SendVideoPacket(std::move(packet), storage);
stefan@webrtc.org2ec56062014-07-31 14:59:24381 }
skvlad98bb6642016-04-07 22:36:45382
383 if (first_frame) {
384 if (first) {
385 LOG(LS_INFO)
386 << "Sent first RTP packet of the first video frame (pre-pacer)";
387 }
388 if (last) {
389 LOG(LS_INFO)
390 << "Sent last RTP packet of the first video frame (pre-pacer)";
391 }
392 }
393 first = false;
stefan@webrtc.org2ec56062014-07-31 14:59:24394 }
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55395
Sergey Ulanovec4f0682016-07-28 22:19:10396 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
danilchape5b41412016-08-22 10:39:23397 rtp_timestamp);
Sergey Ulanov525df3f2016-08-03 00:46:41398 return true;
mflodmanfcf54bd2015-04-14 19:28:08399}
400
pbos@webrtc.org2f446732013-04-08 11:08:41401uint32_t RTPSenderVideo::VideoBitrateSent() const {
sprangcd349d92016-07-13 16:11:28402 rtc::CritScope cs(&stats_crit_);
403 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgfbea4e52011-10-27 16:08:29404}
405
pbos@webrtc.org2f446732013-04-08 11:08:41406uint32_t RTPSenderVideo::FecOverheadRate() const {
sprangcd349d92016-07-13 16:11:28407 rtc::CritScope cs(&stats_crit_);
408 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgd0bdab02011-10-14 14:24:54409}
410
stefan@webrtc.org6a4bef42011-12-22 12:52:41411int RTPSenderVideo::SelectiveRetransmissions() const {
danilchap7c9426c2016-04-14 10:05:31412 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10413 return retransmission_settings_;
stefan@webrtc.org6a4bef42011-12-22 12:52:41414}
415
mflodmanfcf54bd2015-04-14 19:28:08416void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
danilchap7c9426c2016-04-14 10:05:31417 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10418 retransmission_settings_ = settings;
stefan@webrtc.org6a4bef42011-12-22 12:52:41419}
420
pbos@webrtc.orgd900e8b2013-07-03 15:12:26421} // namespace webrtc