Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc

Issue 2871173008: Fix packetization logic to leave space for extensions in the last packet (Closed)
Patch Set: Implemented Danilchap@ comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698