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 |
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" |
12 | 12 |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <string.h> | 14 #include <string.h> |
15 | 15 |
16 #include <memory> | 16 #include <memory> |
17 #include <vector> | 17 #include <vector> |
18 #include <utility> | 18 #include <utility> |
19 | 19 |
20 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
21 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
| 22 #include "webrtc/base/ptr_util.h" |
22 #include "webrtc/base/trace_event.h" | 23 #include "webrtc/base/trace_event.h" |
23 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 24 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
24 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 25 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" | 26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |
26 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 27 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
27 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" | 28 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |
28 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | 29 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
29 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 30 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
30 | 31 |
31 namespace webrtc { | 32 namespace webrtc { |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 const RTPFragmentationHeader* fragmentation, | 294 const RTPFragmentationHeader* fragmentation, |
294 const RTPVideoHeader* video_header) { | 295 const RTPVideoHeader* video_header) { |
295 if (payload_size == 0) | 296 if (payload_size == 0) |
296 return false; | 297 return false; |
297 | 298 |
298 // Create header that will be reused in all packets. | 299 // Create header that will be reused in all packets. |
299 std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); | 300 std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); |
300 rtp_header->SetPayloadType(payload_type); | 301 rtp_header->SetPayloadType(payload_type); |
301 rtp_header->SetTimestamp(rtp_timestamp); | 302 rtp_header->SetTimestamp(rtp_timestamp); |
302 rtp_header->set_capture_time_ms(capture_time_ms); | 303 rtp_header->set_capture_time_ms(capture_time_ms); |
| 304 auto last_packet = rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |
303 | 305 |
304 size_t fec_packet_overhead; | 306 size_t fec_packet_overhead; |
305 bool red_enabled; | 307 bool red_enabled; |
306 int32_t retransmission_settings; | 308 int32_t retransmission_settings; |
307 { | 309 { |
308 rtc::CritScope cs(&crit_); | 310 rtc::CritScope cs(&crit_); |
309 // According to | 311 // According to |
310 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ | 312 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ |
311 // ts_126114v120700p.pdf Section 7.4.5: | 313 // ts_126114v120700p.pdf Section 7.4.5: |
312 // The MTSI client shall add the payload bytes as defined in this clause | 314 // The MTSI client shall add the payload bytes as defined in this clause |
313 // onto the last RTP packet in each group of packets which make up a key | 315 // onto the last RTP packet in each group of packets which make up a key |
314 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 | 316 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 |
315 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP | 317 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP |
316 // packet in each group of packets which make up another type of frame | 318 // packet in each group of packets which make up another type of frame |
317 // (e.g. a P-Frame) only if the current value is different from the previous | 319 // (e.g. a P-Frame) only if the current value is different from the previous |
318 // value sent. | 320 // value sent. |
319 if (video_header) { | 321 if (video_header) { |
320 // Set rotation when key frame or when changed (to follow standard). | 322 // Set rotation when key frame or when changed (to follow standard). |
321 // Or when different from 0 (to follow current receiver implementation). | 323 // Or when different from 0 (to follow current receiver implementation). |
322 VideoRotation current_rotation = video_header->rotation; | 324 VideoRotation current_rotation = video_header->rotation; |
323 if (frame_type == kVideoFrameKey || current_rotation != last_rotation_ || | 325 if (frame_type == kVideoFrameKey || current_rotation != last_rotation_ || |
324 current_rotation != kVideoRotation_0) | 326 current_rotation != kVideoRotation_0) |
325 rtp_header->SetExtension<VideoOrientation>(current_rotation); | 327 last_packet->SetExtension<VideoOrientation>(current_rotation); |
326 last_rotation_ = current_rotation; | 328 last_rotation_ = current_rotation; |
327 // Report content type only for key frames. | 329 // Report content type only for key frames. |
328 if (frame_type == kVideoFrameKey && | 330 if (frame_type == kVideoFrameKey && |
329 video_header->content_type != VideoContentType::UNSPECIFIED) { | 331 video_header->content_type != VideoContentType::UNSPECIFIED) { |
330 rtp_header->SetExtension<VideoContentTypeExtension>( | 332 last_packet->SetExtension<VideoContentTypeExtension>( |
331 video_header->content_type); | 333 video_header->content_type); |
332 } | 334 } |
333 } | 335 } |
334 | 336 |
335 // FEC settings. | 337 // FEC settings. |
336 const FecProtectionParams& fec_params = | 338 const FecProtectionParams& fec_params = |
337 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_; | 339 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_; |
338 if (flexfec_enabled()) | 340 if (flexfec_enabled()) |
339 flexfec_sender_->SetFecParameters(fec_params); | 341 flexfec_sender_->SetFecParameters(fec_params); |
340 if (ulpfec_enabled()) | 342 if (ulpfec_enabled()) |
341 ulpfec_generator_.SetFecParameters(fec_params); | 343 ulpfec_generator_.SetFecParameters(fec_params); |
342 | 344 |
343 fec_packet_overhead = CalculateFecPacketOverhead(); | 345 fec_packet_overhead = CalculateFecPacketOverhead(); |
344 red_enabled = this->red_enabled(); | 346 red_enabled = this->red_enabled(); |
345 retransmission_settings = retransmission_settings_; | 347 retransmission_settings = retransmission_settings_; |
346 } | 348 } |
347 | 349 |
348 size_t packet_capacity = rtp_sender_->MaxRtpPacketSize() - | 350 size_t packet_capacity = rtp_sender_->MaxRtpPacketSize() - |
349 fec_packet_overhead - | 351 fec_packet_overhead - |
350 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0); | 352 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0); |
351 RTC_DCHECK_LE(packet_capacity, rtp_header->capacity()); | 353 RTC_DCHECK_LE(packet_capacity, rtp_header->capacity()); |
352 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); | 354 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); |
| 355 RTC_DCHECK_GT(packet_capacity, last_packet->headers_size()); |
353 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); | 356 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); |
| 357 RTC_DCHECK_GE(last_packet->headers_size(), rtp_header->headers_size()); |
| 358 size_t last_packet_reduction_len = |
| 359 last_packet->headers_size() - rtp_header->headers_size(); |
354 | 360 |
355 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 361 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
356 video_type, max_data_payload_length, | 362 video_type, max_data_payload_length, last_packet_reduction_len, |
357 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 363 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |
358 // Media packet storage. | 364 // Media packet storage. |
359 StorageType storage = packetizer->GetStorageType(retransmission_settings); | 365 StorageType storage = packetizer->GetStorageType(retransmission_settings); |
360 | 366 |
361 // TODO(changbin): we currently don't support to configure the codec to | 367 // TODO(changbin): we currently don't support to configure the codec to |
362 // output multiple partitions for VP8. Should remove below check after the | 368 // output multiple partitions for VP8. Should remove below check after the |
363 // issue is fixed. | 369 // issue is fixed. |
364 const RTPFragmentationHeader* frag = | 370 const RTPFragmentationHeader* frag = |
365 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; | 371 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; |
366 packetizer->SetPayloadData(payload_data, payload_size, frag); | 372 size_t num_packets = |
| 373 packetizer->SetPayloadData(payload_data, payload_size, frag); |
| 374 |
| 375 if (num_packets == 0) |
| 376 return false; |
367 | 377 |
368 bool first_frame = first_frame_sent_(); | 378 bool first_frame = first_frame_sent_(); |
369 bool first = true; | 379 for (size_t i = 0; i < num_packets; ++i) { |
370 bool last = false; | 380 bool last = (i + 1) == num_packets; |
371 while (!last) { | 381 auto packet = last ? std::move(last_packet) |
372 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header)); | 382 : rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |
373 | 383 if (!packetizer->NextPacket(packet.get())) |
374 if (!packetizer->NextPacket(packet.get(), &last)) | |
375 return false; | 384 return false; |
376 RTC_DCHECK_LE(packet->payload_size(), max_data_payload_length); | 385 RTC_DCHECK_LE(packet->payload_size(), |
377 | 386 last ? max_data_payload_length - last_packet_reduction_len |
| 387 : max_data_payload_length); |
378 if (!rtp_sender_->AssignSequenceNumber(packet.get())) | 388 if (!rtp_sender_->AssignSequenceNumber(packet.get())) |
379 return false; | 389 return false; |
380 | 390 |
381 const bool protect_packet = | 391 const bool protect_packet = |
382 (packetizer->GetProtectionType() == kProtectedPacket); | 392 (packetizer->GetProtectionType() == kProtectedPacket); |
383 if (flexfec_enabled()) { | 393 if (flexfec_enabled()) { |
384 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender | 394 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender |
385 // is wired up to PacedSender instead. | 395 // is wired up to PacedSender instead. |
386 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet); | 396 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet); |
387 } else if (red_enabled) { | 397 } else if (red_enabled) { |
388 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage, | 398 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage, |
389 protect_packet); | 399 protect_packet); |
390 } else { | 400 } else { |
391 SendVideoPacket(std::move(packet), storage); | 401 SendVideoPacket(std::move(packet), storage); |
392 } | 402 } |
393 | 403 |
394 if (first_frame) { | 404 if (first_frame) { |
395 if (first) { | 405 if (i == 0) { |
396 LOG(LS_INFO) | 406 LOG(LS_INFO) |
397 << "Sent first RTP packet of the first video frame (pre-pacer)"; | 407 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
398 } | 408 } |
399 if (last) { | 409 if (last) { |
400 LOG(LS_INFO) | 410 LOG(LS_INFO) |
401 << "Sent last RTP packet of the first video frame (pre-pacer)"; | 411 << "Sent last RTP packet of the first video frame (pre-pacer)"; |
402 } | 412 } |
403 } | 413 } |
404 first = false; | |
405 } | 414 } |
406 | 415 |
407 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp", | 416 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp", |
408 rtp_timestamp); | 417 rtp_timestamp); |
409 return true; | 418 return true; |
410 } | 419 } |
411 | 420 |
412 uint32_t RTPSenderVideo::VideoBitrateSent() const { | 421 uint32_t RTPSenderVideo::VideoBitrateSent() const { |
413 rtc::CritScope cs(&stats_crit_); | 422 rtc::CritScope cs(&stats_crit_); |
414 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); | 423 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
415 } | 424 } |
416 | 425 |
417 uint32_t RTPSenderVideo::FecOverheadRate() const { | 426 uint32_t RTPSenderVideo::FecOverheadRate() const { |
418 rtc::CritScope cs(&stats_crit_); | 427 rtc::CritScope cs(&stats_crit_); |
419 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); | 428 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
420 } | 429 } |
421 | 430 |
422 int RTPSenderVideo::SelectiveRetransmissions() const { | 431 int RTPSenderVideo::SelectiveRetransmissions() const { |
423 rtc::CritScope cs(&crit_); | 432 rtc::CritScope cs(&crit_); |
424 return retransmission_settings_; | 433 return retransmission_settings_; |
425 } | 434 } |
426 | 435 |
427 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 436 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
428 rtc::CritScope cs(&crit_); | 437 rtc::CritScope cs(&crit_); |
429 retransmission_settings_ = settings; | 438 retransmission_settings_ = settings; |
430 } | 439 } |
431 | 440 |
432 } // namespace webrtc | 441 } // namespace webrtc |
OLD | NEW |