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