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