blob: fd36d763e12a5bcaaee38197bbc915d1011cb293 [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>
18
19#include "webrtc/base/checks.h"
Peter Boströmebc0b4e2015-10-28 15:39:3320#include "webrtc/base/logging.h"
tommie4f96502015-10-21 06:00:4821#include "webrtc/base/trace_event.h"
Henrik Kjellanderff761fb2015-11-04 07:31:5222#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
sprang@webrtc.org779c3d12015-03-17 16:42:4923#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:3824#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_vp8.h"
asaperssona9455ab2015-07-31 13:10:0927#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h"
niklase@google.com470e71d2011-07-07 08:21:2528
29namespace webrtc {
Sergey Ulanovec4f0682016-07-28 22:19:1030
niklase@google.com470e71d2011-07-07 08:21:2531enum { REDForFECHeaderLength = 1 };
32
Sergey Ulanovec4f0682016-07-28 22:19:1033RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtp_sender)
34 : rtp_sender_(rtp_sender),
sprangcd349d92016-07-13 16:11:2835 clock_(clock),
sprang@webrtc.org6811b6e2013-12-13 09:46:5936 // Generic FEC
Stefan Holmer4654d202015-12-08 08:10:4337 producer_fec_(&fec_),
sprangcd349d92016-07-13 16:11:2838 fec_bitrate_(1000, RateStatistics::kBpsScale),
Sergey Ulanovec4f0682016-07-28 22:19:1039 video_bitrate_(1000, RateStatistics::kBpsScale) {}
niklase@google.com470e71d2011-07-07 08:21:2540
Sergey Ulanovec4f0682016-07-28 22:19:1041RTPSenderVideo::~RTPSenderVideo() {}
niklase@google.com470e71d2011-07-07 08:21:2542
Sergey Ulanovec4f0682016-07-28 22:19:1043void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) {
44 video_type_ = video_type;
niklase@google.com470e71d2011-07-07 08:21:2545}
46
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:5547RtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const {
Sergey Ulanovec4f0682016-07-28 22:19:1048 return video_type_;
niklase@google.com470e71d2011-07-07 08:21:2549}
50
mflodmanfcf54bd2015-04-14 19:28:0851// Static.
52RtpUtility::Payload* RTPSenderVideo::CreateVideoPayload(
Sergey Ulanovec4f0682016-07-28 22:19:1053 const char payload_name[RTP_PAYLOAD_NAME_SIZE],
54 int8_t payload_type) {
55 RtpVideoCodecTypes video_type = kRtpVideoGeneric;
56 if (RtpUtility::StringCompare(payload_name, "VP8", 3)) {
57 video_type = kRtpVideoVp8;
58 } else if (RtpUtility::StringCompare(payload_name, "VP9", 3)) {
59 video_type = kRtpVideoVp9;
60 } else if (RtpUtility::StringCompare(payload_name, "H264", 4)) {
61 video_type = kRtpVideoH264;
62 } else if (RtpUtility::StringCompare(payload_name, "I420", 4)) {
63 video_type = kRtpVideoGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:0664 } else {
Sergey Ulanovec4f0682016-07-28 22:19:1065 video_type = kRtpVideoGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:0666 }
mflodmanfcf54bd2015-04-14 19:28:0867 RtpUtility::Payload* payload = new RtpUtility::Payload();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:5968 payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
Sergey Ulanovec4f0682016-07-28 22:19:1069 strncpy(payload->name, payload_name, RTP_PAYLOAD_NAME_SIZE - 1);
70 payload->typeSpecific.Video.videoCodecType = video_type;
pwestin@webrtc.org95cf4792012-01-20 06:59:0671 payload->audio = false;
mflodmanfcf54bd2015-04-14 19:28:0872 return payload;
niklase@google.com470e71d2011-07-07 08:21:2573}
74
mflodmanfcf54bd2015-04-14 19:28:0875void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer,
Sergey Ulanovec4f0682016-07-28 22:19:1076 size_t payload_length,
77 size_t rtp_header_length,
mflodmanfcf54bd2015-04-14 19:28:0878 uint16_t seq_num,
Sergey Ulanovec4f0682016-07-28 22:19:1079 uint32_t capture_timestamp,
mflodmanfcf54bd2015-04-14 19:28:0880 int64_t capture_time_ms,
81 StorageType storage) {
Sergey Ulanov525df3f2016-08-03 00:46:4182 if (!rtp_sender_->SendToNetwork(data_buffer, payload_length,
83 rtp_header_length, capture_time_ms, storage,
84 RtpPacketSender::kLowPriority)) {
mflodmanfcf54bd2015-04-14 19:28:0885 LOG(LS_WARNING) << "Failed to send video packet " << seq_num;
Sergey Ulanov525df3f2016-08-03 00:46:4186 return;
mflodmanfcf54bd2015-04-14 19:28:0887 }
Sergey Ulanov525df3f2016-08-03 00:46:4188 rtc::CritScope cs(&stats_crit_);
89 video_bitrate_.Update(payload_length + rtp_header_length,
90 clock_->TimeInMilliseconds());
91 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
92 "Video::PacketNormal", "timestamp", capture_timestamp,
93 "seqnum", seq_num);
mflodmanfcf54bd2015-04-14 19:28:0894}
niklase@google.com470e71d2011-07-07 08:21:2595
mflodmanfcf54bd2015-04-14 19:28:0896void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer,
Sergey Ulanovec4f0682016-07-28 22:19:1097 size_t payload_length,
98 size_t rtp_header_length,
mflodmanfcf54bd2015-04-14 19:28:0899 uint16_t media_seq_num,
Sergey Ulanovec4f0682016-07-28 22:19:10100 uint32_t capture_timestamp,
mflodmanfcf54bd2015-04-14 19:28:08101 int64_t capture_time_ms,
102 StorageType media_packet_storage,
103 bool protect) {
kwiberg84be5112016-04-27 08:19:58104 std::unique_ptr<RedPacket> red_packet;
mflodmanfcf54bd2015-04-14 19:28:08105 std::vector<RedPacket*> fec_packets;
106 StorageType fec_storage = kDontRetransmit;
107 uint16_t next_fec_sequence_number = 0;
108 {
109 // Only protect while creating RED and FEC packets, not when sending.
danilchap7c9426c2016-04-14 10:05:31110 rtc::CritScope cs(&crit_);
mflodmanfcf54bd2015-04-14 19:28:08111 red_packet.reset(producer_fec_.BuildRedPacket(
Stefan Holmer4654d202015-12-08 08:10:43112 data_buffer, payload_length, rtp_header_length, red_payload_type_));
mflodmanfcf54bd2015-04-14 19:28:08113 if (protect) {
114 producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, payload_length,
115 rtp_header_length);
116 }
117 uint16_t num_fec_packets = producer_fec_.NumAvailableFecPackets();
118 if (num_fec_packets > 0) {
119 next_fec_sequence_number =
Sergey Ulanovec4f0682016-07-28 22:19:10120 rtp_sender_->AllocateSequenceNumber(num_fec_packets);
mflodmanfcf54bd2015-04-14 19:28:08121 fec_packets = producer_fec_.GetFecPackets(
Stefan Holmer4654d202015-12-08 08:10:43122 red_payload_type_, fec_payload_type_, next_fec_sequence_number,
mflodmanfcf54bd2015-04-14 19:28:08123 rtp_header_length);
henrikg91d6ede2015-09-17 07:24:34124 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
Sergey Ulanovec4f0682016-07-28 22:19:10125 if (retransmission_settings_ & kRetransmitFECPackets)
mflodmanfcf54bd2015-04-14 19:28:08126 fec_storage = kAllowRetransmission;
127 }
128 }
Sergey Ulanovec4f0682016-07-28 22:19:10129 if (rtp_sender_->SendToNetwork(
mflodmanfcf54bd2015-04-14 19:28:08130 red_packet->data(), red_packet->length() - rtp_header_length,
131 rtp_header_length, capture_time_ms, media_packet_storage,
Sergey Ulanov525df3f2016-08-03 00:46:41132 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28133 rtc::CritScope cs(&stats_crit_);
134 video_bitrate_.Update(red_packet->length(), clock_->TimeInMilliseconds());
sprang@webrtc.org0200f702015-02-16 12:06:00135 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
136 "Video::PacketRed", "timestamp", capture_timestamp,
mflodmanfcf54bd2015-04-14 19:28:08137 "seqnum", media_seq_num);
138 } else {
139 LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num;
140 }
141 for (RedPacket* fec_packet : fec_packets) {
Sergey Ulanovec4f0682016-07-28 22:19:10142 if (rtp_sender_->SendToNetwork(
mflodmanfcf54bd2015-04-14 19:28:08143 fec_packet->data(), fec_packet->length() - rtp_header_length,
144 rtp_header_length, capture_time_ms, fec_storage,
Sergey Ulanov525df3f2016-08-03 00:46:41145 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28146 rtc::CritScope cs(&stats_crit_);
147 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
sprang@webrtc.org0200f702015-02-16 12:06:00148 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
149 "Video::PacketFec", "timestamp", capture_timestamp,
mflodmanfcf54bd2015-04-14 19:28:08150 "seqnum", next_fec_sequence_number);
151 } else {
152 LOG(LS_WARNING) << "Failed to send FEC packet "
153 << next_fec_sequence_number;
stefan@webrtc.orgfbea4e52011-10-27 16:08:29154 }
mflodmanfcf54bd2015-04-14 19:28:08155 delete fec_packet;
156 ++next_fec_sequence_number;
stefan@webrtc.orge0d6fa42012-03-20 22:10:56157 }
niklase@google.com470e71d2011-07-07 08:21:25158}
159
Sergey Ulanovec4f0682016-07-28 22:19:10160void RTPSenderVideo::SetGenericFECStatus(bool enable,
161 uint8_t payload_type_red,
162 uint8_t payload_type_fec) {
163 RTC_DCHECK(!enable || payload_type_red > 0);
danilchap7c9426c2016-04-14 10:05:31164 rtc::CritScope cs(&crit_);
Stefan Holmer4654d202015-12-08 08:10:43165 fec_enabled_ = enable;
Sergey Ulanovec4f0682016-07-28 22:19:10166 red_payload_type_ = payload_type_red;
167 fec_payload_type_ = payload_type_fec;
168 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
169 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
niklase@google.com470e71d2011-07-07 08:21:25170}
171
danilchap6db6cdc2015-12-15 10:54:47172void RTPSenderVideo::GenericFECStatus(bool* enable,
Sergey Ulanovec4f0682016-07-28 22:19:10173 uint8_t* payload_type_red,
174 uint8_t* payload_type_fec) const {
danilchap7c9426c2016-04-14 10:05:31175 rtc::CritScope cs(&crit_);
danilchap6db6cdc2015-12-15 10:54:47176 *enable = fec_enabled_;
Sergey Ulanovec4f0682016-07-28 22:19:10177 *payload_type_red = red_payload_type_;
178 *payload_type_fec = fec_payload_type_;
niklase@google.com470e71d2011-07-07 08:21:25179}
180
pkasting@chromium.org4591fbd2014-11-20 22:28:14181size_t RTPSenderVideo::FECPacketOverhead() const {
danilchap7c9426c2016-04-14 10:05:31182 rtc::CritScope cs(&crit_);
stefan8f4c77f2016-06-03 07:16:45183 size_t overhead = 0;
184 if (red_payload_type_ != 0) {
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55185 // Overhead is FEC headers plus RED for FEC header plus anything in RTP
186 // header beyond the 12 bytes base header (CSRC list, extensions...)
187 // This reason for the header extensions to be included here is that
188 // from an FEC viewpoint, they are part of the payload to be protected.
189 // (The base RTP header is already protected by the FEC header.)
isheriff6b4b5f32016-06-08 07:24:21190 return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength +
Sergey Ulanovec4f0682016-07-28 22:19:10191 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55192 }
stefan8f4c77f2016-06-03 07:16:45193 if (fec_enabled_)
194 overhead += ForwardErrorCorrection::PacketOverhead();
195 return overhead;
niklase@google.com470e71d2011-07-07 08:21:25196}
197
mflodmanfcf54bd2015-04-14 19:28:08198void RTPSenderVideo::SetFecParameters(const FecProtectionParams* delta_params,
199 const FecProtectionParams* key_params) {
danilchap7c9426c2016-04-14 10:05:31200 rtc::CritScope cs(&crit_);
henrikg91d6ede2015-09-17 07:24:34201 RTC_DCHECK(delta_params);
202 RTC_DCHECK(key_params);
stefan8f4c77f2016-06-03 07:16:45203 if (fec_enabled_) {
204 delta_fec_params_ = *delta_params;
205 key_fec_params_ = *key_params;
206 }
marpan@google.com80c5d7a2011-07-15 21:32:40207}
208
Sergey Ulanov525df3f2016-08-03 00:46:41209bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
210 FrameType frame_type,
211 int8_t payload_type,
212 uint32_t capture_timestamp,
213 int64_t capture_time_ms,
214 const uint8_t* payload_data,
215 size_t payload_size,
216 const RTPFragmentationHeader* fragmentation,
217 const RTPVideoHeader* video_header) {
218 if (payload_size == 0)
219 return false;
niklase@google.com470e71d2011-07-07 08:21:25220
kwiberg84be5112016-04-27 08:19:58221 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
Sergey Ulanovec4f0682016-07-28 22:19:10222 video_type, rtp_sender_->MaxDataPayloadLength(),
223 video_header ? &(video_header->codecHeader) : nullptr, frame_type));
mflodmanfcf54bd2015-04-14 19:28:08224
Peter Boströme23e7372015-10-08 09:44:14225 StorageType storage;
stefan8f4c77f2016-06-03 07:16:45226 int red_payload_type;
skvlad98bb6642016-04-07 22:36:45227 bool first_frame = first_frame_sent_();
mflodmanfcf54bd2015-04-14 19:28:08228 {
danilchap7c9426c2016-04-14 10:05:31229 rtc::CritScope cs(&crit_);
mflodmanfcf54bd2015-04-14 19:28:08230 FecProtectionParams* fec_params =
Sergey Ulanovec4f0682016-07-28 22:19:10231 frame_type == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_;
mflodmanfcf54bd2015-04-14 19:28:08232 producer_fec_.SetFecParameters(fec_params, 0);
Sergey Ulanovec4f0682016-07-28 22:19:10233 storage = packetizer->GetStorageType(retransmission_settings_);
stefan8f4c77f2016-06-03 07:16:45234 red_payload_type = red_payload_type_;
stefan@webrtc.org2ec56062014-07-31 14:59:24235 }
niklase@google.com470e71d2011-07-07 08:21:25236
Guo-wei Shieh64c1e8c2015-04-01 22:33:06237 // Register CVO rtp header extension at the first time when we receive a frame
238 // with pending rotation.
isheriff6b4b5f32016-06-08 07:24:21239 bool video_rotation_active = false;
Peter Boströmc0ae3052016-02-08 14:00:16240 if (video_header && video_header->rotation != kVideoRotation_0) {
Sergey Ulanovec4f0682016-07-28 22:19:10241 video_rotation_active = rtp_sender_->ActivateCVORtpHeaderExtension();
Guo-wei Shieh64c1e8c2015-04-01 22:33:06242 }
243
Sergey Ulanovec4f0682016-07-28 22:19:10244 int rtp_header_length = rtp_sender_->RtpHeaderLength();
245 size_t payload_bytes_to_send = payload_size;
246 const uint8_t* data = payload_data;
stefan@webrtc.org2ec56062014-07-31 14:59:24247
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55248 // TODO(changbin): we currently don't support to configure the codec to
249 // output multiple partitions for VP8. Should remove below check after the
250 // issue is fixed.
251 const RTPFragmentationHeader* frag =
Sergey Ulanovec4f0682016-07-28 22:19:10252 (video_type == kRtpVideoVp8) ? NULL : fragmentation;
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55253
254 packetizer->SetPayloadData(data, payload_bytes_to_send, frag);
255
skvlad98bb6642016-04-07 22:36:45256 bool first = true;
stefan@webrtc.org2ec56062014-07-31 14:59:24257 bool last = false;
stefan@webrtc.org2ec56062014-07-31 14:59:24258 while (!last) {
stefan@webrtc.org2ec56062014-07-31 14:59:24259 uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
260 size_t payload_bytes_in_packet = 0;
isheriff6b4b5f32016-06-08 07:24:21261
mflodmanfcf54bd2015-04-14 19:28:08262 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length],
263 &payload_bytes_in_packet, &last)) {
Sergey Ulanov525df3f2016-08-03 00:46:41264 return false;
stefan@webrtc.org2ec56062014-07-31 14:59:24265 }
skvlad98bb6642016-04-07 22:36:45266
stefan@webrtc.org2ec56062014-07-31 14:59:24267 // Write RTP header.
danilchap32cd2c42016-08-01 13:58:34268 int32_t header_length = rtp_sender_->BuildRtpHeader(
269 dataBuffer, payload_type, last, capture_timestamp, capture_time_ms);
270 if (header_length <= 0)
Sergey Ulanov525df3f2016-08-03 00:46:41271 return false;
isheriff6b4b5f32016-06-08 07:24:21272
guoweis@webrtc.org45362892015-03-04 22:55:15273 // According to
274 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
275 // ts_126114v120700p.pdf Section 7.4.5:
276 // The MTSI client shall add the payload bytes as defined in this clause
277 // onto the last RTP packet in each group of packets which make up a key
278 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
279 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP
280 // packet in each group of packets which make up another type of frame
281 // (e.g. a P-Frame) only if the current value is different from the previous
282 // value sent.
Guo-wei Shieh64c1e8c2015-04-01 22:33:06283 // Here we are adding it to every packet of every frame at this point.
Peter Boströmc0ae3052016-02-08 14:00:16284 if (!video_header) {
Sergey Ulanovec4f0682016-07-28 22:19:10285 RTC_DCHECK(!rtp_sender_->IsRtpHeaderExtensionRegistered(
guoweis@webrtc.org45362892015-03-04 22:55:15286 kRtpExtensionVideoRotation));
isheriff6b4b5f32016-06-08 07:24:21287 } else if (video_rotation_active) {
guoweis@webrtc.org45362892015-03-04 22:55:15288 // Checking whether CVO header extension is registered will require taking
289 // a lock. It'll be a no-op if it's not registered.
Guo-wei Shieh64c1e8c2015-04-01 22:33:06290 // TODO(guoweis): For now, all packets sent will carry the CVO such that
291 // the RTP header length is consistent, although the receiver side will
Stefan Holmer586b19b2015-09-18 09:14:31292 // only exam the packets with marker bit set.
Sergey Ulanovec4f0682016-07-28 22:19:10293 size_t packetSize = payload_size + rtp_header_length;
guoweis@webrtc.org45362892015-03-04 22:55:15294 RtpUtility::RtpHeaderParser rtp_parser(dataBuffer, packetSize);
295 RTPHeader rtp_header;
danilchapf6975f42015-12-28 18:18:46296 rtp_parser.Parse(&rtp_header);
Sergey Ulanovec4f0682016-07-28 22:19:10297 rtp_sender_->UpdateVideoRotation(dataBuffer, packetSize, rtp_header,
298 video_header->rotation);
guoweis@webrtc.org45362892015-03-04 22:55:15299 }
stefan8f4c77f2016-06-03 07:16:45300 if (red_payload_type != 0) {
mflodmanfcf54bd2015-04-14 19:28:08301 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet,
Sergey Ulanovec4f0682016-07-28 22:19:10302 rtp_header_length, rtp_sender_->SequenceNumber(),
303 capture_timestamp, capture_time_ms, storage,
mflodmanfcf54bd2015-04-14 19:28:08304 packetizer->GetProtectionType() == kProtectedPacket);
305 } else {
306 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length,
Sergey Ulanovec4f0682016-07-28 22:19:10307 rtp_sender_->SequenceNumber(), capture_timestamp,
mflodmanfcf54bd2015-04-14 19:28:08308 capture_time_ms, storage);
stefan@webrtc.org2ec56062014-07-31 14:59:24309 }
skvlad98bb6642016-04-07 22:36:45310
311 if (first_frame) {
312 if (first) {
313 LOG(LS_INFO)
314 << "Sent first RTP packet of the first video frame (pre-pacer)";
315 }
316 if (last) {
317 LOG(LS_INFO)
318 << "Sent last RTP packet of the first video frame (pre-pacer)";
319 }
320 }
321 first = false;
stefan@webrtc.org2ec56062014-07-31 14:59:24322 }
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55323
Sergey Ulanovec4f0682016-07-28 22:19:10324 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
325 rtp_sender_->Timestamp());
Sergey Ulanov525df3f2016-08-03 00:46:41326 return true;
mflodmanfcf54bd2015-04-14 19:28:08327}
328
pbos@webrtc.org2f446732013-04-08 11:08:41329uint32_t RTPSenderVideo::VideoBitrateSent() const {
sprangcd349d92016-07-13 16:11:28330 rtc::CritScope cs(&stats_crit_);
331 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgfbea4e52011-10-27 16:08:29332}
333
pbos@webrtc.org2f446732013-04-08 11:08:41334uint32_t RTPSenderVideo::FecOverheadRate() const {
sprangcd349d92016-07-13 16:11:28335 rtc::CritScope cs(&stats_crit_);
336 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgd0bdab02011-10-14 14:24:54337}
338
stefan@webrtc.org6a4bef42011-12-22 12:52:41339int RTPSenderVideo::SelectiveRetransmissions() const {
danilchap7c9426c2016-04-14 10:05:31340 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10341 return retransmission_settings_;
stefan@webrtc.org6a4bef42011-12-22 12:52:41342}
343
mflodmanfcf54bd2015-04-14 19:28:08344void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
danilchap7c9426c2016-04-14 10:05:31345 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10346 retransmission_settings_ = settings;
stefan@webrtc.org6a4bef42011-12-22 12:52:41347}
348
pbos@webrtc.orgd900e8b2013-07-03 15:12:26349} // namespace webrtc