1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" 12cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org 13cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include <assert.h> 14cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include <stdlib.h> 15cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include <string.h> 16cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org 173e4cdeca70f8a9499fb746fa4e9a094a449dda86sprang@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" 18cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 19cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" 20cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" 21cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 22cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 2399681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 24cbd78ae09f44b003a9969536b78f08cd1ff513e8pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace_event.h" 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgenum { REDForFECHeaderLength = 1 }; 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstruct RtpPacket { 30b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org uint16_t rtpHeaderLength; 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ForwardErrorCorrection::Packet* pkt; 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}; 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 34b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgRTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender) 3599681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org : _rtpSender(*rtpSender), 36b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()), 37b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _videoType(kRtpVideoGeneric), 38b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _videoCodecInformation(NULL), 39b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _maxBitrate(0), 40b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _retransmissionSettings(kRetransmitBaseLayer), 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 42b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org // Generic FEC 4399681317b0a9dc29c1682a17908f382eac16bd2aandresp@webrtc.org _fec(), 44b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _fecEnabled(false), 45b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _payloadTypeRED(-1), 46b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _payloadTypeFEC(-1), 47b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _numberFirstPartition(0), 48b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org delta_fec_params_(), 49b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org key_fec_params_(), 50b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org producer_fec_(&_fec), 51b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _fecOverheadRate(clock, NULL), 52b70db6dbe962f01976f2e1e9a4141c1ee37e3801sprang@webrtc.org _videoBitrate(clock, NULL) { 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = 57b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org kFecMaskRandom; 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 60b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgRTPSenderVideo::~RTPSenderVideo() { 61b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org if (_videoCodecInformation) { 62b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org delete _videoCodecInformation; 63b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org } 64b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org delete _sendVideoCritsect; 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 67b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgvoid RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) { 68b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org CriticalSectionScoped cs(_sendVideoCritsect); 69b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _videoType = videoType; 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 72b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgRtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const { 73b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return _videoType; 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 76b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTPSenderVideo::RegisterVideoPayload( 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char payloadName[RTP_PAYLOAD_NAME_SIZE], 78b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org const int8_t payloadType, 79b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.org const uint32_t maxBitRate, 806aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org RtpUtility::Payload*& payload) { 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_sendVideoCritsect); 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 837fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org RtpVideoCodecTypes videoType = kRtpVideoGeneric; 846aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org if (RtpUtility::StringCompare(payloadName, "VP8", 3)) { 857fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org videoType = kRtpVideoVp8; 866aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org } else if (RtpUtility::StringCompare(payloadName, "H264", 4)) { 872d4a80c05adffe07b48dc235475852450cd90568stefan@webrtc.org videoType = kRtpVideoH264; 886aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org } else if (RtpUtility::StringCompare(payloadName, "I420", 4)) { 897fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org videoType = kRtpVideoGeneric; 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 917fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org videoType = kRtpVideoGeneric; 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 936aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org payload = new RtpUtility::Payload; 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1); 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org payload->typeSpecific.Video.videoCodecType = videoType; 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org payload->typeSpecific.Video.maxRate = maxBitRate; 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org payload->audio = false; 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 102b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgint32_t RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, 103b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint16_t payload_length, 104b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint16_t rtp_header_length, 105b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint32_t capture_timestamp, 106b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org int64_t capture_time_ms, 107b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org StorageType storage, 108b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org bool protect) { 109b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org if (_fecEnabled) { 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int ret = 0; 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fec_overhead_sent = 0; 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int video_sent = 0; 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 114b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org RedPacket* red_packet = producer_fec_.BuildRedPacket( 115b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data_buffer, payload_length, rtp_header_length, _payloadTypeRED); 116b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org TRACE_EVENT_INSTANT2("webrtc_rtp", 117b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "Video::PacketRed", 118b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "timestamp", 119b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_timestamp, 120b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "seqnum", 121b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SequenceNumber()); 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sending the media packet with RED header. 123b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org int packet_success = 124b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SendToNetwork(red_packet->data(), 125b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org red_packet->length() - rtp_header_length, 126b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org rtp_header_length, 127b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_time_ms, 128b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org storage, 129b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org PacedSender::kNormalPriority); 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret |= packet_success; 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet_success == 0) { 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org video_sent += red_packet->length(); 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete red_packet; 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_packet = NULL; 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (protect) { 140b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org ret = producer_fec_.AddRtpPacketAndGenerateFec( 141b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data_buffer, payload_length, rtp_header_length); 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret != 0) 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (producer_fec_.FecAvailable()) { 147b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org red_packet = 148b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org producer_fec_.GetFecPacket(_payloadTypeRED, 149b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _payloadTypeFEC, 150b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.IncrementSequenceNumber(), 151b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org rtp_header_length); 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StorageType storage = kDontRetransmit; 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_retransmissionSettings & kRetransmitFECPackets) { 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org storage = kAllowRetransmission; 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 156b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org TRACE_EVENT_INSTANT2("webrtc_rtp", 157b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "Video::PacketFec", 158b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "timestamp", 159b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_timestamp, 160b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "seqnum", 161b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SequenceNumber()); 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Sending FEC packet with RED header. 163b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org int packet_success = 164b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SendToNetwork(red_packet->data(), 165b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org red_packet->length() - rtp_header_length, 166b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org rtp_header_length, 167b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_time_ms, 168b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org storage, 169b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org PacedSender::kNormalPriority); 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ret |= packet_success; 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (packet_success == 0) { 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fec_overhead_sent += red_packet->length(); 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete red_packet; 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org red_packet = NULL; 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _videoBitrate.Update(video_sent); 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _fecOverheadRate.Update(fec_overhead_sent); 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 183b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org TRACE_EVENT_INSTANT2("webrtc_rtp", 184b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "Video::PacketNormal", 185b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "timestamp", 186b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_timestamp, 187b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "seqnum", 188b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SequenceNumber()); 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int ret = _rtpSender.SendToNetwork(data_buffer, 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org payload_length, 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rtp_header_length, 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capture_time_ms, 19369f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org storage, 19469f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org PacedSender::kNormalPriority); 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ret == 0) { 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _videoBitrate.Update(payload_length + rtp_header_length); 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return ret; 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 201b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgint32_t RTPSenderVideo::SendRTPIntraRequest() { 202b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // RFC 2032 203b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // 5.2.1. Full intra-frame Request (FIR) packet 204b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org 205b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org uint16_t length = 8; 206b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org uint8_t data[8]; 207b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data[0] = 0x80; 208b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data[1] = 192; 209b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data[2] = 0; 210b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data[3] = 1; // length 211b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org 212b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org RtpUtility::AssignUWord32ToBuffer(data + 4, _rtpSender.SSRC()); 213b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org 214b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org TRACE_EVENT_INSTANT1("webrtc_rtp", 215b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "Video::IntraRequest", 216b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "seqnum", 217b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _rtpSender.SequenceNumber()); 218b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return _rtpSender.SendToNetwork( 219b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org data, 0, length, -1, kDontStore, PacedSender::kNormalPriority); 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 222b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgint32_t RTPSenderVideo::SetGenericFECStatus(const bool enable, 223b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint8_t payloadTypeRED, 224b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint8_t payloadTypeFEC) { 225b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _fecEnabled = enable; 226b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _payloadTypeRED = payloadTypeRED; 227b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _payloadTypeFEC = payloadTypeFEC; 228b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); 229b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org memset(&key_fec_params_, 0, sizeof(key_fec_params_)); 230b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; 231b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = 232b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org kFecMaskRandom; 233b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return 0; 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 236b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgint32_t RTPSenderVideo::GenericFECStatus(bool& enable, 237b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org uint8_t& payloadTypeRED, 238b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org uint8_t& payloadTypeFEC) const { 239b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org enable = _fecEnabled; 240b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org payloadTypeRED = _payloadTypeRED; 241b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org payloadTypeFEC = _payloadTypeFEC; 242b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return 0; 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 245b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orguint16_t RTPSenderVideo::FECPacketOverhead() const { 246b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org if (_fecEnabled) { 247b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // Overhead is FEC headers plus RED for FEC header plus anything in RTP 248b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // header beyond the 12 bytes base header (CSRC list, extensions...) 249b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // This reason for the header extensions to be included here is that 250b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // from an FEC viewpoint, they are part of the payload to be protected. 251b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // (The base RTP header is already protected by the FEC header.) 252b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength + 253b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org (_rtpSender.RTPHeaderLength() - kRtpHeaderSize); 254b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org } 255b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return 0; 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 258b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orgint32_t RTPSenderVideo::SetFecParameters( 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const FecProtectionParams* delta_params, 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const FecProtectionParams* key_params) { 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(delta_params); 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(key_params); 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delta_fec_params_ = *delta_params; 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org key_fec_params_ = *key_params; 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 268e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.orgint32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, 269e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const FrameType frameType, 270e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const int8_t payloadType, 271e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const uint32_t captureTimeStamp, 272e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org int64_t capture_time_ms, 273e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const uint8_t* payloadData, 274e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const uint32_t payloadSize, 275e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const RTPFragmentationHeader* fragmentation, 276e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org VideoCodecInformation* codecInfo, 277e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const RTPVideoTypeHeader* rtpTypeHdr) { 278e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org if (payloadSize == 0) { 279e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org return -1; 280e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 282e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org if (frameType == kVideoFrameKey) { 283e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org producer_fec_.SetFecParameters(&key_fec_params_, _numberFirstPartition); 284e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } else { 285e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org producer_fec_.SetFecParameters(&delta_fec_params_, _numberFirstPartition); 286e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 288e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org // Default setting for number of first partition packets: 289e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org // Will be extracted in SendVP8 for VP8 codec; other codecs use 0 290e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org _numberFirstPartition = 0; 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 292b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return Send(videoType, 293b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org frameType, 294b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org payloadType, 295b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org captureTimeStamp, 296b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org capture_time_ms, 297b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org payloadData, 298b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org payloadSize, 299b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org fragmentation, 300b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org rtpTypeHdr) 301b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org ? 0 302b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org : -1; 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 305b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgVideoCodecInformation* RTPSenderVideo::CodecInformationVideo() { 306b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return _videoCodecInformation; 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 309b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgvoid RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) { 310b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org _maxBitrate = maxBitrate; 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 313b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orguint32_t RTPSenderVideo::MaxConfiguredBitrateVideo() const { 314b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org return _maxBitrate; 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 317b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.orgbool RTPSenderVideo::Send(const RtpVideoCodecTypes videoType, 318b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const FrameType frameType, 319b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const int8_t payloadType, 320b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint32_t captureTimeStamp, 321b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org int64_t capture_time_ms, 322b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint8_t* payloadData, 323b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const uint32_t payloadSize, 324b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const RTPFragmentationHeader* fragmentation, 325b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const RTPVideoTypeHeader* rtpTypeHdr) { 326b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); 327e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org int32_t payload_bytes_to_send = payloadSize; 328e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org const uint8_t* data = payloadData; 329e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org size_t max_payload_length = _rtpSender.MaxDataPayloadLength(); 330e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org 331b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( 332b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org videoType, max_payload_length, rtpTypeHdr, frameType)); 333e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org 334b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // TODO(changbin): we currently don't support to configure the codec to 335b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // output multiple partitions for VP8. Should remove below check after the 336b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org // issue is fixed. 337b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org const RTPFragmentationHeader* frag = 338b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org (videoType == kRtpVideoVp8) ? NULL : fragmentation; 339b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org 340b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org packetizer->SetPayloadData(data, payload_bytes_to_send, frag); 341e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org 342b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org bool last = false; 343e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org while (!last) { 344e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; 345e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org size_t payload_bytes_in_packet = 0; 346e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org if (!packetizer->NextPacket( 347e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org &dataBuffer[rtp_header_length], &payload_bytes_in_packet, &last)) { 348e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org return false; 349e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } 350e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org 351e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org // Write RTP header. 352e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org // Set marker bit true if this is the last packet in frame. 353e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org _rtpSender.BuildRTPheader( 354e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms); 355e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org if (SendVideoPacket(dataBuffer, 356e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org payload_bytes_in_packet, 357e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org rtp_header_length, 358e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org captureTimeStamp, 359e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org capture_time_ms, 360b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org packetizer->GetStorageType(_retransmissionSettings), 361b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org packetizer->GetProtectionType() == kProtectedPacket)) { 362b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org LOG(LS_WARNING) << packetizer->ToString() 363b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org << " failed to send packet number " 364b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org << _rtpSender.SequenceNumber(); 365e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } 366e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org } 367b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org 368b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org TRACE_EVENT_ASYNC_END1( 369b7fb080fab9a42241324a0dfc238de51ba5f911apbos@webrtc.org "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp()); 370e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org return true; 371e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org} 372e75b34844a4e9998475ab557001ce0cfa1fe458fstefan@webrtc.org 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid RTPSenderVideo::ProcessBitrate() { 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _videoBitrate.Process(); 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _fecOverheadRate.Process(); 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 378b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orguint32_t RTPSenderVideo::VideoBitrateSent() const { 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _videoBitrate.BitrateLast(); 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 382b57da6501f9db93536f51f7a64abf27306a7af04pbos@webrtc.orguint32_t RTPSenderVideo::FecOverheadRate() const { 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _fecOverheadRate.BitrateLast(); 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint RTPSenderVideo::SelectiveRetransmissions() const { 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _retransmissionSettings; 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _retransmissionSettings = settings; 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3953b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace webrtc 396