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 size_t last_packet_extensions_len = | |
358 last_packet->headers_size() - rtp_header->headers_size(); | |
danilchap
2017/05/12 13:56:10
be explicit about your assumption
last_packet->hea
ilnik
2017/05/12 14:46:08
Done.
| |
354 | 359 |
355 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 360 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
356 video_type, max_data_payload_length, | 361 video_type, max_data_payload_length, last_packet_extensions_len, |
357 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 362 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |
358 // Media packet storage. | 363 // Media packet storage. |
359 StorageType storage = packetizer->GetStorageType(retransmission_settings); | 364 StorageType storage = packetizer->GetStorageType(retransmission_settings); |
360 | 365 |
361 // TODO(changbin): we currently don't support to configure the codec to | 366 // TODO(changbin): we currently don't support to configure the codec to |
362 // output multiple partitions for VP8. Should remove below check after the | 367 // output multiple partitions for VP8. Should remove below check after the |
363 // issue is fixed. | 368 // issue is fixed. |
364 const RTPFragmentationHeader* frag = | 369 const RTPFragmentationHeader* frag = |
365 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; | 370 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; |
366 packetizer->SetPayloadData(payload_data, payload_size, frag); | 371 size_t num_packets = |
372 packetizer->SetPayloadData(payload_data, payload_size, frag); | |
367 | 373 |
368 bool first_frame = first_frame_sent_(); | 374 bool first_frame = first_frame_sent_(); |
369 bool first = true; | 375 for (size_t i = 0; i < num_packets; ++i) { |
370 bool last = false; | 376 RtpPacketToSend* rtp_header_to_use = rtp_header.get(); |
371 while (!last) { | 377 bool last = (i + 1) == num_packets; |
372 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header)); | 378 if (last) |
373 | 379 rtp_header_to_use = last_packet.get(); |
374 if (!packetizer->NextPacket(packet.get(), &last)) | 380 std::unique_ptr<RtpPacketToSend> packet( |
danilchap
2017/05/12 13:56:10
may be
auto packet = last ? std::move(last_packet)
ilnik
2017/05/12 14:46:08
Done.
| |
381 new RtpPacketToSend(*rtp_header_to_use)); | |
382 if (!packetizer->NextPacket(packet.get())) | |
375 return false; | 383 return false; |
376 RTC_DCHECK_LE(packet->payload_size(), max_data_payload_length); | 384 RTC_DCHECK_LE(packet->payload_size(), packet->capacity()); |
danilchap
2017/05/12 13:56:10
sorry for confusion, but
packet->capacity() != pac
ilnik
2017/05/12 14:46:08
Done here something better now. It may be redundan
| |
377 | |
378 if (!rtp_sender_->AssignSequenceNumber(packet.get())) | 385 if (!rtp_sender_->AssignSequenceNumber(packet.get())) |
379 return false; | 386 return false; |
380 | 387 |
381 const bool protect_packet = | 388 const bool protect_packet = |
382 (packetizer->GetProtectionType() == kProtectedPacket); | 389 (packetizer->GetProtectionType() == kProtectedPacket); |
383 if (flexfec_enabled()) { | 390 if (flexfec_enabled()) { |
384 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender | 391 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender |
385 // is wired up to PacedSender instead. | 392 // is wired up to PacedSender instead. |
386 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet); | 393 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet); |
387 } else if (red_enabled) { | 394 } else if (red_enabled) { |
388 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage, | 395 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage, |
389 protect_packet); | 396 protect_packet); |
390 } else { | 397 } else { |
391 SendVideoPacket(std::move(packet), storage); | 398 SendVideoPacket(std::move(packet), storage); |
392 } | 399 } |
393 | 400 |
394 if (first_frame) { | 401 if (first_frame) { |
395 if (first) { | 402 if (i == 0) { |
396 LOG(LS_INFO) | 403 LOG(LS_INFO) |
397 << "Sent first RTP packet of the first video frame (pre-pacer)"; | 404 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
398 } | 405 } |
399 if (last) { | 406 if (last) { |
400 LOG(LS_INFO) | 407 LOG(LS_INFO) |
401 << "Sent last RTP packet of the first video frame (pre-pacer)"; | 408 << "Sent last RTP packet of the first video frame (pre-pacer)"; |
402 } | 409 } |
403 } | 410 } |
404 first = false; | |
405 } | 411 } |
406 | 412 |
407 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp", | 413 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp", |
408 rtp_timestamp); | 414 rtp_timestamp); |
409 return true; | 415 return true; |
410 } | 416 } |
411 | 417 |
412 uint32_t RTPSenderVideo::VideoBitrateSent() const { | 418 uint32_t RTPSenderVideo::VideoBitrateSent() const { |
413 rtc::CritScope cs(&stats_crit_); | 419 rtc::CritScope cs(&stats_crit_); |
414 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); | 420 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
415 } | 421 } |
416 | 422 |
417 uint32_t RTPSenderVideo::FecOverheadRate() const { | 423 uint32_t RTPSenderVideo::FecOverheadRate() const { |
418 rtc::CritScope cs(&stats_crit_); | 424 rtc::CritScope cs(&stats_crit_); |
419 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); | 425 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
420 } | 426 } |
421 | 427 |
422 int RTPSenderVideo::SelectiveRetransmissions() const { | 428 int RTPSenderVideo::SelectiveRetransmissions() const { |
423 rtc::CritScope cs(&crit_); | 429 rtc::CritScope cs(&crit_); |
424 return retransmission_settings_; | 430 return retransmission_settings_; |
425 } | 431 } |
426 | 432 |
427 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 433 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
428 rtc::CritScope cs(&crit_); | 434 rtc::CritScope cs(&crit_); |
429 retransmission_settings_ = settings; | 435 retransmission_settings_ = settings; |
430 } | 436 } |
431 | 437 |
432 } // namespace webrtc | 438 } // namespace webrtc |
OLD | NEW |