Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_sender_video.cc
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
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
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h"
12
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
18 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h"
19 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
21 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
22 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
23 #include "webrtc/system_wrappers/interface/logging.h"
24 #include "webrtc/system_wrappers/interface/trace_event.h"
25
26 namespace webrtc {
27 enum { REDForFECHeaderLength = 1 };
28
29 struct RtpPacket {
30   uint16_t rtpHeaderLength;
31   ForwardErrorCorrection::Packet* pkt;
32 };
33
34 RTPSenderVideo::RTPSenderVideo(Clock* clock,
35                                RTPSenderInterface* rtpSender)
36     : _rtpSender(*rtpSender),
37       _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()),
38       _videoType(kRtpVideoGeneric),
39       _videoCodecInformation(NULL),
40       _maxBitrate(0),
41       _retransmissionSettings(kRetransmitBaseLayer),
42
43       // Generic FEC
44       _fec(),
45       _fecEnabled(false),
46       _payloadTypeRED(-1),
47       _payloadTypeFEC(-1),
48       _numberFirstPartition(0),
49       delta_fec_params_(),
50       key_fec_params_(),
51       producer_fec_(&_fec),
52       _fecOverheadRate(clock, NULL),
53       _videoBitrate(clock, NULL) {
54   memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
55   memset(&key_fec_params_, 0, sizeof(key_fec_params_));
56   delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
57   delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
58         kFecMaskRandom;
59 }
60
61 RTPSenderVideo::~RTPSenderVideo()
62 {
63     if(_videoCodecInformation)
64     {
65         delete _videoCodecInformation;
66     }
67     delete _sendVideoCritsect;
68 }
69
70 void
71 RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType)
72 {
73     CriticalSectionScoped cs(_sendVideoCritsect);
74     _videoType = videoType;
75 }
76
77 RtpVideoCodecTypes
78 RTPSenderVideo::VideoCodecType() const
79 {
80     return _videoType;
81 }
82
83 int32_t RTPSenderVideo::RegisterVideoPayload(
84     const char payloadName[RTP_PAYLOAD_NAME_SIZE],
85     const int8_t payloadType,
86     const uint32_t maxBitRate,
87     ModuleRTPUtility::Payload*& payload) {
88   CriticalSectionScoped cs(_sendVideoCritsect);
89
90   RtpVideoCodecTypes videoType = kRtpVideoGeneric;
91   if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
92     videoType = kRtpVideoVp8;
93   } else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
94     videoType = kRtpVideoGeneric;
95   } else {
96     videoType = kRtpVideoGeneric;
97   }
98   payload = new ModuleRTPUtility::Payload;
99   payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0;
100   strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
101   payload->typeSpecific.Video.videoCodecType = videoType;
102   payload->typeSpecific.Video.maxRate = maxBitRate;
103   payload->audio = false;
104   return 0;
105 }
106
107 int32_t
108 RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer,
109                                 const uint16_t payload_length,
110                                 const uint16_t rtp_header_length,
111                                 const uint32_t capture_timestamp,
112                                 int64_t capture_time_ms,
113                                 StorageType storage,
114                                 bool protect) {
115   if(_fecEnabled) {
116     int ret = 0;
117     int fec_overhead_sent = 0;
118     int video_sent = 0;
119
120     RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer,
121                                                          payload_length,
122                                                          rtp_header_length,
123                                                          _payloadTypeRED);
124     TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketRed",
125                          "timestamp", capture_timestamp,
126                          "seqnum", _rtpSender.SequenceNumber());
127     // Sending the media packet with RED header.
128     int packet_success = _rtpSender.SendToNetwork(
129         red_packet->data(),
130         red_packet->length() - rtp_header_length,
131         rtp_header_length,
132         capture_time_ms,
133         storage,
134         PacedSender::kNormalPriority);
135
136     ret |= packet_success;
137
138     if (packet_success == 0) {
139       video_sent += red_packet->length();
140     }
141     delete red_packet;
142     red_packet = NULL;
143
144     if (protect) {
145       ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer,
146                                                      payload_length,
147                                                      rtp_header_length);
148       if (ret != 0)
149         return ret;
150     }
151
152     while (producer_fec_.FecAvailable()) {
153       red_packet = producer_fec_.GetFecPacket(
154           _payloadTypeRED,
155           _payloadTypeFEC,
156           _rtpSender.IncrementSequenceNumber(),
157           rtp_header_length);
158       StorageType storage = kDontRetransmit;
159       if (_retransmissionSettings & kRetransmitFECPackets) {
160         storage = kAllowRetransmission;
161       }
162       TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketFec",
163                            "timestamp", capture_timestamp,
164                            "seqnum", _rtpSender.SequenceNumber());
165       // Sending FEC packet with RED header.
166       int packet_success = _rtpSender.SendToNetwork(
167           red_packet->data(),
168           red_packet->length() - rtp_header_length,
169           rtp_header_length,
170           capture_time_ms,
171           storage,
172           PacedSender::kNormalPriority);
173
174       ret |= packet_success;
175
176       if (packet_success == 0) {
177         fec_overhead_sent += red_packet->length();
178       }
179       delete red_packet;
180       red_packet = NULL;
181     }
182     _videoBitrate.Update(video_sent);
183     _fecOverheadRate.Update(fec_overhead_sent);
184     return ret;
185   }
186   TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal",
187                        "timestamp", capture_timestamp,
188                        "seqnum", _rtpSender.SequenceNumber());
189   int ret = _rtpSender.SendToNetwork(data_buffer,
190                                      payload_length,
191                                      rtp_header_length,
192                                      capture_time_ms,
193                                      storage,
194                                      PacedSender::kNormalPriority);
195   if (ret == 0) {
196     _videoBitrate.Update(payload_length + rtp_header_length);
197   }
198   return ret;
199 }
200
201 int32_t
202 RTPSenderVideo::SendRTPIntraRequest()
203 {
204     // RFC 2032
205     // 5.2.1.  Full intra-frame Request (FIR) packet
206
207     uint16_t length = 8;
208     uint8_t data[8];
209     data[0] = 0x80;
210     data[1] = 192;
211     data[2] = 0;
212     data[3] = 1; // length
213
214     ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC());
215
216     TRACE_EVENT_INSTANT1("webrtc_rtp",
217                          "Video::IntraRequest",
218                          "seqnum", _rtpSender.SequenceNumber());
219     return _rtpSender.SendToNetwork(data, 0, length, -1, kDontStore,
220                                     PacedSender::kNormalPriority);
221 }
222
223 int32_t
224 RTPSenderVideo::SetGenericFECStatus(const bool enable,
225                                     const uint8_t payloadTypeRED,
226                                     const uint8_t payloadTypeFEC)
227 {
228     _fecEnabled = enable;
229     _payloadTypeRED = payloadTypeRED;
230     _payloadTypeFEC = payloadTypeFEC;
231     memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
232     memset(&key_fec_params_, 0, sizeof(key_fec_params_));
233     delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
234     delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type =
235           kFecMaskRandom;
236     return 0;
237 }
238
239 int32_t
240 RTPSenderVideo::GenericFECStatus(bool& enable,
241                                  uint8_t& payloadTypeRED,
242                                  uint8_t& payloadTypeFEC) const
243 {
244     enable = _fecEnabled;
245     payloadTypeRED = _payloadTypeRED;
246     payloadTypeFEC = _payloadTypeFEC;
247     return 0;
248 }
249
250 uint16_t
251 RTPSenderVideo::FECPacketOverhead() const
252 {
253     if (_fecEnabled)
254     {
255       // Overhead is FEC headers plus RED for FEC header plus anything in RTP
256       // header beyond the 12 bytes base header (CSRC list, extensions...)
257       // This reason for the header extensions to be included here is that
258       // from an FEC viewpoint, they are part of the payload to be protected.
259       // (The base RTP header is already protected by the FEC header.)
260       return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength +
261              (_rtpSender.RTPHeaderLength() - kRtpHeaderSize);
262     }
263     return 0;
264 }
265
266 int32_t RTPSenderVideo::SetFecParameters(
267     const FecProtectionParams* delta_params,
268     const FecProtectionParams* key_params) {
269   assert(delta_params);
270   assert(key_params);
271   delta_fec_params_ = *delta_params;
272   key_fec_params_ = *key_params;
273   return 0;
274 }
275
276 int32_t
277 RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
278                           const FrameType frameType,
279                           const int8_t payloadType,
280                           const uint32_t captureTimeStamp,
281                           int64_t capture_time_ms,
282                           const uint8_t* payloadData,
283                           const uint32_t payloadSize,
284                           const RTPFragmentationHeader* fragmentation,
285                           VideoCodecInformation* codecInfo,
286                           const RTPVideoTypeHeader* rtpTypeHdr)
287 {
288     if( payloadSize == 0)
289     {
290         return -1;
291     }
292
293     if (frameType == kVideoFrameKey) {
294       producer_fec_.SetFecParameters(&key_fec_params_,
295                                      _numberFirstPartition);
296     } else {
297       producer_fec_.SetFecParameters(&delta_fec_params_,
298                                      _numberFirstPartition);
299     }
300
301     // Default setting for number of first partition packets:
302     // Will be extracted in SendVP8 for VP8 codec; other codecs use 0
303     _numberFirstPartition = 0;
304
305     int32_t retVal = -1;
306     switch(videoType)
307     {
308     case kRtpVideoGeneric:
309         retVal = SendGeneric(frameType, payloadType, captureTimeStamp,
310                              capture_time_ms, payloadData, payloadSize);
311         break;
312     case kRtpVideoVp8:
313         retVal = SendVP8(frameType,
314                          payloadType,
315                          captureTimeStamp,
316                          capture_time_ms,
317                          payloadData,
318                          payloadSize,
319                          fragmentation,
320                          rtpTypeHdr);
321         break;
322     default:
323         assert(false);
324         break;
325     }
326     if(retVal <= 0)
327     {
328         return retVal;
329     }
330     return 0;
331 }
332
333 int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type,
334                                     const int8_t payload_type,
335                                     const uint32_t capture_timestamp,
336                                     int64_t capture_time_ms,
337                                     const uint8_t* payload,
338                                     uint32_t size) {
339   assert(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta);
340   uint16_t rtp_header_length = _rtpSender.RTPHeaderLength();
341   uint16_t max_length = _rtpSender.MaxPayloadLength() - FECPacketOverhead() -
342                         rtp_header_length - (1 /* generic header length */);
343
344   // Fragment packets more evenly by splitting the payload up evenly.
345   uint32_t num_packets = (size + max_length - 1) / max_length;
346   uint32_t payload_length = (size + num_packets - 1) / num_packets;
347   assert(payload_length <= max_length);
348
349   // Fragment packet into packets of max MaxPayloadLength bytes payload.
350   uint8_t buffer[IP_PACKET_SIZE];
351
352   uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit;
353   if (frame_type == kVideoFrameKey) {
354     generic_header |= RtpFormatVideoGeneric::kKeyFrameBit;
355   }
356
357   while (size > 0) {
358     if (size < payload_length) {
359       payload_length = size;
360     }
361     size -= payload_length;
362
363     // MarkerBit is 1 on final packet (bytes_to_send == 0)
364     if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
365                                   capture_timestamp,
366                                   capture_time_ms) != rtp_header_length) {
367       return -1;
368     }
369
370     uint8_t* out_ptr = &buffer[rtp_header_length];
371
372     // Put generic header in packet
373     *out_ptr++ = generic_header;
374     // Remove first-packet bit, following packets are intermediate
375     generic_header &= ~RtpFormatVideoGeneric::kFirstPacketBit;
376
377     // Put payload in packet
378     memcpy(out_ptr, payload, payload_length);
379     payload += payload_length;
380
381     if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length,
382                         capture_timestamp, capture_time_ms,
383                         kAllowRetransmission, true)) {
384       return -1;
385     }
386   }
387   return 0;
388 }
389
390 VideoCodecInformation*
391 RTPSenderVideo::CodecInformationVideo()
392 {
393     return _videoCodecInformation;
394 }
395
396 void
397 RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate)
398 {
399     _maxBitrate = maxBitrate;
400 }
401
402 uint32_t
403 RTPSenderVideo::MaxConfiguredBitrateVideo() const
404 {
405     return _maxBitrate;
406 }
407
408 int32_t
409 RTPSenderVideo::SendVP8(const FrameType frameType,
410                         const int8_t payloadType,
411                         const uint32_t captureTimeStamp,
412                         int64_t capture_time_ms,
413                         const uint8_t* payloadData,
414                         const uint32_t payloadSize,
415                         const RTPFragmentationHeader* fragmentation,
416                         const RTPVideoTypeHeader* rtpTypeHdr)
417 {
418     const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength();
419
420     int32_t payloadBytesToSend = payloadSize;
421     const uint8_t* data = payloadData;
422
423     uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength();
424
425     assert(rtpTypeHdr);
426     // Initialize disregarding partition boundaries: this will use kEqualSize
427     // packetization mode, which produces ~equal size packets for each frame.
428     RtpFormatVp8 packetizer(data, payloadBytesToSend, rtpTypeHdr->VP8,
429                             maxPayloadLengthVP8);
430
431     StorageType storage = kAllowRetransmission;
432     if (rtpTypeHdr->VP8.temporalIdx == 0 &&
433         !(_retransmissionSettings & kRetransmitBaseLayer)) {
434       storage = kDontRetransmit;
435     }
436     if (rtpTypeHdr->VP8.temporalIdx > 0 &&
437         !(_retransmissionSettings & kRetransmitHigherLayers)) {
438       storage = kDontRetransmit;
439     }
440
441     bool last = false;
442     _numberFirstPartition = 0;
443     // |rtpTypeHdr->VP8.temporalIdx| is zero for base layers, or -1 if the field
444     // isn't used. We currently only protect base layers.
445     bool protect = (rtpTypeHdr->VP8.temporalIdx < 1);
446     while (!last)
447     {
448         // Write VP8 Payload Descriptor and VP8 payload.
449         uint8_t dataBuffer[IP_PACKET_SIZE] = {0};
450         int payloadBytesInPacket = 0;
451         int packetStartPartition =
452             packetizer.NextPacket(&dataBuffer[rtpHeaderLength],
453                                   &payloadBytesInPacket, &last);
454         // TODO(holmer): Temporarily disable first partition packet counting
455         // to avoid a bug in ProducerFec which doesn't properly handle
456         // important packets.
457         // if (packetStartPartition == 0)
458         // {
459         //     ++_numberFirstPartition;
460         // }
461         // else
462         if (packetStartPartition < 0)
463         {
464             return -1;
465         }
466
467         // Write RTP header.
468         // Set marker bit true if this is the last packet in frame.
469         _rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
470             captureTimeStamp, capture_time_ms);
471         if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket,
472                                   rtpHeaderLength, captureTimeStamp,
473                                   capture_time_ms, storage, protect))
474         {
475           LOG(LS_WARNING)
476               << "RTPSenderVideo::SendVP8 failed to send packet number "
477               << _rtpSender.SequenceNumber();
478         }
479     }
480     TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms,
481                            "timestamp", _rtpSender.Timestamp());
482     return 0;
483 }
484
485 void RTPSenderVideo::ProcessBitrate() {
486   _videoBitrate.Process();
487   _fecOverheadRate.Process();
488 }
489
490 uint32_t RTPSenderVideo::VideoBitrateSent() const {
491   return _videoBitrate.BitrateLast();
492 }
493
494 uint32_t RTPSenderVideo::FecOverheadRate() const {
495   return _fecOverheadRate.BitrateLast();
496 }
497
498 int RTPSenderVideo::SelectiveRetransmissions() const {
499   return _retransmissionSettings;
500 }
501
502 int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
503   _retransmissionSettings = settings;
504   return 0;
505 }
506
507 }  // namespace webrtc