1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* 12 * This file contains the declaration of the VP8 packetizer class. 13 * A packetizer object is created for each encoded video frame. The 14 * constructor is called with the payload data and size, 15 * together with the fragmentation information and a packetizer mode 16 * of choice. Alternatively, if no fragmentation info is available, the 17 * second constructor can be used with only payload data and size; in that 18 * case the mode kEqualSize is used. 19 * 20 * After creating the packetizer, the method NextPacket is called 21 * repeatedly to get all packets for the frame. The method returns 22 * false as long as there are more packets left to fetch. 23 */ 24 25 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ 26 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ 27 28 #include <queue> 29 #include <vector> 30 31 #include "webrtc/base/constructormagic.h" 32 #include "webrtc/modules/interface/module_common_types.h" 33 #include "webrtc/modules/rtp_rtcp/source/rtp_format.h" 34 #include "webrtc/typedefs.h" 35 36 namespace webrtc { 37 38 enum VP8PacketizerMode { 39 kStrict = 0, // Split partitions if too large; 40 // never aggregate, balance size. 41 kAggregate, // Split partitions if too large; aggregate whole partitions. 42 kEqualSize, // Split entire payload without considering partition limits. 43 // This will produce equal size packets for the whole frame. 44 kNumModes, 45 }; 46 47 // Packetizer for VP8. 48 class RtpPacketizerVp8 : public RtpPacketizer { 49 public: 50 // Initialize with payload from encoder and fragmentation info. 51 // The payload_data must be exactly one encoded VP8 frame. 52 RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, 53 int max_payload_len, 54 VP8PacketizerMode mode); 55 56 // Initialize without fragmentation info. Mode kEqualSize will be used. 57 // The payload_data must be exactly one encoded VP8 frame. 58 RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, int max_payload_len); 59 60 virtual ~RtpPacketizerVp8(); 61 62 virtual void SetPayloadData( 63 const uint8_t* payload_data, 64 size_t payload_size, 65 const RTPFragmentationHeader* fragmentation) OVERRIDE; 66 67 // Get the next payload with VP8 payload header. 68 // max_payload_len limits the sum length of payload and VP8 payload header. 69 // buffer is a pointer to where the output will be written. 70 // bytes_to_send is an output variable that will contain number of bytes 71 // written to buffer. Parameter last_packet is true for the last packet of 72 // the frame, false otherwise (i.e., call the function again to get the 73 // next packet). 74 // For the kStrict and kAggregate mode: returns the partition index from which 75 // the first payload byte in the packet is taken, with the first partition 76 // having index 0; returns negative on error. 77 // For the kEqualSize mode: returns 0 on success, return negative on error. 78 virtual bool NextPacket(uint8_t* buffer, 79 size_t* bytes_to_send, 80 bool* last_packet) OVERRIDE; 81 82 virtual ProtectionType GetProtectionType() OVERRIDE; 83 84 virtual StorageType GetStorageType(uint32_t retransmission_settings) OVERRIDE; 85 86 virtual std::string ToString() OVERRIDE; 87 88 private: 89 typedef struct { 90 int payload_start_pos; 91 int size; 92 bool first_fragment; 93 int first_partition_ix; 94 } InfoStruct; 95 typedef std::queue<InfoStruct> InfoQueue; 96 enum AggregationMode { 97 kAggrNone = 0, // No aggregation. 98 kAggrPartitions, // Aggregate intact partitions. 99 kAggrFragments // Aggregate intact and fragmented partitions. 100 }; 101 102 static const AggregationMode aggr_modes_[kNumModes]; 103 static const bool balance_modes_[kNumModes]; 104 static const bool separate_first_modes_[kNumModes]; 105 static const int kXBit = 0x80; 106 static const int kNBit = 0x20; 107 static const int kSBit = 0x10; 108 static const int kPartIdField = 0x0F; 109 static const int kKeyIdxField = 0x1F; 110 static const int kIBit = 0x80; 111 static const int kLBit = 0x40; 112 static const int kTBit = 0x20; 113 static const int kKBit = 0x10; 114 static const int kYBit = 0x20; 115 116 // Calculate size of next chunk to send. Returns 0 if none can be sent. 117 int CalcNextSize(int max_payload_len, 118 int remaining_bytes, 119 bool split_payload) const; 120 121 // Calculate all packet sizes and load to packet info queue. 122 int GeneratePackets(); 123 124 // Calculate all packet sizes using Vp8PartitionAggregator and load to packet 125 // info queue. 126 int GeneratePacketsBalancedAggregates(); 127 128 // Helper function to GeneratePacketsBalancedAggregates(). Find all 129 // continuous sets of partitions smaller than the max payload size (not 130 // max_size), and aggregate them into balanced packets. The result is written 131 // to partition_vec, which is of the same length as the number of partitions. 132 // A value of -1 indicates that the partition is too large and must be split. 133 // Aggregates are numbered 0, 1, 2, etc. For each set of small partitions, 134 // the aggregate numbers restart at 0. Output values min_size and max_size 135 // will hold the smallest and largest resulting aggregates (i.e., not counting 136 // those that must be split). 137 void AggregateSmallPartitions(std::vector<int>* partition_vec, 138 int* min_size, 139 int* max_size); 140 141 // Insert packet into packet queue. 142 void QueuePacket(int start_pos, 143 int packet_size, 144 int first_partition_in_packet, 145 bool start_on_new_fragment); 146 147 // Write the payload header and copy the payload to the buffer. 148 // The info in packet_info determines which part of the payload is written 149 // and what to write in the header fields. 150 int WriteHeaderAndPayload(const InfoStruct& packet_info, 151 uint8_t* buffer, 152 int buffer_length) const; 153 154 // Write the X field and the appropriate extension fields to buffer. 155 // The function returns the extension length (including X field), or -1 156 // on error. 157 int WriteExtensionFields(uint8_t* buffer, int buffer_length) const; 158 159 // Set the I bit in the x_field, and write PictureID to the appropriate 160 // position in buffer. The function returns 0 on success, -1 otherwise. 161 int WritePictureIDFields(uint8_t* x_field, 162 uint8_t* buffer, 163 int buffer_length, 164 int* extension_length) const; 165 166 // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate 167 // position in buffer. The function returns 0 on success, -1 otherwise. 168 int WriteTl0PicIdxFields(uint8_t* x_field, 169 uint8_t* buffer, 170 int buffer_length, 171 int* extension_length) const; 172 173 // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the 174 // appropriate position in buffer. The function returns 0 on success, 175 // -1 otherwise. 176 int WriteTIDAndKeyIdxFields(uint8_t* x_field, 177 uint8_t* buffer, 178 int buffer_length, 179 int* extension_length) const; 180 181 // Write the PictureID from codec_specific_info_ to buffer. One or two 182 // bytes are written, depending on magnitude of PictureID. The function 183 // returns the number of bytes written. 184 int WritePictureID(uint8_t* buffer, int buffer_length) const; 185 186 // Calculate and return length (octets) of the variable header fields in 187 // the next header (i.e., header length in addition to vp8_header_bytes_). 188 int PayloadDescriptorExtraLength() const; 189 190 // Calculate and return length (octets) of PictureID field in the next 191 // header. Can be 0, 1, or 2. 192 int PictureIdLength() const; 193 194 // Check whether each of the optional fields will be included in the header. 195 bool XFieldPresent() const; 196 bool TIDFieldPresent() const; 197 bool KeyIdxFieldPresent() const; 198 bool TL0PicIdxFieldPresent() const; 199 bool PictureIdPresent() const { return (PictureIdLength() > 0); } 200 201 const uint8_t* payload_data_; 202 int payload_size_; 203 RTPFragmentationHeader part_info_; 204 const int vp8_fixed_payload_descriptor_bytes_; // Length of VP8 payload 205 // descriptors's fixed part. 206 const AggregationMode aggr_mode_; 207 const bool balance_; 208 const bool separate_first_; 209 const RTPVideoHeaderVP8 hdr_info_; 210 int num_partitions_; 211 const int max_payload_len_; 212 InfoQueue packets_; 213 bool packets_calculated_; 214 215 DISALLOW_COPY_AND_ASSIGN(RtpPacketizerVp8); 216 }; 217 218 // Depacketizer for VP8. 219 class RtpDepacketizerVp8 : public RtpDepacketizer { 220 public: 221 explicit RtpDepacketizerVp8(RtpData* const callback); 222 223 virtual ~RtpDepacketizerVp8() {} 224 225 virtual bool Parse(WebRtcRTPHeader* rtp_header, 226 const uint8_t* payload_data, 227 size_t payload_data_length) OVERRIDE; 228 229 private: 230 RtpData* const callback_; 231 232 DISALLOW_COPY_AND_ASSIGN(RtpDepacketizerVp8); 233 }; 234 } // namespace webrtc 235 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ 236