diff --git a/webrtc/modules/rtp_rtcp/BUILD.gn b/webrtc/modules/rtp_rtcp/BUILD.gn index 74af071a5..2ee1a8f0d 100644 --- a/webrtc/modules/rtp_rtcp/BUILD.gn +++ b/webrtc/modules/rtp_rtcp/BUILD.gn @@ -85,6 +85,7 @@ source_set("rtp_rtcp") { "source/rtp_format_h264.h", "source/rtp_format_vp8.cc", "source/rtp_format_vp8.h", + "source/rtp_format_video_generic.cc", "source/rtp_format_video_generic.h", "source/vp8_partition_aggregator.cc", "source/vp8_partition_aggregator.h", diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index 40c8b9e83..2d6b272af 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -63,6 +63,11 @@ enum RTPAliveType kRtpAlive = 2 }; +enum ProtectionType { + kUnprotectedPacket, + kProtectedPacket +}; + enum StorageType { kDontStore, kDontRetransmit, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format.cc b/webrtc/modules/rtp_rtcp/source/rtp_format.cc index da1f2df27..afb6c06d1 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format.cc @@ -11,16 +11,23 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/modules/rtp_rtcp/source/rtp_format_h264.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" namespace webrtc { RtpPacketizer* RtpPacketizer::Create(RtpVideoCodecTypes type, - size_t max_payload_len) { + size_t max_payload_len, + const RTPVideoTypeHeader* rtp_type_header, + FrameType frame_type) { switch (type) { case kRtpVideoH264: - return new RtpPacketizerH264(max_payload_len); - case kRtpVideoNone: - case kRtpVideoGeneric: + return new RtpPacketizerH264(frame_type, max_payload_len); case kRtpVideoVp8: + assert(rtp_type_header != NULL); + return new RtpPacketizerVp8(rtp_type_header->VP8, max_payload_len); + case kRtpVideoGeneric: + return new RtpPacketizerGeneric(frame_type, max_payload_len); + case kRtpVideoNone: assert(false); } return NULL; @@ -31,9 +38,11 @@ RtpDepacketizer* RtpDepacketizer::Create(RtpVideoCodecTypes type, switch (type) { case kRtpVideoH264: return new RtpDepacketizerH264(callback); - case kRtpVideoNone: - case kRtpVideoGeneric: case kRtpVideoVp8: + return new RtpDepacketizerVp8(callback); + case kRtpVideoGeneric: + return new RtpDepacketizerGeneric(callback); + case kRtpVideoNone: assert(false); } return NULL; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format.h b/webrtc/modules/rtp_rtcp/source/rtp_format.h index d7dba480f..07dc225c7 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H_ +#include + #include "webrtc/base/constructormagic.h" #include "webrtc/modules/interface/module_common_types.h" #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" @@ -19,7 +21,10 @@ namespace webrtc { class RtpPacketizer { public: - static RtpPacketizer* Create(RtpVideoCodecTypes type, size_t max_payload_len); + static RtpPacketizer* Create(RtpVideoCodecTypes type, + size_t max_payload_len, + const RTPVideoTypeHeader* rtp_type_header, + FrameType frame_type); virtual ~RtpPacketizer() {} @@ -37,6 +42,12 @@ class RtpPacketizer { virtual bool NextPacket(uint8_t* buffer, size_t* bytes_to_send, bool* last_packet) = 0; + + virtual ProtectionType GetProtectionType() = 0; + + virtual StorageType GetStorageType(uint32_t retransmission_settings) = 0; + + virtual std::string ToString() = 0; }; class RtpDepacketizer { diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc index 85bd94688..6b25f9c4d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.cc @@ -94,8 +94,12 @@ void ParseFuaNalu(WebRtcRTPHeader* rtp_header, } } // namespace -RtpPacketizerH264::RtpPacketizerH264(size_t max_payload_len) - : payload_data_(NULL), payload_size_(0), max_payload_len_(max_payload_len) { +RtpPacketizerH264::RtpPacketizerH264(FrameType frame_type, + size_t max_payload_len) + : payload_data_(NULL), + payload_size_(0), + max_payload_len_(max_payload_len), + frame_type_(frame_type) { } RtpPacketizerH264::~RtpPacketizerH264() { @@ -272,6 +276,20 @@ void RtpPacketizerH264::NextFragmentPacket(uint8_t* buffer, packets_.pop(); } +ProtectionType RtpPacketizerH264::GetProtectionType() { + return (frame_type_ == kVideoFrameKey) ? kProtectedPacket + : kUnprotectedPacket; +} + +StorageType RtpPacketizerH264::GetStorageType( + uint32_t retransmission_settings) { + return kAllowRetransmission; +} + +std::string RtpPacketizerH264::ToString() { + return "RtpPacketizerH264"; +} + RtpDepacketizerH264::RtpDepacketizerH264(RtpData* const callback) : callback_(callback) { } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h index 773fa18f3..abd9321fd 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264.h @@ -21,7 +21,7 @@ class RtpPacketizerH264 : public RtpPacketizer { public: // Initialize with payload from encoder. // The payload_data must be exactly one encoded H264 frame. - explicit RtpPacketizerH264(size_t max_payload_len); + RtpPacketizerH264(FrameType frame_type, size_t max_payload_len); virtual ~RtpPacketizerH264(); @@ -41,6 +41,12 @@ class RtpPacketizerH264 : public RtpPacketizer { size_t* bytes_to_send, bool* last_packet) OVERRIDE; + virtual ProtectionType GetProtectionType() OVERRIDE; + + virtual StorageType GetStorageType(uint32_t retrasmission_settings) OVERRIDE; + + virtual std::string ToString() OVERRIDE; + private: struct Packet { Packet(size_t offset, @@ -78,6 +84,7 @@ class RtpPacketizerH264 : public RtpPacketizer { const size_t max_payload_len_; RTPFragmentationHeader fragmentation_; PacketQueue packets_; + FrameType frame_type_; DISALLOW_COPY_AND_ASSIGN(RtpPacketizerH264); }; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc index 55b9712bd..fc30a0626 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc @@ -88,8 +88,8 @@ void TestFua(size_t frame_size, fragmentation.VerifyAndAllocateFragmentationHeader(1); fragmentation.fragmentationOffset[0] = 0; fragmentation.fragmentationLength[0] = frame_size; - scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, max_payload_size)); + scoped_ptr packetizer(RtpPacketizer::Create( + kRtpVideoH264, max_payload_size, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame.get(), frame_size, &fragmentation); scoped_ptr packet(new uint8_t[max_payload_size]); @@ -163,7 +163,7 @@ TEST(RtpPacketizerH264Test, TestSingleNalu) { fragmentation.fragmentationOffset[0] = 0; fragmentation.fragmentationLength[0] = sizeof(frame); scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize)); + RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation); uint8_t packet[kMaxPayloadSize] = {0}; size_t length = 0; @@ -192,7 +192,7 @@ TEST(RtpPacketizerH264Test, TestSingleNaluTwoPackets) { frame[fragmentation.fragmentationOffset[1]] = 0x01; scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize)); + RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); uint8_t packet[kMaxPayloadSize] = {0}; @@ -229,7 +229,7 @@ TEST(RtpPacketizerH264Test, TestStapA) { fragmentation.fragmentationLength[2] = kNalHeaderSize + kFrameSize - kPayloadOffset; scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize)); + RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); uint8_t packet[kMaxPayloadSize] = {0}; @@ -264,7 +264,7 @@ TEST(RtpPacketizerH264Test, TestTooSmallForStapAHeaders) { fragmentation.fragmentationLength[2] = kNalHeaderSize + kFrameSize - kPayloadOffset; scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize)); + RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); uint8_t packet[kMaxPayloadSize] = {0}; @@ -312,7 +312,7 @@ TEST(RtpPacketizerH264Test, TestMixedStapA_FUA) { } } scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize)); + RtpPacketizer::Create(kRtpVideoH264, kMaxPayloadSize, NULL, kFrameEmpty)); packetizer->SetPayloadData(frame, kFrameSize, &fragmentation); // First expecting two FU-A packets. diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc new file mode 100644 index 000000000..c28aa13bf --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.cc @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" + +namespace webrtc { + +static const size_t kGenericHeaderLength = 1; + +RtpPacketizerGeneric::RtpPacketizerGeneric(FrameType frame_type, + size_t max_payload_len) + : payload_data_(NULL), + payload_size_(0), + max_payload_len_(max_payload_len - kGenericHeaderLength), + frame_type_(frame_type) { +} + +RtpPacketizerGeneric::~RtpPacketizerGeneric() { +} + +void RtpPacketizerGeneric::SetPayloadData( + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation) { + payload_data_ = payload_data; + payload_size_ = payload_size; + + // Fragment packets more evenly by splitting the payload up evenly. + uint32_t num_packets = + (payload_size_ + max_payload_len_ - 1) / max_payload_len_; + payload_length_ = (payload_size_ + num_packets - 1) / num_packets; + assert(payload_length_ <= max_payload_len_); + + generic_header_ = RtpFormatVideoGeneric::kFirstPacketBit; +} + +bool RtpPacketizerGeneric::NextPacket(uint8_t* buffer, + size_t* bytes_to_send, + bool* last_packet) { + if (payload_size_ < payload_length_) { + payload_length_ = payload_size_; + } + + payload_size_ -= payload_length_; + *bytes_to_send = payload_length_ + kGenericHeaderLength; + assert(payload_length_ <= max_payload_len_); + + uint8_t* out_ptr = buffer; + // Put generic header in packet + if (frame_type_ == kVideoFrameKey) { + generic_header_ |= RtpFormatVideoGeneric::kKeyFrameBit; + } + *out_ptr++ = generic_header_; + // Remove first-packet bit, following packets are intermediate + generic_header_ &= ~RtpFormatVideoGeneric::kFirstPacketBit; + + // Put payload in packet + memcpy(out_ptr, payload_data_, payload_length_); + payload_data_ += payload_length_; + + *last_packet = payload_size_ <= 0; + + return true; +} + +ProtectionType RtpPacketizerGeneric::GetProtectionType() { + return kProtectedPacket; +} + +StorageType RtpPacketizerGeneric::GetStorageType( + uint32_t retransmission_settings) { + return kAllowRetransmission; +} + +std::string RtpPacketizerGeneric::ToString() { + return "RtpPacketizerGeneric"; +} + +RtpDepacketizerGeneric::RtpDepacketizerGeneric(RtpData* const callback) + : callback_(callback) { +} + +bool RtpDepacketizerGeneric::Parse(WebRtcRTPHeader* rtp_header, + const uint8_t* payload_data, + size_t payload_data_length) { + uint8_t generic_header = *payload_data++; + --payload_data_length; + + rtp_header->frameType = + ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) + ? kVideoFrameKey + : kVideoFrameDelta; + rtp_header->type.Video.isFirstPacket = + (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0; + + if (callback_->OnReceivedPayloadData( + payload_data, payload_data_length, rtp_header) != 0) { + return false; + } + return true; +} +} // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h index 93fcfa886..23a4e6bed 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h @@ -10,13 +10,72 @@ #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_ +#include "webrtc/common_types.h" +#include "webrtc/modules/rtp_rtcp/source/rtp_format.h" #include "webrtc/typedefs.h" namespace webrtc { namespace RtpFormatVideoGeneric { - static const uint8_t kKeyFrameBit = 0x01; - static const uint8_t kFirstPacketBit = 0x02; +static const uint8_t kKeyFrameBit = 0x01; +static const uint8_t kFirstPacketBit = 0x02; } // namespace RtpFormatVideoGeneric -} // namespace webrtc +class RtpPacketizerGeneric : public RtpPacketizer { + public: + // Initialize with payload from encoder. + // The payload_data must be exactly one encoded generic frame. + RtpPacketizerGeneric(FrameType frametype, size_t max_payload_len); + + virtual ~RtpPacketizerGeneric(); + + virtual void SetPayloadData( + const uint8_t* payload_data, + size_t payload_size, + const RTPFragmentationHeader* fragmentation) OVERRIDE; + + // Get the next payload with generic payload header. + // buffer is a pointer to where the output will be written. + // bytes_to_send is an output variable that will contain number of bytes + // written to buffer. The parameter last_packet is true for the last packet of + // the frame, false otherwise (i.e., call the function again to get the + // next packet). + // Returns true on success or false if there was no payload to packetize. + virtual bool NextPacket(uint8_t* buffer, + size_t* bytes_to_send, + bool* last_packet) OVERRIDE; + + virtual ProtectionType GetProtectionType() OVERRIDE; + + virtual StorageType GetStorageType(uint32_t retransmission_settings) OVERRIDE; + + virtual std::string ToString() OVERRIDE; + + private: + const uint8_t* payload_data_; + size_t payload_size_; + const size_t max_payload_len_; + FrameType frame_type_; + uint32_t payload_length_; + uint8_t generic_header_; + + DISALLOW_COPY_AND_ASSIGN(RtpPacketizerGeneric); +}; + +// Depacketizer for generic codec. +class RtpDepacketizerGeneric : public RtpDepacketizer { + public: + explicit RtpDepacketizerGeneric(RtpData* const callback); + + virtual ~RtpDepacketizerGeneric() {} + + virtual bool Parse(WebRtcRTPHeader* rtp_header, + const uint8_t* payload_data, + size_t payload_data_length) OVERRIDE; + + private: + RtpData* const callback_; + + DISALLOW_COPY_AND_ASSIGN(RtpDepacketizerGeneric); +}; +} // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VIDEO_GENERIC_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc index 049bd05e5..e638c361e 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.cc @@ -10,11 +10,12 @@ #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" -#include // assert +#include // assert #include // memcpy #include +#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" #include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h" namespace webrtc { @@ -107,6 +108,29 @@ bool RtpPacketizerVp8::NextPacket(uint8_t* buffer, return true; } +ProtectionType RtpPacketizerVp8::GetProtectionType() { + bool protect = + hdr_info_.temporalIdx == 0 || hdr_info_.temporalIdx == kNoTemporalIdx; + return protect ? kProtectedPacket : kUnprotectedPacket; +} + +StorageType RtpPacketizerVp8::GetStorageType(uint32_t retransmission_settings) { + StorageType storage = kAllowRetransmission; + if (hdr_info_.temporalIdx == 0 && + !(retransmission_settings & kRetransmitBaseLayer)) { + storage = kDontRetransmit; + } else if (hdr_info_.temporalIdx != kNoTemporalIdx && + hdr_info_.temporalIdx > 0 && + !(retransmission_settings & kRetransmitHigherLayers)) { + storage = kDontRetransmit; + } + return storage; +} + +std::string RtpPacketizerVp8::ToString() { + return "RtpPacketizerVp8"; +} + int RtpPacketizerVp8::CalcNextSize(int max_payload_len, int remaining_bytes, bool split_payload) const { @@ -123,17 +147,17 @@ int RtpPacketizerVp8::CalcNextSize(int max_payload_len, // Number of fragments for remaining_bytes: int num_frags = remaining_bytes / max_payload_len + 1; // Number of bytes in this fragment: - return static_cast(static_cast(remaining_bytes) - / num_frags + 0.5); + return static_cast(static_cast(remaining_bytes) / num_frags + + 0.5); } else { return max_payload_len >= remaining_bytes ? remaining_bytes - : max_payload_len; + : max_payload_len; } } int RtpPacketizerVp8::GeneratePackets() { - if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ - + PayloadDescriptorExtraLength() + 1) { + if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ + + PayloadDescriptorExtraLength() + 1) { // The provided payload length is not long enough for the payload // descriptor and one payload byte. Return an error. return -1; @@ -143,16 +167,18 @@ int RtpPacketizerVp8::GeneratePackets() { bool beginning = true; int part_ix = 0; while (total_bytes_processed < payload_size_) { - int packet_bytes = 0; // How much data to send in this packet. + int packet_bytes = 0; // How much data to send in this packet. bool split_payload = true; // Splitting of partitions is initially allowed. int remaining_in_partition = part_info_.fragmentationOffset[part_ix] - - total_bytes_processed + part_info_.fragmentationLength[part_ix]; - int rem_payload_len = max_payload_len_ - + total_bytes_processed + + part_info_.fragmentationLength[part_ix]; + int rem_payload_len = + max_payload_len_ - (vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength()); int first_partition_in_packet = part_ix; - while (int next_size = CalcNextSize(rem_payload_len, remaining_in_partition, - split_payload)) { + while (int next_size = CalcNextSize( + rem_payload_len, remaining_in_partition, split_payload)) { packet_bytes += next_size; rem_payload_len -= next_size; remaining_in_partition -= next_size; @@ -165,7 +191,7 @@ int RtpPacketizerVp8::GeneratePackets() { // with an intact partition (indicated by first_fragment_ == true). if (part_ix + 1 < num_partitions_ && ((aggr_mode_ == kAggrFragments) || - (aggr_mode_ == kAggrPartitions && start_on_new_fragment))) { + (aggr_mode_ == kAggrPartitions && start_on_new_fragment))) { assert(part_ix < num_partitions_); remaining_in_partition = part_info_.fragmentationLength[++part_ix]; // Disallow splitting unless kAggrFragments. In kAggrPartitions, @@ -181,7 +207,9 @@ int RtpPacketizerVp8::GeneratePackets() { } assert(packet_bytes > 0); - QueuePacket(total_bytes_processed, packet_bytes, first_partition_in_packet, + QueuePacket(total_bytes_processed, + packet_bytes, + first_partition_in_packet, start_on_new_fragment); total_bytes_processed += packet_bytes; start_on_new_fragment = (remaining_in_partition == 0); @@ -193,15 +221,15 @@ int RtpPacketizerVp8::GeneratePackets() { } int RtpPacketizerVp8::GeneratePacketsBalancedAggregates() { - if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ - + PayloadDescriptorExtraLength() + 1) { + if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ + + PayloadDescriptorExtraLength() + 1) { // The provided payload length is not long enough for the payload // descriptor and one payload byte. Return an error. return -1; } std::vector partition_decision; - const int overhead = vp8_fixed_payload_descriptor_bytes_ + - PayloadDescriptorExtraLength(); + const int overhead = + vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength(); const uint32_t max_payload_len = max_payload_len_ - overhead; int min_size, max_size; AggregateSmallPartitions(&partition_decision, &min_size, &max_size); @@ -217,10 +245,11 @@ int RtpPacketizerVp8::GeneratePacketsBalancedAggregates() { const int packet_bytes = (remaining_partition + num_fragments - 1) / num_fragments; for (int n = 0; n < num_fragments; ++n) { - const int this_packet_bytes = packet_bytes < remaining_partition ? - packet_bytes : remaining_partition; - QueuePacket(total_bytes_processed, this_packet_bytes, part_ix, - (n == 0)); + const int this_packet_bytes = packet_bytes < remaining_partition + ? packet_bytes + : remaining_partition; + QueuePacket( + total_bytes_processed, this_packet_bytes, part_ix, (n == 0)); remaining_partition -= this_packet_bytes; total_bytes_processed += this_packet_bytes; if (this_packet_bytes < min_size) { @@ -237,13 +266,15 @@ int RtpPacketizerVp8::GeneratePacketsBalancedAggregates() { const int first_partition_in_packet = part_ix; const int aggregation_index = partition_decision[part_ix]; while (static_cast(part_ix) < partition_decision.size() && - partition_decision[part_ix] == aggregation_index) { + partition_decision[part_ix] == aggregation_index) { // Collect all partitions that were aggregated into the same packet. this_packet_bytes += part_info_.fragmentationLength[part_ix]; ++part_ix; } - QueuePacket(total_bytes_processed, this_packet_bytes, - first_partition_in_packet, true); + QueuePacket(total_bytes_processed, + this_packet_bytes, + first_partition_in_packet, + true); total_bytes_processed += this_packet_bytes; } } @@ -259,8 +290,8 @@ void RtpPacketizerVp8::AggregateSmallPartitions(std::vector* partition_vec, *max_size = -1; assert(partition_vec); partition_vec->assign(num_partitions_, -1); - const int overhead = vp8_fixed_payload_descriptor_bytes_ + - PayloadDescriptorExtraLength(); + const int overhead = + vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength(); const uint32_t max_payload_len = max_payload_len_ - overhead; int first_in_set = 0; int last_in_set = 0; @@ -271,12 +302,12 @@ void RtpPacketizerVp8::AggregateSmallPartitions(std::vector* partition_vec, // Found start of a set. last_in_set = first_in_set; while (last_in_set + 1 < num_partitions_ && - part_info_.fragmentationLength[last_in_set + 1] < max_payload_len) { + part_info_.fragmentationLength[last_in_set + 1] < + max_payload_len) { ++last_in_set; } // Found end of a set. Run optimized aggregator. It is ok if start == end. - Vp8PartitionAggregator aggregator(part_info_, first_in_set, - last_in_set); + Vp8PartitionAggregator aggregator(part_info_, first_in_set, last_in_set); if (*min_size >= 0 && *max_size >= 0) { aggregator.SetPriorMinMax(*min_size, *max_size); } @@ -328,19 +359,23 @@ int RtpPacketizerVp8::WriteHeaderAndPayload(const InfoStruct& packet_info, assert(packet_info.size > 0); buffer[0] = 0; - if (XFieldPresent()) buffer[0] |= kXBit; - if (hdr_info_.nonReference) buffer[0] |= kNBit; - if (packet_info.first_fragment) buffer[0] |= kSBit; + if (XFieldPresent()) + buffer[0] |= kXBit; + if (hdr_info_.nonReference) + buffer[0] |= kNBit; + if (packet_info.first_fragment) + buffer[0] |= kSBit; buffer[0] |= (packet_info.first_partition_ix & kPartIdField); const int extension_length = WriteExtensionFields(buffer, buffer_length); memcpy(&buffer[vp8_fixed_payload_descriptor_bytes_ + extension_length], - &payload_data_[packet_info.payload_start_pos], packet_info.size); + &payload_data_[packet_info.payload_start_pos], + packet_info.size); // Return total length of written data. - return packet_info.size + vp8_fixed_payload_descriptor_bytes_ - + extension_length; + return packet_info.size + vp8_fixed_payload_descriptor_bytes_ + + extension_length; } int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer, @@ -351,20 +386,20 @@ int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer, *x_field = 0; extension_length = 1; // One octet for the X field. if (PictureIdPresent()) { - if (WritePictureIDFields(x_field, buffer, buffer_length, - &extension_length) < 0) { + if (WritePictureIDFields( + x_field, buffer, buffer_length, &extension_length) < 0) { return -1; } } if (TL0PicIdxFieldPresent()) { - if (WriteTl0PicIdxFields(x_field, buffer, buffer_length, - &extension_length) < 0) { + if (WriteTl0PicIdxFields( + x_field, buffer, buffer_length, &extension_length) < 0) { return -1; } } if (TIDFieldPresent() || KeyIdxFieldPresent()) { - if (WriteTIDAndKeyIdxFields(x_field, buffer, buffer_length, - &extension_length) < 0) { + if (WriteTIDAndKeyIdxFields( + x_field, buffer, buffer_length, &extension_length) < 0) { return -1; } } @@ -380,18 +415,18 @@ int RtpPacketizerVp8::WritePictureIDFields(uint8_t* x_field, *x_field |= kIBit; const int pic_id_length = WritePictureID( buffer + vp8_fixed_payload_descriptor_bytes_ + *extension_length, - buffer_length - vp8_fixed_payload_descriptor_bytes_ - - *extension_length); - if (pic_id_length < 0) return -1; + buffer_length - vp8_fixed_payload_descriptor_bytes_ - *extension_length); + if (pic_id_length < 0) + return -1; *extension_length += pic_id_length; return 0; } int RtpPacketizerVp8::WritePictureID(uint8_t* buffer, int buffer_length) const { - const uint16_t pic_id = - static_cast (hdr_info_.pictureId); + const uint16_t pic_id = static_cast(hdr_info_.pictureId); int picture_id_len = PictureIdLength(); - if (picture_id_len > buffer_length) return -1; + if (picture_id_len > buffer_length) + return -1; if (picture_id_len == 2) { buffer[0] = 0x80 | ((pic_id >> 8) & 0x7F); buffer[1] = pic_id & 0xFF; @@ -405,13 +440,13 @@ int RtpPacketizerVp8::WriteTl0PicIdxFields(uint8_t* x_field, uint8_t* buffer, int buffer_length, int* extension_length) const { - if (buffer_length < vp8_fixed_payload_descriptor_bytes_ + *extension_length - + 1) { + if (buffer_length < + vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) { return -1; } *x_field |= kLBit; - buffer[vp8_fixed_payload_descriptor_bytes_ - + *extension_length] = hdr_info_.tl0PicIdx; + buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length] = + hdr_info_.tl0PicIdx; ++*extension_length; return 0; } @@ -420,8 +455,8 @@ int RtpPacketizerVp8::WriteTIDAndKeyIdxFields(uint8_t* x_field, uint8_t* buffer, int buffer_length, int* extension_length) const { - if (buffer_length < vp8_fixed_payload_descriptor_bytes_ + *extension_length - + 1) { + if (buffer_length < + vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) { return -1; } uint8_t* data_field = @@ -443,9 +478,12 @@ int RtpPacketizerVp8::WriteTIDAndKeyIdxFields(uint8_t* x_field, int RtpPacketizerVp8::PayloadDescriptorExtraLength() const { int length_bytes = PictureIdLength(); - if (TL0PicIdxFieldPresent()) ++length_bytes; - if (TIDFieldPresent() || KeyIdxFieldPresent()) ++length_bytes; - if (length_bytes > 0) ++length_bytes; // Include the extension field. + if (TL0PicIdxFieldPresent()) + ++length_bytes; + if (TIDFieldPresent() || KeyIdxFieldPresent()) + ++length_bytes; + if (length_bytes > 0) + ++length_bytes; // Include the extension field. return length_bytes; } @@ -460,8 +498,8 @@ int RtpPacketizerVp8::PictureIdLength() const { } bool RtpPacketizerVp8::XFieldPresent() const { - return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent() - || KeyIdxFieldPresent()); + return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent() || + KeyIdxFieldPresent()); } bool RtpPacketizerVp8::TIDFieldPresent() const { @@ -477,4 +515,58 @@ bool RtpPacketizerVp8::KeyIdxFieldPresent() const { bool RtpPacketizerVp8::TL0PicIdxFieldPresent() const { return (hdr_info_.tl0PicIdx != kNoTl0PicIdx); } + +RtpDepacketizerVp8::RtpDepacketizerVp8(RtpData* const callback) + : callback_(callback) { +} + +bool RtpDepacketizerVp8::Parse(WebRtcRTPHeader* rtp_header, + const uint8_t* payload_data, + size_t payload_data_length) { + RtpUtility::RTPPayload parsed_packet; + RtpUtility::RTPPayloadParser rtp_payload_parser( + kRtpVideoVp8, payload_data, payload_data_length); + + if (!rtp_payload_parser.Parse(parsed_packet)) + return false; + + if (parsed_packet.info.VP8.dataLength == 0) + return true; + + rtp_header->frameType = (parsed_packet.frameType == RtpUtility::kIFrame) + ? kVideoFrameKey + : kVideoFrameDelta; + + RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8; + RtpUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8; + + rtp_header->type.Video.isFirstPacket = + from_header->beginningOfPartition && (from_header->partitionID == 0); + to_header->nonReference = from_header->nonReferenceFrame; + to_header->pictureId = + from_header->hasPictureID ? from_header->pictureID : kNoPictureId; + to_header->tl0PicIdx = + from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx; + if (from_header->hasTID) { + to_header->temporalIdx = from_header->tID; + to_header->layerSync = from_header->layerSync; + } else { + to_header->temporalIdx = kNoTemporalIdx; + to_header->layerSync = false; + } + to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx; + + rtp_header->type.Video.width = from_header->frameWidth; + rtp_header->type.Video.height = from_header->frameHeight; + + to_header->partitionId = from_header->partitionID; + to_header->beginningOfPartition = from_header->beginningOfPartition; + + if (callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data, + parsed_packet.info.VP8.dataLength, + rtp_header) != 0) { + return false; + } + return true; +} } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h index 755d19ed1..85a3304de 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h @@ -79,6 +79,12 @@ class RtpPacketizerVp8 : public RtpPacketizer { size_t* bytes_to_send, bool* last_packet) OVERRIDE; + virtual ProtectionType GetProtectionType() OVERRIDE; + + virtual StorageType GetStorageType(uint32_t retransmission_settings) OVERRIDE; + + virtual std::string ToString() OVERRIDE; + private: typedef struct { int payload_start_pos; @@ -96,19 +102,20 @@ class RtpPacketizerVp8 : public RtpPacketizer { static const AggregationMode aggr_modes_[kNumModes]; static const bool balance_modes_[kNumModes]; static const bool separate_first_modes_[kNumModes]; - static const int kXBit = 0x80; - static const int kNBit = 0x20; - static const int kSBit = 0x10; + static const int kXBit = 0x80; + static const int kNBit = 0x20; + static const int kSBit = 0x10; static const int kPartIdField = 0x0F; static const int kKeyIdxField = 0x1F; - static const int kIBit = 0x80; - static const int kLBit = 0x40; - static const int kTBit = 0x20; - static const int kKBit = 0x10; - static const int kYBit = 0x20; + static const int kIBit = 0x80; + static const int kLBit = 0x40; + static const int kTBit = 0x20; + static const int kKBit = 0x10; + static const int kYBit = 0x20; // Calculate size of next chunk to send. Returns 0 if none can be sent. - int CalcNextSize(int max_payload_len, int remaining_bytes, + int CalcNextSize(int max_payload_len, + int remaining_bytes, bool split_payload) const; // Calculate all packet sizes and load to packet info queue. @@ -144,7 +151,6 @@ class RtpPacketizerVp8 : public RtpPacketizer { uint8_t* buffer, int buffer_length) const; - // Write the X field and the appropriate extension fields to buffer. // The function returns the extension length (including X field), or -1 // on error. @@ -152,19 +158,25 @@ class RtpPacketizerVp8 : public RtpPacketizer { // Set the I bit in the x_field, and write PictureID to the appropriate // position in buffer. The function returns 0 on success, -1 otherwise. - int WritePictureIDFields(uint8_t* x_field, uint8_t* buffer, - int buffer_length, int* extension_length) const; + int WritePictureIDFields(uint8_t* x_field, + uint8_t* buffer, + int buffer_length, + int* extension_length) const; // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate // position in buffer. The function returns 0 on success, -1 otherwise. - int WriteTl0PicIdxFields(uint8_t* x_field, uint8_t* buffer, - int buffer_length, int* extension_length) const; + int WriteTl0PicIdxFields(uint8_t* x_field, + uint8_t* buffer, + int buffer_length, + int* extension_length) const; // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the // appropriate position in buffer. The function returns 0 on success, // -1 otherwise. - int WriteTIDAndKeyIdxFields(uint8_t* x_field, uint8_t* buffer, - int buffer_length, int* extension_length) const; + int WriteTIDAndKeyIdxFields(uint8_t* x_field, + uint8_t* buffer, + int buffer_length, + int* extension_length) const; // Write the PictureID from codec_specific_info_ to buffer. One or two // bytes are written, depending on magnitude of PictureID. The function @@ -202,5 +214,22 @@ class RtpPacketizerVp8 : public RtpPacketizer { DISALLOW_COPY_AND_ASSIGN(RtpPacketizerVp8); }; -} // namespace + +// Depacketizer for VP8. +class RtpDepacketizerVp8 : public RtpDepacketizer { + public: + explicit RtpDepacketizerVp8(RtpData* const callback); + + virtual ~RtpDepacketizerVp8() {} + + virtual bool Parse(WebRtcRTPHeader* rtp_header, + const uint8_t* payload_data, + size_t payload_data_length) OVERRIDE; + + private: + RtpData* const callback_; + + DISALLOW_COPY_AND_ASSIGN(RtpDepacketizerVp8); +}; +} // namespace webrtc #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc index 8dfc27ac7..c6574e6e7 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc @@ -297,5 +297,4 @@ TEST_F(RtpPacketizerVp8Test, TestTIDAndKeyIdx) { helper_->GetAllPacketsAndCheck(&packetizer, kExpectedSizes, kExpectedPart, kExpectedFragStart, kExpectedNum); } - } // namespace diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc index 5eb5710fb..058d91e37 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.cc @@ -29,13 +29,13 @@ RTPReceiverStrategy* RTPReceiverStrategy::CreateVideoStrategy( } RTPReceiverVideo::RTPReceiverVideo(RtpData* data_callback) - : RTPReceiverStrategy(data_callback) {} + : RTPReceiverStrategy(data_callback) { +} RTPReceiverVideo::~RTPReceiverVideo() { } -bool RTPReceiverVideo::ShouldReportCsrcChanges( - uint8_t payload_type) const { +bool RTPReceiverVideo::ShouldReportCsrcChanges(uint8_t payload_type) const { // Always do this for video packets. return true; } @@ -47,17 +47,19 @@ int32_t RTPReceiverVideo::OnNewPayloadTypeCreated( return 0; } -int32_t RTPReceiverVideo::ParseRtpPacket( - WebRtcRTPHeader* rtp_header, - const PayloadUnion& specific_payload, - bool is_red, - const uint8_t* payload, - uint16_t payload_length, - int64_t timestamp_ms, - bool is_first_packet) { - TRACE_EVENT2("webrtc_rtp", "Video::ParseRtp", - "seqnum", rtp_header->header.sequenceNumber, - "timestamp", rtp_header->header.timestamp); +int32_t RTPReceiverVideo::ParseRtpPacket(WebRtcRTPHeader* rtp_header, + const PayloadUnion& specific_payload, + bool is_red, + const uint8_t* payload, + uint16_t payload_length, + int64_t timestamp_ms, + bool is_first_packet) { + TRACE_EVENT2("webrtc_rtp", + "Video::ParseRtp", + "seqnum", + rtp_header->header.sequenceNumber, + "timestamp", + rtp_header->header.timestamp); rtp_header->type.Video.codec = specific_payload.Video.videoCodecType; const uint16_t payload_data_length = @@ -67,12 +69,16 @@ int32_t RTPReceiverVideo::ParseRtpPacket( return data_callback_->OnReceivedPayloadData(NULL, 0, rtp_header) == 0 ? 0 : -1; - return ParseVideoCodecSpecific(rtp_header, - payload, - payload_data_length, - specific_payload.Video.videoCodecType, - timestamp_ms, - is_first_packet); + // We are not allowed to hold a critical section when calling below functions. + scoped_ptr depacketizer( + RtpDepacketizer::Create(rtp_header->type.Video.codec, data_callback_)); + if (depacketizer.get() == NULL) { + LOG(LS_ERROR) << "Failed to create depacketizer."; + return -1; + } + + rtp_header->type.Video.isFirstPacket = is_first_packet; + return depacketizer->Parse(rtp_header, payload, payload_data_length) ? 0 : -1; } int RTPReceiverVideo::GetPayloadTypeFrequency() const { @@ -91,8 +97,9 @@ int32_t RTPReceiverVideo::InvokeOnInitializeDecoder( const char payload_name[RTP_PAYLOAD_NAME_SIZE], const PayloadUnion& specific_payload) const { // For video we just go with default values. - if (-1 == callback->OnInitializeDecoder( - id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) { + if (-1 == + callback->OnInitializeDecoder( + id, payload_type, payload_name, kVideoPayloadTypeFrequency, 1, 0)) { LOG(LS_ERROR) << "Failed to created decoder for payload type: " << payload_type; return -1; @@ -100,36 +107,8 @@ int32_t RTPReceiverVideo::InvokeOnInitializeDecoder( return 0; } -// We are not allowed to hold a critical section when calling this function. -int32_t RTPReceiverVideo::ParseVideoCodecSpecific( - WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length, - RtpVideoCodecTypes video_type, - int64_t now_ms, - bool is_first_packet) { - switch (rtp_header->type.Video.codec) { - case kRtpVideoGeneric: - rtp_header->type.Video.isFirstPacket = is_first_packet; - return ReceiveGenericCodec(rtp_header, payload_data, payload_data_length); - case kRtpVideoVp8: - return ReceiveVp8Codec(rtp_header, payload_data, payload_data_length); - case kRtpVideoH264: { - scoped_ptr depacketizer(RtpDepacketizer::Create( - rtp_header->type.Video.codec, data_callback_)); - return depacketizer->Parse(rtp_header, payload_data, payload_data_length) - ? 0 - : -1; - } - case kRtpVideoNone: - break; - } - return -1; -} - -int32_t RTPReceiverVideo::BuildRTPheader( - const WebRtcRTPHeader* rtp_header, - uint8_t* data_buffer) const { +int32_t RTPReceiverVideo::BuildRTPheader(const WebRtcRTPHeader* rtp_header, + uint8_t* data_buffer) const { data_buffer[0] = static_cast(0x80); // version 2 data_buffer[1] = static_cast(rtp_header->header.payloadType); if (rtp_header->header.markerBit) { @@ -161,73 +140,4 @@ int32_t RTPReceiverVideo::BuildRTPheader( return rtp_header_length; } -int32_t RTPReceiverVideo::ReceiveVp8Codec(WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length) { - RtpUtility::RTPPayload parsed_packet; - RtpUtility::RTPPayloadParser rtp_payload_parser( - kRtpVideoVp8, payload_data, payload_data_length); - - if (!rtp_payload_parser.Parse(parsed_packet)) - return -1; - - if (parsed_packet.info.VP8.dataLength == 0) - return 0; - - rtp_header->frameType = (parsed_packet.frameType == RtpUtility::kIFrame) - ? kVideoFrameKey - : kVideoFrameDelta; - - RTPVideoHeaderVP8* to_header = &rtp_header->type.Video.codecHeader.VP8; - RtpUtility::RTPPayloadVP8* from_header = &parsed_packet.info.VP8; - - rtp_header->type.Video.isFirstPacket = - from_header->beginningOfPartition && (from_header->partitionID == 0); - to_header->nonReference = from_header->nonReferenceFrame; - to_header->pictureId = - from_header->hasPictureID ? from_header->pictureID : kNoPictureId; - to_header->tl0PicIdx = - from_header->hasTl0PicIdx ? from_header->tl0PicIdx : kNoTl0PicIdx; - if (from_header->hasTID) { - to_header->temporalIdx = from_header->tID; - to_header->layerSync = from_header->layerSync; - } else { - to_header->temporalIdx = kNoTemporalIdx; - to_header->layerSync = false; - } - to_header->keyIdx = from_header->hasKeyIdx ? from_header->keyIdx : kNoKeyIdx; - - rtp_header->type.Video.width = from_header->frameWidth; - rtp_header->type.Video.height = from_header->frameHeight; - - to_header->partitionId = from_header->partitionID; - to_header->beginningOfPartition = from_header->beginningOfPartition; - - if (data_callback_->OnReceivedPayloadData(parsed_packet.info.VP8.data, - parsed_packet.info.VP8.dataLength, - rtp_header) != 0) { - return -1; - } - return 0; -} - -int32_t RTPReceiverVideo::ReceiveGenericCodec( - WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length) { - uint8_t generic_header = *payload_data++; - --payload_data_length; - - rtp_header->frameType = - ((generic_header & RtpFormatVideoGeneric::kKeyFrameBit) != 0) ? - kVideoFrameKey : kVideoFrameDelta; - rtp_header->type.Video.isFirstPacket = - (generic_header & RtpFormatVideoGeneric::kFirstPacketBit) != 0; - - if (data_callback_->OnReceivedPayloadData( - payload_data, payload_data_length, rtp_header) != 0) { - return -1; - } - return 0; -} } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h index 365e4d740..8fe4acb80 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h @@ -22,27 +22,24 @@ namespace webrtc { class RTPReceiverVideo : public RTPReceiverStrategy { public: - RTPReceiverVideo(RtpData* data_callback); + explicit RTPReceiverVideo(RtpData* data_callback); virtual ~RTPReceiverVideo(); - virtual int32_t ParseRtpPacket( - WebRtcRTPHeader* rtp_header, - const PayloadUnion& specific_payload, - bool is_red, - const uint8_t* packet, - uint16_t packet_length, - int64_t timestamp, - bool is_first_packet) OVERRIDE; + virtual int32_t ParseRtpPacket(WebRtcRTPHeader* rtp_header, + const PayloadUnion& specific_payload, + bool is_red, + const uint8_t* packet, + uint16_t packet_length, + int64_t timestamp, + bool is_first_packet) OVERRIDE; - TelephoneEventHandler* GetTelephoneEventHandler() { - return NULL; - } + TelephoneEventHandler* GetTelephoneEventHandler() { return NULL; } int GetPayloadTypeFrequency() const OVERRIDE; - virtual RTPAliveType ProcessDeadOrAlive(uint16_t last_payload_length) const - OVERRIDE; + virtual RTPAliveType ProcessDeadOrAlive( + uint16_t last_payload_length) const OVERRIDE; virtual bool ShouldReportCsrcChanges(uint8_t payload_type) const OVERRIDE; @@ -61,28 +58,8 @@ class RTPReceiverVideo : public RTPReceiverStrategy { void SetPacketOverHead(uint16_t packet_over_head); private: - int32_t ReceiveGenericCodec(WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length); - - int32_t ReceiveVp8Codec(WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length); - - int32_t ReceiveH264Codec(WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length); - int32_t BuildRTPheader(const WebRtcRTPHeader* rtp_header, uint8_t* data_buffer) const; - - int32_t ParseVideoCodecSpecific( - WebRtcRTPHeader* rtp_header, - const uint8_t* payload_data, - uint16_t payload_data_length, - RtpVideoCodecTypes video_type, - int64_t now_ms, - bool is_first_packet); }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi b/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi index 05741a069..a6d211549 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp.gypi @@ -92,6 +92,7 @@ 'rtp_format_h264.h', 'rtp_format_vp8.cc', 'rtp_format_vp8.h', + 'rtp_format_video_generic.cc', 'rtp_format_video_generic.h', 'vp8_partition_aggregator.cc', 'vp8_partition_aggregator.h', diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc index da58f6165..ec031dfc8 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc @@ -31,8 +31,7 @@ struct RtpPacket { ForwardErrorCorrection::Packet* pkt; }; -RTPSenderVideo::RTPSenderVideo(Clock* clock, - RTPSenderInterface* rtpSender) +RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender) : _rtpSender(*rtpSender), _sendVideoCritsect(CriticalSectionWrapper::CreateCriticalSection()), _videoType(kRtpVideoGeneric), @@ -55,29 +54,23 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock, memset(&key_fec_params_, 0, sizeof(key_fec_params_)); delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = - kFecMaskRandom; + kFecMaskRandom; } -RTPSenderVideo::~RTPSenderVideo() -{ - if(_videoCodecInformation) - { - delete _videoCodecInformation; - } - delete _sendVideoCritsect; +RTPSenderVideo::~RTPSenderVideo() { + if (_videoCodecInformation) { + delete _videoCodecInformation; + } + delete _sendVideoCritsect; } -void -RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) -{ - CriticalSectionScoped cs(_sendVideoCritsect); - _videoType = videoType; +void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes videoType) { + CriticalSectionScoped cs(_sendVideoCritsect); + _videoType = videoType; } -RtpVideoCodecTypes -RTPSenderVideo::VideoCodecType() const -{ - return _videoType; +RtpVideoCodecTypes RTPSenderVideo::VideoCodecType() const { + return _videoType; } int32_t RTPSenderVideo::RegisterVideoPayload( @@ -106,34 +99,34 @@ int32_t RTPSenderVideo::RegisterVideoPayload( return 0; } -int32_t -RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, - const uint16_t payload_length, - const uint16_t rtp_header_length, - const uint32_t capture_timestamp, - int64_t capture_time_ms, - StorageType storage, - bool protect) { - if(_fecEnabled) { +int32_t RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, + const uint16_t payload_length, + const uint16_t rtp_header_length, + const uint32_t capture_timestamp, + int64_t capture_time_ms, + StorageType storage, + bool protect) { + if (_fecEnabled) { int ret = 0; int fec_overhead_sent = 0; int video_sent = 0; - RedPacket* red_packet = producer_fec_.BuildRedPacket(data_buffer, - payload_length, - rtp_header_length, - _payloadTypeRED); - TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketRed", - "timestamp", capture_timestamp, - "seqnum", _rtpSender.SequenceNumber()); + RedPacket* red_packet = producer_fec_.BuildRedPacket( + data_buffer, payload_length, rtp_header_length, _payloadTypeRED); + TRACE_EVENT_INSTANT2("webrtc_rtp", + "Video::PacketRed", + "timestamp", + capture_timestamp, + "seqnum", + _rtpSender.SequenceNumber()); // Sending the media packet with RED header. - int packet_success = _rtpSender.SendToNetwork( - red_packet->data(), - red_packet->length() - rtp_header_length, - rtp_header_length, - capture_time_ms, - storage, - PacedSender::kNormalPriority); + int packet_success = + _rtpSender.SendToNetwork(red_packet->data(), + red_packet->length() - rtp_header_length, + rtp_header_length, + capture_time_ms, + storage, + PacedSender::kNormalPriority); ret |= packet_success; @@ -144,34 +137,36 @@ RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, red_packet = NULL; if (protect) { - ret = producer_fec_.AddRtpPacketAndGenerateFec(data_buffer, - payload_length, - rtp_header_length); + ret = producer_fec_.AddRtpPacketAndGenerateFec( + data_buffer, payload_length, rtp_header_length); if (ret != 0) return ret; } while (producer_fec_.FecAvailable()) { - red_packet = producer_fec_.GetFecPacket( - _payloadTypeRED, - _payloadTypeFEC, - _rtpSender.IncrementSequenceNumber(), - rtp_header_length); + red_packet = + producer_fec_.GetFecPacket(_payloadTypeRED, + _payloadTypeFEC, + _rtpSender.IncrementSequenceNumber(), + rtp_header_length); StorageType storage = kDontRetransmit; if (_retransmissionSettings & kRetransmitFECPackets) { storage = kAllowRetransmission; } - TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketFec", - "timestamp", capture_timestamp, - "seqnum", _rtpSender.SequenceNumber()); + TRACE_EVENT_INSTANT2("webrtc_rtp", + "Video::PacketFec", + "timestamp", + capture_timestamp, + "seqnum", + _rtpSender.SequenceNumber()); // Sending FEC packet with RED header. - int packet_success = _rtpSender.SendToNetwork( - red_packet->data(), - red_packet->length() - rtp_header_length, - rtp_header_length, - capture_time_ms, - storage, - PacedSender::kNormalPriority); + int packet_success = + _rtpSender.SendToNetwork(red_packet->data(), + red_packet->length() - rtp_header_length, + rtp_header_length, + capture_time_ms, + storage, + PacedSender::kNormalPriority); ret |= packet_success; @@ -185,9 +180,12 @@ RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, _fecOverheadRate.Update(fec_overhead_sent); return ret; } - TRACE_EVENT_INSTANT2("webrtc_rtp", "Video::PacketNormal", - "timestamp", capture_timestamp, - "seqnum", _rtpSender.SequenceNumber()); + TRACE_EVENT_INSTANT2("webrtc_rtp", + "Video::PacketNormal", + "timestamp", + capture_timestamp, + "seqnum", + _rtpSender.SequenceNumber()); int ret = _rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length, @@ -200,69 +198,61 @@ RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer, return ret; } -int32_t -RTPSenderVideo::SendRTPIntraRequest() -{ - // RFC 2032 - // 5.2.1. Full intra-frame Request (FIR) packet +int32_t RTPSenderVideo::SendRTPIntraRequest() { + // RFC 2032 + // 5.2.1. Full intra-frame Request (FIR) packet - uint16_t length = 8; - uint8_t data[8]; - data[0] = 0x80; - data[1] = 192; - data[2] = 0; - data[3] = 1; // length + uint16_t length = 8; + uint8_t data[8]; + data[0] = 0x80; + data[1] = 192; + data[2] = 0; + data[3] = 1; // length - RtpUtility::AssignUWord32ToBuffer(data + 4, _rtpSender.SSRC()); + RtpUtility::AssignUWord32ToBuffer(data + 4, _rtpSender.SSRC()); - TRACE_EVENT_INSTANT1("webrtc_rtp", - "Video::IntraRequest", - "seqnum", _rtpSender.SequenceNumber()); - return _rtpSender.SendToNetwork(data, 0, length, -1, kDontStore, - PacedSender::kNormalPriority); + TRACE_EVENT_INSTANT1("webrtc_rtp", + "Video::IntraRequest", + "seqnum", + _rtpSender.SequenceNumber()); + return _rtpSender.SendToNetwork( + data, 0, length, -1, kDontStore, PacedSender::kNormalPriority); } -int32_t -RTPSenderVideo::SetGenericFECStatus(const bool enable, - const uint8_t payloadTypeRED, - const uint8_t payloadTypeFEC) -{ - _fecEnabled = enable; - _payloadTypeRED = payloadTypeRED; - _payloadTypeFEC = payloadTypeFEC; - memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); - memset(&key_fec_params_, 0, sizeof(key_fec_params_)); - delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; - delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = - kFecMaskRandom; - return 0; +int32_t RTPSenderVideo::SetGenericFECStatus(const bool enable, + const uint8_t payloadTypeRED, + const uint8_t payloadTypeFEC) { + _fecEnabled = enable; + _payloadTypeRED = payloadTypeRED; + _payloadTypeFEC = payloadTypeFEC; + memset(&delta_fec_params_, 0, sizeof(delta_fec_params_)); + memset(&key_fec_params_, 0, sizeof(key_fec_params_)); + delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1; + delta_fec_params_.fec_mask_type = key_fec_params_.fec_mask_type = + kFecMaskRandom; + return 0; } -int32_t -RTPSenderVideo::GenericFECStatus(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC) const -{ - enable = _fecEnabled; - payloadTypeRED = _payloadTypeRED; - payloadTypeFEC = _payloadTypeFEC; - return 0; +int32_t RTPSenderVideo::GenericFECStatus(bool& enable, + uint8_t& payloadTypeRED, + uint8_t& payloadTypeFEC) const { + enable = _fecEnabled; + payloadTypeRED = _payloadTypeRED; + payloadTypeFEC = _payloadTypeFEC; + return 0; } -uint16_t -RTPSenderVideo::FECPacketOverhead() const -{ - if (_fecEnabled) - { - // Overhead is FEC headers plus RED for FEC header plus anything in RTP - // header beyond the 12 bytes base header (CSRC list, extensions...) - // This reason for the header extensions to be included here is that - // from an FEC viewpoint, they are part of the payload to be protected. - // (The base RTP header is already protected by the FEC header.) - return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength + - (_rtpSender.RTPHeaderLength() - kRtpHeaderSize); - } - return 0; +uint16_t RTPSenderVideo::FECPacketOverhead() const { + if (_fecEnabled) { + // Overhead is FEC headers plus RED for FEC header plus anything in RTP + // header beyond the 12 bytes base header (CSRC list, extensions...) + // This reason for the header extensions to be included here is that + // from an FEC viewpoint, they are part of the payload to be protected. + // (The base RTP header is already protected by the FEC header.) + return ForwardErrorCorrection::PacketOverhead() + REDForFECHeaderLength + + (_rtpSender.RTPHeaderLength() - kRtpHeaderSize); + } + return 0; } int32_t RTPSenderVideo::SetFecParameters( @@ -299,206 +289,58 @@ int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType, // Will be extracted in SendVP8 for VP8 codec; other codecs use 0 _numberFirstPartition = 0; - switch (videoType) { - case kRtpVideoGeneric: - return SendGeneric(frameType, - payloadType, - captureTimeStamp, - capture_time_ms, - payloadData, - payloadSize); - case kRtpVideoVp8: - return SendVP8(frameType, - payloadType, - captureTimeStamp, - capture_time_ms, - payloadData, - payloadSize, - fragmentation, - rtpTypeHdr); - case kRtpVideoH264: - return SendH264(frameType, - payloadType, - captureTimeStamp, - capture_time_ms, - payloadData, - payloadSize, - fragmentation, - rtpTypeHdr) - ? 0 - : -1; - default: - assert(false); - break; - } - return 0; + return Send(videoType, + frameType, + payloadType, + captureTimeStamp, + capture_time_ms, + payloadData, + payloadSize, + fragmentation, + rtpTypeHdr) + ? 0 + : -1; } -int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type, - const int8_t payload_type, - const uint32_t capture_timestamp, - int64_t capture_time_ms, - const uint8_t* payload, - uint32_t size) { - assert(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta); +VideoCodecInformation* RTPSenderVideo::CodecInformationVideo() { + return _videoCodecInformation; +} + +void RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) { + _maxBitrate = maxBitrate; +} + +uint32_t RTPSenderVideo::MaxConfiguredBitrateVideo() const { + return _maxBitrate; +} + +bool RTPSenderVideo::Send(const RtpVideoCodecTypes videoType, + const FrameType frameType, + const int8_t payloadType, + const uint32_t captureTimeStamp, + int64_t capture_time_ms, + const uint8_t* payloadData, + const uint32_t payloadSize, + const RTPFragmentationHeader* fragmentation, + const RTPVideoTypeHeader* rtpTypeHdr) { uint16_t rtp_header_length = _rtpSender.RTPHeaderLength(); - uint16_t max_length = _rtpSender.MaxPayloadLength() - FECPacketOverhead() - - rtp_header_length - (1 /* generic header length */); - - // Fragment packets more evenly by splitting the payload up evenly. - uint32_t num_packets = (size + max_length - 1) / max_length; - uint32_t payload_length = (size + num_packets - 1) / num_packets; - assert(payload_length <= max_length); - - // Fragment packet into packets of max MaxPayloadLength bytes payload. - uint8_t buffer[IP_PACKET_SIZE]; - - uint8_t generic_header = RtpFormatVideoGeneric::kFirstPacketBit; - if (frame_type == kVideoFrameKey) { - generic_header |= RtpFormatVideoGeneric::kKeyFrameBit; - } - - while (size > 0) { - if (size < payload_length) { - payload_length = size; - } - size -= payload_length; - - // MarkerBit is 1 on final packet (bytes_to_send == 0) - if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0, - capture_timestamp, - capture_time_ms) != rtp_header_length) { - return -1; - } - - uint8_t* out_ptr = &buffer[rtp_header_length]; - - // Put generic header in packet - *out_ptr++ = generic_header; - // Remove first-packet bit, following packets are intermediate - generic_header &= ~RtpFormatVideoGeneric::kFirstPacketBit; - - // Put payload in packet - memcpy(out_ptr, payload, payload_length); - payload += payload_length; - - if (SendVideoPacket(buffer, payload_length + 1, rtp_header_length, - capture_timestamp, capture_time_ms, - kAllowRetransmission, true)) { - return -1; - } - } - return 0; -} - -VideoCodecInformation* -RTPSenderVideo::CodecInformationVideo() -{ - return _videoCodecInformation; -} - -void -RTPSenderVideo::SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate) -{ - _maxBitrate = maxBitrate; -} - -uint32_t -RTPSenderVideo::MaxConfiguredBitrateVideo() const -{ - return _maxBitrate; -} - -int32_t -RTPSenderVideo::SendVP8(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const uint32_t payloadSize, - const RTPFragmentationHeader* fragmentation, - const RTPVideoTypeHeader* rtpTypeHdr) -{ - const uint16_t rtpHeaderLength = _rtpSender.RTPHeaderLength(); - - int32_t payloadBytesToSend = payloadSize; - const uint8_t* data = payloadData; - - uint16_t maxPayloadLengthVP8 = _rtpSender.MaxDataPayloadLength(); - - assert(rtpTypeHdr); - // Initialize disregarding partition boundaries: this will use kEqualSize - // packetization mode, which produces ~equal size packets for each frame. - RtpPacketizerVp8 packetizer(rtpTypeHdr->VP8, maxPayloadLengthVP8); - packetizer.SetPayloadData(data, payloadBytesToSend, NULL); - - StorageType storage = kAllowRetransmission; - if (rtpTypeHdr->VP8.temporalIdx == 0 && - !(_retransmissionSettings & kRetransmitBaseLayer)) { - storage = kDontRetransmit; - } else if (rtpTypeHdr->VP8.temporalIdx != kNoTemporalIdx && - rtpTypeHdr->VP8.temporalIdx > 0 && - !(_retransmissionSettings & kRetransmitHigherLayers)) { - storage = kDontRetransmit; - } - - bool last = false; - _numberFirstPartition = 0; - // |rtpTypeHdr->VP8.temporalIdx| is zero for base layers, or kNoTemporalIdx - // if the field isn't used (so all layers are the base layer). We currently - // only protect base layers, so look for these two cases. - bool protect = rtpTypeHdr->VP8.temporalIdx == 0 || - rtpTypeHdr->VP8.temporalIdx == kNoTemporalIdx; - while (!last) - { - // Write VP8 Payload Descriptor and VP8 payload. - uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; - size_t payloadBytesInPacket = 0; - if (!packetizer.NextPacket( - &dataBuffer[rtpHeaderLength], &payloadBytesInPacket, &last)) - return -1; - - // Write RTP header. - // Set marker bit true if this is the last packet in frame. - _rtpSender.BuildRTPheader(dataBuffer, payloadType, last, - captureTimeStamp, capture_time_ms); - if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket, - rtpHeaderLength, captureTimeStamp, - capture_time_ms, storage, protect)) - { - LOG(LS_WARNING) - << "RTPSenderVideo::SendVP8 failed to send packet number " - << _rtpSender.SequenceNumber(); - } - } - TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, - "timestamp", _rtpSender.Timestamp()); - return 0; -} - -bool RTPSenderVideo::SendH264(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const uint32_t payloadSize, - const RTPFragmentationHeader* fragmentation, - const RTPVideoTypeHeader* rtpTypeHdr) { - size_t rtp_header_length = _rtpSender.RTPHeaderLength(); int32_t payload_bytes_to_send = payloadSize; const uint8_t* data = payloadData; size_t max_payload_length = _rtpSender.MaxDataPayloadLength(); - scoped_ptr packetizer( - RtpPacketizer::Create(kRtpVideoH264, max_payload_length)); - packetizer->SetPayloadData(data, payload_bytes_to_send, fragmentation); + scoped_ptr packetizer(RtpPacketizer::Create( + videoType, max_payload_length, rtpTypeHdr, frameType)); + + // TODO(changbin): we currently don't support to configure the codec to + // output multiple partitions for VP8. Should remove below check after the + // issue is fixed. + const RTPFragmentationHeader* frag = + (videoType == kRtpVideoVp8) ? NULL : fragmentation; + + packetizer->SetPayloadData(data, payload_bytes_to_send, frag); - StorageType storage = kAllowRetransmission; - bool protect = (frameType == kVideoFrameKey); bool last = false; - while (!last) { - // Write H264 payload. uint8_t dataBuffer[IP_PACKET_SIZE] = {0}; size_t payload_bytes_in_packet = 0; if (!packetizer->NextPacket( @@ -515,13 +357,16 @@ bool RTPSenderVideo::SendH264(const FrameType frameType, rtp_header_length, captureTimeStamp, capture_time_ms, - storage, - protect)) { - LOG(LS_WARNING) - << "RTPSenderVideo::SendH264 failed to send packet number " - << _rtpSender.SequenceNumber(); + packetizer->GetStorageType(_retransmissionSettings), + packetizer->GetProtectionType() == kProtectedPacket)) { + LOG(LS_WARNING) << packetizer->ToString() + << " failed to send packet number " + << _rtpSender.SequenceNumber(); } } + + TRACE_EVENT_ASYNC_END1( + "webrtc", "Video", capture_time_ms, "timestamp", _rtpSender.Timestamp()); return true; } diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h index 77b91c993..250e36b93 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.h @@ -28,122 +28,106 @@ namespace webrtc { class CriticalSectionWrapper; struct RtpPacket; -class RTPSenderVideo -{ -public: - RTPSenderVideo(Clock* clock, - RTPSenderInterface* rtpSender); - virtual ~RTPSenderVideo(); +class RTPSenderVideo { + public: + RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender); + virtual ~RTPSenderVideo(); - virtual RtpVideoCodecTypes VideoCodecType() const; + virtual RtpVideoCodecTypes VideoCodecType() const; - uint16_t FECPacketOverhead() const; + uint16_t FECPacketOverhead() const; - int32_t RegisterVideoPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE], - const int8_t payloadType, - const uint32_t maxBitRate, - RtpUtility::Payload*& payload); + int32_t RegisterVideoPayload(const char payloadName[RTP_PAYLOAD_NAME_SIZE], + const int8_t payloadType, + const uint32_t maxBitRate, + RtpUtility::Payload*& payload); - int32_t SendVideo(const RtpVideoCodecTypes videoType, - const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const uint32_t payloadSize, - const RTPFragmentationHeader* fragmentation, - VideoCodecInformation* codecInfo, - const RTPVideoTypeHeader* rtpTypeHdr); - - int32_t SendRTPIntraRequest(); - - void SetVideoCodecType(RtpVideoCodecTypes type); - - VideoCodecInformation* CodecInformationVideo(); - - void SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate); - - uint32_t MaxConfiguredBitrateVideo() const; - - // FEC - int32_t SetGenericFECStatus(const bool enable, - const uint8_t payloadTypeRED, - const uint8_t payloadTypeFEC); - - int32_t GenericFECStatus(bool& enable, - uint8_t& payloadTypeRED, - uint8_t& payloadTypeFEC) const; - - int32_t SetFecParameters(const FecProtectionParams* delta_params, - const FecProtectionParams* key_params); - - void ProcessBitrate(); - - uint32_t VideoBitrateSent() const; - uint32_t FecOverheadRate() const; - - int SelectiveRetransmissions() const; - int SetSelectiveRetransmissions(uint8_t settings); - -protected: - virtual int32_t SendVideoPacket(uint8_t* dataBuffer, - const uint16_t payloadLength, - const uint16_t rtpHeaderLength, - const uint32_t capture_timestamp, - int64_t capture_time_ms, - StorageType storage, - bool protect); - -private: - int32_t SendGeneric(const FrameType frame_type, - const int8_t payload_type, - const uint32_t capture_timestamp, - int64_t capture_time_ms, - const uint8_t* payload, const uint32_t size); - - int32_t SendVP8(const FrameType frameType, + int32_t SendVideo(const RtpVideoCodecTypes videoType, + const FrameType frameType, const int8_t payloadType, const uint32_t captureTimeStamp, int64_t capture_time_ms, const uint8_t* payloadData, const uint32_t payloadSize, const RTPFragmentationHeader* fragmentation, + VideoCodecInformation* codecInfo, const RTPVideoTypeHeader* rtpTypeHdr); - bool SendH264(const FrameType frameType, - const int8_t payloadType, - const uint32_t captureTimeStamp, - int64_t capture_time_ms, - const uint8_t* payloadData, - const uint32_t payloadSize, - const RTPFragmentationHeader* fragmentation, - const RTPVideoTypeHeader* rtpTypeHdr); + int32_t SendRTPIntraRequest(); -private: - RTPSenderInterface& _rtpSender; + void SetVideoCodecType(RtpVideoCodecTypes type); - CriticalSectionWrapper* _sendVideoCritsect; - RtpVideoCodecTypes _videoType; - VideoCodecInformation* _videoCodecInformation; - uint32_t _maxBitrate; - int32_t _retransmissionSettings; + VideoCodecInformation* CodecInformationVideo(); - // FEC - ForwardErrorCorrection _fec; - bool _fecEnabled; - int8_t _payloadTypeRED; - int8_t _payloadTypeFEC; - unsigned int _numberFirstPartition; - FecProtectionParams delta_fec_params_; - FecProtectionParams key_fec_params_; - ProducerFec producer_fec_; + void SetMaxConfiguredBitrateVideo(const uint32_t maxBitrate); - // Bitrate used for FEC payload, RED headers, RTP headers for FEC packets - // and any padding overhead. - Bitrate _fecOverheadRate; - // Bitrate used for video payload and RTP headers - Bitrate _videoBitrate; + uint32_t MaxConfiguredBitrateVideo() const; + + // FEC + int32_t SetGenericFECStatus(const bool enable, + const uint8_t payloadTypeRED, + const uint8_t payloadTypeFEC); + + int32_t GenericFECStatus(bool& enable, + uint8_t& payloadTypeRED, + uint8_t& payloadTypeFEC) const; + + int32_t SetFecParameters(const FecProtectionParams* delta_params, + const FecProtectionParams* key_params); + + void ProcessBitrate(); + + uint32_t VideoBitrateSent() const; + uint32_t FecOverheadRate() const; + + int SelectiveRetransmissions() const; + int SetSelectiveRetransmissions(uint8_t settings); + + protected: + virtual int32_t SendVideoPacket(uint8_t* dataBuffer, + const uint16_t payloadLength, + const uint16_t rtpHeaderLength, + const uint32_t capture_timestamp, + int64_t capture_time_ms, + StorageType storage, + bool protect); + + private: + bool Send(const RtpVideoCodecTypes videoType, + const FrameType frameType, + const int8_t payloadType, + const uint32_t captureTimeStamp, + int64_t capture_time_ms, + const uint8_t* payloadData, + const uint32_t payloadSize, + const RTPFragmentationHeader* fragmentation, + const RTPVideoTypeHeader* rtpTypeHdr); + + private: + RTPSenderInterface& _rtpSender; + + CriticalSectionWrapper* _sendVideoCritsect; + RtpVideoCodecTypes _videoType; + VideoCodecInformation* _videoCodecInformation; + uint32_t _maxBitrate; + int32_t _retransmissionSettings; + + // FEC + ForwardErrorCorrection _fec; + bool _fecEnabled; + int8_t _payloadTypeRED; + int8_t _payloadTypeFEC; + unsigned int _numberFirstPartition; + FecProtectionParams delta_fec_params_; + FecProtectionParams key_fec_params_; + ProducerFec producer_fec_; + + // Bitrate used for FEC payload, RED headers, RTP headers for FEC packets + // and any padding overhead. + Bitrate _fecOverheadRate; + // Bitrate used for video payload and RTP headers + Bitrate _videoBitrate; }; } // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_