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/typedefs.h" 34 35 namespace webrtc { 36 37 enum VP8PacketizerMode { 38 kStrict = 0, // Split partitions if too large; 39 // never aggregate, balance size. 40 kAggregate, // Split partitions if too large; aggregate whole partitions. 41 kEqualSize, // Split entire payload without considering partition limits. 42 // This will produce equal size packets for the whole frame. 43 kNumModes, 44 }; 45 46 // Packetizer for VP8. 47 class RtpFormatVp8 { 48 public: 49 // Initialize with payload from encoder and fragmentation info. 50 // The payload_data must be exactly one encoded VP8 frame. 51 RtpFormatVp8(const uint8_t* payload_data, 52 uint32_t payload_size, 53 const RTPVideoHeaderVP8& hdr_info, 54 int max_payload_len, 55 const RTPFragmentationHeader& fragmentation, 56 VP8PacketizerMode mode); 57 58 // Initialize without fragmentation info. Mode kEqualSize will be used. 59 // The payload_data must be exactly one encoded VP8 frame. 60 RtpFormatVp8(const uint8_t* payload_data, 61 uint32_t payload_size, 62 const RTPVideoHeaderVP8& hdr_info, 63 int max_payload_len); 64 65 ~RtpFormatVp8(); 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 int NextPacket(uint8_t* buffer, 79 int* bytes_to_send, 80 bool* last_packet); 81 82 private: 83 typedef struct { 84 int payload_start_pos; 85 int size; 86 bool first_fragment; 87 int first_partition_ix; 88 } InfoStruct; 89 typedef std::queue<InfoStruct> InfoQueue; 90 enum AggregationMode { 91 kAggrNone = 0, // No aggregation. 92 kAggrPartitions, // Aggregate intact partitions. 93 kAggrFragments // Aggregate intact and fragmented partitions. 94 }; 95 96 static const AggregationMode aggr_modes_[kNumModes]; 97 static const bool balance_modes_[kNumModes]; 98 static const bool separate_first_modes_[kNumModes]; 99 static const int kXBit = 0x80; 100 static const int kNBit = 0x20; 101 static const int kSBit = 0x10; 102 static const int kPartIdField = 0x0F; 103 static const int kKeyIdxField = 0x1F; 104 static const int kIBit = 0x80; 105 static const int kLBit = 0x40; 106 static const int kTBit = 0x20; 107 static const int kKBit = 0x10; 108 static const int kYBit = 0x20; 109 110 // Calculate size of next chunk to send. Returns 0 if none can be sent. 111 int CalcNextSize(int max_payload_len, int remaining_bytes, 112 bool split_payload) const; 113 114 // Calculate all packet sizes and load to packet info queue. 115 int GeneratePackets(); 116 117 // Calculate all packet sizes using Vp8PartitionAggregator and load to packet 118 // info queue. 119 int GeneratePacketsBalancedAggregates(); 120 121 // Helper function to GeneratePacketsBalancedAggregates(). Find all 122 // continuous sets of partitions smaller than the max payload size (not 123 // max_size), and aggregate them into balanced packets. The result is written 124 // to partition_vec, which is of the same length as the number of partitions. 125 // A value of -1 indicates that the partition is too large and must be split. 126 // Aggregates are numbered 0, 1, 2, etc. For each set of small partitions, 127 // the aggregate numbers restart at 0. Output values min_size and max_size 128 // will hold the smallest and largest resulting aggregates (i.e., not counting 129 // those that must be split). 130 void AggregateSmallPartitions(std::vector<int>* partition_vec, 131 int* min_size, 132 int* max_size); 133 134 // Insert packet into packet queue. 135 void QueuePacket(int start_pos, 136 int packet_size, 137 int first_partition_in_packet, 138 bool start_on_new_fragment); 139 140 // Write the payload header and copy the payload to the buffer. 141 // The info in packet_info determines which part of the payload is written 142 // and what to write in the header fields. 143 int WriteHeaderAndPayload(const InfoStruct& packet_info, 144 uint8_t* buffer, 145 int buffer_length) const; 146 147 148 // Write the X field and the appropriate extension fields to buffer. 149 // The function returns the extension length (including X field), or -1 150 // on error. 151 int WriteExtensionFields(uint8_t* buffer, int buffer_length) const; 152 153 // Set the I bit in the x_field, and write PictureID to the appropriate 154 // position in buffer. The function returns 0 on success, -1 otherwise. 155 int WritePictureIDFields(uint8_t* x_field, uint8_t* buffer, 156 int buffer_length, int* extension_length) const; 157 158 // Set the L bit in the x_field, and write Tl0PicIdx to the appropriate 159 // position in buffer. The function returns 0 on success, -1 otherwise. 160 int WriteTl0PicIdxFields(uint8_t* x_field, uint8_t* buffer, 161 int buffer_length, int* extension_length) const; 162 163 // Set the T and K bits in the x_field, and write TID, Y and KeyIdx to the 164 // appropriate position in buffer. The function returns 0 on success, 165 // -1 otherwise. 166 int WriteTIDAndKeyIdxFields(uint8_t* x_field, uint8_t* buffer, 167 int buffer_length, int* extension_length) const; 168 169 // Write the PictureID from codec_specific_info_ to buffer. One or two 170 // bytes are written, depending on magnitude of PictureID. The function 171 // returns the number of bytes written. 172 int WritePictureID(uint8_t* buffer, int buffer_length) const; 173 174 // Calculate and return length (octets) of the variable header fields in 175 // the next header (i.e., header length in addition to vp8_header_bytes_). 176 int PayloadDescriptorExtraLength() const; 177 178 // Calculate and return length (octets) of PictureID field in the next 179 // header. Can be 0, 1, or 2. 180 int PictureIdLength() const; 181 182 // Check whether each of the optional fields will be included in the header. 183 bool XFieldPresent() const; 184 bool TIDFieldPresent() const; 185 bool KeyIdxFieldPresent() const; 186 bool TL0PicIdxFieldPresent() const; 187 bool PictureIdPresent() const { return (PictureIdLength() > 0); } 188 189 const uint8_t* payload_data_; 190 const int payload_size_; 191 RTPFragmentationHeader part_info_; 192 const int vp8_fixed_payload_descriptor_bytes_; // Length of VP8 payload 193 // descriptors's fixed part. 194 const AggregationMode aggr_mode_; 195 const bool balance_; 196 const bool separate_first_; 197 const RTPVideoHeaderVP8 hdr_info_; 198 const int num_partitions_; 199 const int max_payload_len_; 200 InfoQueue packets_; 201 bool packets_calculated_; 202 203 DISALLOW_COPY_AND_ASSIGN(RtpFormatVp8); 204 }; 205 206 } // namespace 207 208 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_VP8_H_ 209