| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 _retransmissionSettings(kRetransmitBaseLayer), | 36 _retransmissionSettings(kRetransmitBaseLayer), |
| 37 // Generic FEC | 37 // Generic FEC |
| 38 fec_(), | 38 fec_(), |
| 39 fec_enabled_(false), | 39 fec_enabled_(false), |
| 40 red_payload_type_(-1), | 40 red_payload_type_(-1), |
| 41 fec_payload_type_(-1), | 41 fec_payload_type_(-1), |
| 42 delta_fec_params_(), | 42 delta_fec_params_(), |
| 43 key_fec_params_(), | 43 key_fec_params_(), |
| 44 producer_fec_(&fec_), | 44 producer_fec_(&fec_), |
| 45 _fecOverheadRate(clock, NULL), | 45 _fecOverheadRate(clock, NULL), |
| 46 _videoBitrate(clock, NULL) { | 46 _videoBitrate(clock, NULL), |
| 47 sent_first_frame_(false) { |
| 47 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); | 48 memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); |
| 48 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); | 49 memset(&key_fec_params_, 0, sizeof(key_fec_params_)); |
| 49 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; | 50 delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; |
| 50 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = | 51 delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = |
| 51 kFecMaskRandom; | 52 kFecMaskRandom; |
| 52 } | 53 } |
| 53 | 54 |
| 54 RTPSenderVideo::~RTPSenderVideo() { | 55 RTPSenderVideo::~RTPSenderVideo() { |
| 55 } | 56 } |
| 56 | 57 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 if (payloadSize == 0) { | 226 if (payloadSize == 0) { |
| 226 return -1; | 227 return -1; |
| 227 } | 228 } |
| 228 | 229 |
| 229 rtc::scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 230 rtc::scoped_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
| 230 videoType, _rtpSender.MaxDataPayloadLength(), | 231 videoType, _rtpSender.MaxDataPayloadLength(), |
| 231 video_header ? &(video_header->codecHeader) : nullptr, frameType)); | 232 video_header ? &(video_header->codecHeader) : nullptr, frameType)); |
| 232 | 233 |
| 233 StorageType storage; | 234 StorageType storage; |
| 234 bool fec_enabled; | 235 bool fec_enabled; |
| 236 bool first_frame = false; |
| 235 { | 237 { |
| 236 CriticalSectionScoped cs(crit_.get()); | 238 CriticalSectionScoped cs(crit_.get()); |
| 237 FecProtectionParams* fec_params = | 239 FecProtectionParams* fec_params = |
| 238 frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; | 240 frameType == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; |
| 239 producer_fec_.SetFecParameters(fec_params, 0); | 241 producer_fec_.SetFecParameters(fec_params, 0); |
| 240 storage = packetizer->GetStorageType(_retransmissionSettings); | 242 storage = packetizer->GetStorageType(_retransmissionSettings); |
| 241 fec_enabled = fec_enabled_; | 243 fec_enabled = fec_enabled_; |
| 244 if (!sent_first_frame_) { |
| 245 first_frame = true; |
| 246 sent_first_frame_ = true; |
| 247 } |
| 242 } | 248 } |
| 243 | 249 |
| 244 // Register CVO rtp header extension at the first time when we receive a frame | 250 // Register CVO rtp header extension at the first time when we receive a frame |
| 245 // with pending rotation. | 251 // with pending rotation. |
| 246 RTPSenderInterface::CVOMode cvo_mode = RTPSenderInterface::kCVONone; | 252 RTPSenderInterface::CVOMode cvo_mode = RTPSenderInterface::kCVONone; |
| 247 if (video_header && video_header->rotation != kVideoRotation_0) { | 253 if (video_header && video_header->rotation != kVideoRotation_0) { |
| 248 cvo_mode = _rtpSender.ActivateCVORtpHeaderExtension(); | 254 cvo_mode = _rtpSender.ActivateCVORtpHeaderExtension(); |
| 249 } | 255 } |
| 250 | 256 |
| 251 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); | 257 uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); |
| 252 size_t payload_bytes_to_send = payloadSize; | 258 size_t payload_bytes_to_send = payloadSize; |
| 253 const uint8_t* data = payloadData; | 259 const uint8_t* data = payloadData; |
| 254 | 260 |
| 255 // TODO(changbin): we currently don't support to configure the codec to | 261 // TODO(changbin): we currently don't support to configure the codec to |
| 256 // output multiple partitions for VP8. Should remove below check after the | 262 // output multiple partitions for VP8. Should remove below check after the |
| 257 // issue is fixed. | 263 // issue is fixed. |
| 258 const RTPFragmentationHeader* frag = | 264 const RTPFragmentationHeader* frag = |
| 259 (videoType == kRtpVideoVp8) ? NULL : fragmentation; | 265 (videoType == kRtpVideoVp8) ? NULL : fragmentation; |
| 260 | 266 |
| 261 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); | 267 packetizer->SetPayloadData(data, payload_bytes_to_send, frag); |
| 262 | 268 |
| 269 bool first = true; |
| 263 bool last = false; | 270 bool last = false; |
| 264 while (!last) { | 271 while (!last) { |
| 265 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; | 272 uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; |
| 266 size_t payload_bytes_in_packet = 0; | 273 size_t payload_bytes_in_packet = 0; |
| 267 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length], | 274 if (!packetizer->NextPacket(&dataBuffer[rtp_header_length], |
| 268 &payload_bytes_in_packet, &last)) { | 275 &payload_bytes_in_packet, &last)) { |
| 269 return -1; | 276 return -1; |
| 270 } | 277 } |
| 278 |
| 271 // Write RTP header. | 279 // Write RTP header. |
| 272 // Set marker bit true if this is the last packet in frame. | 280 // Set marker bit true if this is the last packet in frame. |
| 273 _rtpSender.BuildRTPheader( | 281 _rtpSender.BuildRTPheader( |
| 274 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms); | 282 dataBuffer, payloadType, last, captureTimeStamp, capture_time_ms); |
| 275 // According to | 283 // According to |
| 276 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ | 284 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ |
| 277 // ts_126114v120700p.pdf Section 7.4.5: | 285 // ts_126114v120700p.pdf Section 7.4.5: |
| 278 // The MTSI client shall add the payload bytes as defined in this clause | 286 // The MTSI client shall add the payload bytes as defined in this clause |
| 279 // onto the last RTP packet in each group of packets which make up a key | 287 // onto the last RTP packet in each group of packets which make up a key |
| 280 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 | 288 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 302 if (fec_enabled) { | 310 if (fec_enabled) { |
| 303 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet, | 311 SendVideoPacketAsRed(dataBuffer, payload_bytes_in_packet, |
| 304 rtp_header_length, _rtpSender.SequenceNumber(), | 312 rtp_header_length, _rtpSender.SequenceNumber(), |
| 305 captureTimeStamp, capture_time_ms, storage, | 313 captureTimeStamp, capture_time_ms, storage, |
| 306 packetizer->GetProtectionType() == kProtectedPacket); | 314 packetizer->GetProtectionType() == kProtectedPacket); |
| 307 } else { | 315 } else { |
| 308 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length, | 316 SendVideoPacket(dataBuffer, payload_bytes_in_packet, rtp_header_length, |
| 309 _rtpSender.SequenceNumber(), captureTimeStamp, | 317 _rtpSender.SequenceNumber(), captureTimeStamp, |
| 310 capture_time_ms, storage); | 318 capture_time_ms, storage); |
| 311 } | 319 } |
| 320 |
| 321 if (first_frame) { |
| 322 if (first) { |
| 323 LOG(LS_INFO) |
| 324 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
| 325 } |
| 326 if (last) { |
| 327 LOG(LS_INFO) |
| 328 << "Sent last RTP packet of the first video frame (pre-pacer)"; |
| 329 } |
| 330 } |
| 331 first = false; |
| 312 } | 332 } |
| 313 | 333 |
| 314 TRACE_EVENT_ASYNC_END1( | 334 TRACE_EVENT_ASYNC_END1( |
| 315 "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp()); | 335 "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp()); |
| 316 return 0; | 336 return 0; |
| 317 } | 337 } |
| 318 | 338 |
| 319 void RTPSenderVideo::ProcessBitrate() { | 339 void RTPSenderVideo::ProcessBitrate() { |
| 320 _videoBitrate.Process(); | 340 _videoBitrate.Process(); |
| 321 _fecOverheadRate.Process(); | 341 _fecOverheadRate.Process(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 333 CriticalSectionScoped cs(crit_.get()); | 353 CriticalSectionScoped cs(crit_.get()); |
| 334 return _retransmissionSettings; | 354 return _retransmissionSettings; |
| 335 } | 355 } |
| 336 | 356 |
| 337 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 357 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
| 338 CriticalSectionScoped cs(crit_.get()); | 358 CriticalSectionScoped cs(crit_.get()); |
| 339 _retransmissionSettings = settings; | 359 _retransmissionSettings = settings; |
| 340 } | 360 } |
| 341 | 361 |
| 342 } // namespace webrtc | 362 } // namespace webrtc |
| OLD | NEW |