OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
72 | 72 |
73 offsets->push_back(offset + kStapAHeaderSize); | 73 offsets->push_back(offset + kStapAHeaderSize); |
74 offset += kLengthFieldSize + nalu_size; | 74 offset += kLengthFieldSize + nalu_size; |
75 } | 75 } |
76 return true; | 76 return true; |
77 } | 77 } |
78 | 78 |
79 } // namespace | 79 } // namespace |
80 | 80 |
81 RtpPacketizerH264::RtpPacketizerH264(size_t max_payload_len, | 81 RtpPacketizerH264::RtpPacketizerH264(size_t max_payload_len, |
82 size_t last_packet_reduction_len, | |
82 H264PacketizationMode packetization_mode) | 83 H264PacketizationMode packetization_mode) |
83 : max_payload_len_(max_payload_len), | 84 : max_payload_len_(max_payload_len), |
85 last_packet_reduction_len_(last_packet_reduction_len), | |
86 total_packets_(0), | |
84 packetization_mode_(packetization_mode) { | 87 packetization_mode_(packetization_mode) { |
85 // Guard against uninitialized memory in packetization_mode. | 88 // Guard against uninitialized memory in packetization_mode. |
86 RTC_CHECK(packetization_mode == H264PacketizationMode::NonInterleaved || | 89 RTC_CHECK(packetization_mode == H264PacketizationMode::NonInterleaved || |
87 packetization_mode == H264PacketizationMode::SingleNalUnit); | 90 packetization_mode == H264PacketizationMode::SingleNalUnit); |
91 RTC_CHECK(max_payload_len > last_packet_reduction_len); | |
danilchap
2017/05/18 11:14:24
RTC_CHECK_GT
ilnik
2017/05/18 12:22:52
Done.
| |
88 } | 92 } |
89 | 93 |
90 RtpPacketizerH264::~RtpPacketizerH264() { | 94 RtpPacketizerH264::~RtpPacketizerH264() { |
91 } | 95 } |
92 | 96 |
93 RtpPacketizerH264::Fragment::Fragment(const uint8_t* buffer, size_t length) | 97 RtpPacketizerH264::Fragment::Fragment(const uint8_t* buffer, size_t length) |
94 : buffer(buffer), length(length) {} | 98 : buffer(buffer), length(length) {} |
95 RtpPacketizerH264::Fragment::Fragment(const Fragment& fragment) | 99 RtpPacketizerH264::Fragment::Fragment(const Fragment& fragment) |
96 : buffer(fragment.buffer), length(fragment.length) {} | 100 : buffer(fragment.buffer), length(fragment.length) {} |
97 | 101 |
98 void RtpPacketizerH264::SetPayloadData( | 102 size_t RtpPacketizerH264::SetPayloadData( |
99 const uint8_t* payload_data, | 103 const uint8_t* payload_data, |
100 size_t payload_size, | 104 size_t payload_size, |
101 const RTPFragmentationHeader* fragmentation) { | 105 const RTPFragmentationHeader* fragmentation) { |
102 RTC_DCHECK(packets_.empty()); | 106 RTC_DCHECK(packets_.empty()); |
103 RTC_DCHECK(input_fragments_.empty()); | 107 RTC_DCHECK(input_fragments_.empty()); |
104 RTC_DCHECK(fragmentation); | 108 RTC_DCHECK(fragmentation); |
105 for (int i = 0; i < fragmentation->fragmentationVectorSize; ++i) { | 109 for (int i = 0; i < fragmentation->fragmentationVectorSize; ++i) { |
106 const uint8_t* buffer = | 110 const uint8_t* buffer = |
107 &payload_data[fragmentation->fragmentationOffset[i]]; | 111 &payload_data[fragmentation->fragmentationOffset[i]]; |
108 size_t length = fragmentation->fragmentationLength[i]; | 112 size_t length = fragmentation->fragmentationLength[i]; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
157 SpsValidEvent::kSentSpsParseFailure, | 161 SpsValidEvent::kSentSpsParseFailure, |
158 SpsValidEvent::kSpsRewrittenMax); | 162 SpsValidEvent::kSpsRewrittenMax); |
159 break; | 163 break; |
160 } | 164 } |
161 } | 165 } |
162 | 166 |
163 if (!updated_sps) | 167 if (!updated_sps) |
164 input_fragments_.push_back(Fragment(buffer, length)); | 168 input_fragments_.push_back(Fragment(buffer, length)); |
165 } | 169 } |
166 GeneratePackets(); | 170 GeneratePackets(); |
171 return total_packets_; | |
167 } | 172 } |
168 | 173 |
169 void RtpPacketizerH264::GeneratePackets() { | 174 void RtpPacketizerH264::GeneratePackets() { |
170 for (size_t i = 0; i < input_fragments_.size();) { | 175 for (size_t i = 0; i < input_fragments_.size();) { |
171 switch (packetization_mode_) { | 176 switch (packetization_mode_) { |
172 case H264PacketizationMode::SingleNalUnit: | 177 case H264PacketizationMode::SingleNalUnit: |
173 PacketizeSingleNalu(i); | 178 PacketizeSingleNalu(i); |
174 ++i; | 179 ++i; |
175 break; | 180 break; |
176 case H264PacketizationMode::NonInterleaved: | 181 case H264PacketizationMode::NonInterleaved: |
177 if (input_fragments_[i].length > max_payload_len_) { | 182 size_t fragment_len = input_fragments_[i].length; |
183 if (i + 1 == input_fragments_.size()) { | |
184 // Pretend that last fragment is larger instead of making last packet | |
185 // smaller. | |
186 fragment_len += last_packet_reduction_len_; | |
187 } | |
188 if (fragment_len > max_payload_len_) { | |
178 PacketizeFuA(i); | 189 PacketizeFuA(i); |
179 ++i; | 190 ++i; |
180 } else { | 191 } else { |
181 i = PacketizeStapA(i); | 192 i = PacketizeStapA(i); |
182 } | 193 } |
183 break; | 194 break; |
184 } | 195 } |
185 } | 196 } |
186 } | 197 } |
187 | 198 |
188 void RtpPacketizerH264::PacketizeFuA(size_t fragment_index) { | 199 void RtpPacketizerH264::PacketizeFuA(size_t fragment_index) { |
189 // Fragment payload into packets (FU-A). | 200 // Fragment payload into packets (FU-A). |
190 // Strip out the original header and leave room for the FU-A header. | 201 // Strip out the original header and leave room for the FU-A header. |
191 const Fragment& fragment = input_fragments_[fragment_index]; | 202 const Fragment& fragment = input_fragments_[fragment_index]; |
203 bool is_last_fragment = fragment_index + 1 == input_fragments_.size(); | |
204 size_t payload_left = fragment.length - kNalHeaderSize; | |
205 size_t offset = kNalHeaderSize; | |
206 size_t per_packet_capacity = max_payload_len_ - kFuAHeaderSize; | |
192 | 207 |
193 size_t fragment_length = fragment.length - kNalHeaderSize; | 208 // Instead of making the last packet smaller we pretend that all packets are |
194 size_t offset = kNalHeaderSize; | 209 // of the same size but we write additional virtual payload to the last |
195 size_t bytes_available = max_payload_len_ - kFuAHeaderSize; | 210 // packet. |
196 const size_t num_fragments = | 211 size_t extra_len = is_last_fragment ? last_packet_reduction_len_ : 0; |
197 (fragment_length + (bytes_available - 1)) / bytes_available; | |
198 | 212 |
199 const size_t avg_size = (fragment_length + num_fragments - 1) / num_fragments; | 213 // Integer divisions with rounding up. Minimal number of packets to fit all |
200 while (fragment_length > 0) { | 214 // payload and virtual payload. |
201 size_t packet_length = avg_size; | 215 size_t num_packets = (payload_left + extra_len + (per_packet_capacity - 1)) / |
202 if (fragment_length < avg_size) | 216 per_packet_capacity; |
203 packet_length = fragment_length; | 217 // Bytes per packet. Average rounded down. |
218 size_t payload_per_packet = (payload_left + extra_len) / num_packets; | |
219 // We make several first packets to be 1 bytes smaller than the rest. | |
220 // i.e 14 bytes splitted in 4 packets would be 3+3+4+4. | |
221 size_t num_larger_packets = (payload_left + extra_len) % num_packets; | |
222 | |
223 total_packets_ += num_packets; | |
224 while (payload_left > 0) { | |
225 // Increase payload per packet at the right time. | |
226 if (num_packets == num_larger_packets) | |
227 ++payload_per_packet; | |
228 size_t packet_length = payload_per_packet; | |
229 if (payload_left <= packet_length) { // Last portion of the payload | |
230 packet_length = payload_left; | |
231 // One additional packet may be used for extensions in the last packet. | |
232 // Together with last payload packet there may be at most 2 of them. | |
233 RTC_DCHECK_LE(num_packets, 2); | |
234 if (num_packets == 2) { | |
235 // Whole payload fits in the first num_packets-1 packets but extra | |
236 // packet is used for virtual payload. Leave at least one byte of data | |
237 // for the last packet. | |
238 --packet_length; | |
239 } | |
240 } | |
241 RTC_CHECK_GT(packet_length, 0); | |
204 packets_.push(PacketUnit(Fragment(fragment.buffer + offset, packet_length), | 242 packets_.push(PacketUnit(Fragment(fragment.buffer + offset, packet_length), |
205 offset - kNalHeaderSize == 0, | 243 offset - kNalHeaderSize == 0, |
206 fragment_length == packet_length, false, | 244 payload_left == packet_length, false, |
207 fragment.buffer[0])); | 245 fragment.buffer[0])); |
208 offset += packet_length; | 246 offset += packet_length; |
209 fragment_length -= packet_length; | 247 payload_left -= packet_length; |
248 --num_packets; | |
210 } | 249 } |
211 RTC_CHECK_EQ(0, fragment_length); | 250 RTC_CHECK_EQ(0, payload_left); |
212 } | 251 } |
213 | 252 |
214 size_t RtpPacketizerH264::PacketizeStapA(size_t fragment_index) { | 253 size_t RtpPacketizerH264::PacketizeStapA(size_t fragment_index) { |
215 // Aggregate fragments into one packet (STAP-A). | 254 // Aggregate fragments into one packet (STAP-A). |
216 size_t payload_size_left = max_payload_len_; | 255 size_t payload_size_left = max_payload_len_; |
217 int aggregated_fragments = 0; | 256 int aggregated_fragments = 0; |
218 size_t fragment_headers_length = 0; | 257 size_t fragment_headers_length = 0; |
219 const Fragment* fragment = &input_fragments_[fragment_index]; | 258 const Fragment* fragment = &input_fragments_[fragment_index]; |
220 RTC_CHECK_GE(payload_size_left, fragment->length); | 259 RTC_CHECK_GE(payload_size_left, fragment->length); |
221 while (payload_size_left >= fragment->length + fragment_headers_length) { | 260 ++total_packets_; |
261 while (payload_size_left >= fragment->length + fragment_headers_length && | |
262 (fragment_index + 1 < input_fragments_.size() || | |
263 payload_size_left >= fragment->length + fragment_headers_length + | |
264 last_packet_reduction_len_)) { | |
222 RTC_CHECK_GT(fragment->length, 0); | 265 RTC_CHECK_GT(fragment->length, 0); |
223 packets_.push(PacketUnit(*fragment, aggregated_fragments == 0, false, true, | 266 packets_.push(PacketUnit(*fragment, aggregated_fragments == 0, false, true, |
224 fragment->buffer[0])); | 267 fragment->buffer[0])); |
225 payload_size_left -= fragment->length; | 268 payload_size_left -= fragment->length; |
226 payload_size_left -= fragment_headers_length; | 269 payload_size_left -= fragment_headers_length; |
227 | 270 |
228 // Next fragment. | |
229 ++fragment_index; | |
230 if (fragment_index == input_fragments_.size()) | |
231 break; | |
232 fragment = &input_fragments_[fragment_index]; | |
233 | |
234 fragment_headers_length = kLengthFieldSize; | 271 fragment_headers_length = kLengthFieldSize; |
235 // If we are going to try to aggregate more fragments into this packet | 272 // If we are going to try to aggregate more fragments into this packet |
236 // we need to add the STAP-A NALU header and a length field for the first | 273 // we need to add the STAP-A NALU header and a length field for the first |
237 // NALU of this packet. | 274 // NALU of this packet. |
238 if (aggregated_fragments == 0) | 275 if (aggregated_fragments == 0) |
239 fragment_headers_length += kNalHeaderSize + kLengthFieldSize; | 276 fragment_headers_length += kNalHeaderSize + kLengthFieldSize; |
240 ++aggregated_fragments; | 277 ++aggregated_fragments; |
278 | |
279 // Next fragment. | |
280 ++fragment_index; | |
281 if (fragment_index == input_fragments_.size()) | |
282 break; | |
283 fragment = &input_fragments_[fragment_index]; | |
241 } | 284 } |
285 RTC_CHECK_GT(aggregated_fragments, 0); | |
242 packets_.back().last_fragment = true; | 286 packets_.back().last_fragment = true; |
243 return fragment_index; | 287 return fragment_index; |
244 } | 288 } |
245 | 289 |
246 void RtpPacketizerH264::PacketizeSingleNalu(size_t fragment_index) { | 290 void RtpPacketizerH264::PacketizeSingleNalu(size_t fragment_index) { |
247 // Add a single NALU to the queue, no aggregation. | 291 // Add a single NALU to the queue, no aggregation. |
248 size_t payload_size_left = max_payload_len_; | 292 size_t payload_size_left = max_payload_len_; |
293 if (fragment_index + 1 == input_fragments_.size()) | |
294 payload_size_left -= last_packet_reduction_len_; | |
249 const Fragment* fragment = &input_fragments_[fragment_index]; | 295 const Fragment* fragment = &input_fragments_[fragment_index]; |
250 RTC_CHECK_GE(payload_size_left, fragment->length) | 296 RTC_CHECK_GE(payload_size_left, fragment->length) |
251 << "Payload size left " << payload_size_left << ", fragment length " | 297 << "Payload size left " << payload_size_left << ", fragment length " |
252 << fragment->length << ", packetization mode " << packetization_mode_; | 298 << fragment->length << ", packetization mode " << packetization_mode_; |
253 RTC_CHECK_GT(fragment->length, 0u); | 299 RTC_CHECK_GT(fragment->length, 0u); |
254 packets_.push(PacketUnit(*fragment, true /* first */, true /* last */, | 300 packets_.push(PacketUnit(*fragment, true /* first */, true /* last */, |
255 false /* aggregated */, fragment->buffer[0])); | 301 false /* aggregated */, fragment->buffer[0])); |
302 ++total_packets_; | |
256 } | 303 } |
257 | 304 |
258 bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet, | 305 bool RtpPacketizerH264::NextPacket(RtpPacketToSend* rtp_packet) { |
259 bool* last_packet) { | |
260 RTC_DCHECK(rtp_packet); | 306 RTC_DCHECK(rtp_packet); |
261 RTC_DCHECK(last_packet); | |
262 if (packets_.empty()) { | 307 if (packets_.empty()) { |
263 *last_packet = true; | |
264 return false; | 308 return false; |
265 } | 309 } |
266 | 310 |
267 PacketUnit packet = packets_.front(); | 311 PacketUnit packet = packets_.front(); |
268 if (packet.first_fragment && packet.last_fragment) { | 312 if (packet.first_fragment && packet.last_fragment) { |
269 // Single NAL unit packet. | 313 // Single NAL unit packet. |
270 size_t bytes_to_send = packet.source_fragment.length; | 314 size_t bytes_to_send = packet.source_fragment.length; |
271 uint8_t* buffer = rtp_packet->AllocatePayload(bytes_to_send); | 315 uint8_t* buffer = rtp_packet->AllocatePayload(bytes_to_send); |
272 memcpy(buffer, packet.source_fragment.buffer, bytes_to_send); | 316 memcpy(buffer, packet.source_fragment.buffer, bytes_to_send); |
273 packets_.pop(); | 317 packets_.pop(); |
274 input_fragments_.pop_front(); | 318 input_fragments_.pop_front(); |
275 } else if (packet.aggregated) { | 319 } else if (packet.aggregated) { |
276 RTC_CHECK_EQ(H264PacketizationMode::NonInterleaved, packetization_mode_); | 320 RTC_CHECK_EQ(H264PacketizationMode::NonInterleaved, packetization_mode_); |
277 NextAggregatePacket(rtp_packet); | 321 NextAggregatePacket(rtp_packet, total_packets_ == 1); |
278 } else { | 322 } else { |
279 RTC_CHECK_EQ(H264PacketizationMode::NonInterleaved, packetization_mode_); | 323 RTC_CHECK_EQ(H264PacketizationMode::NonInterleaved, packetization_mode_); |
280 NextFragmentPacket(rtp_packet); | 324 NextFragmentPacket(rtp_packet); |
281 } | 325 } |
282 RTC_DCHECK_LE(rtp_packet->payload_size(), max_payload_len_); | 326 RTC_DCHECK_LE(rtp_packet->payload_size(), max_payload_len_); |
283 *last_packet = packets_.empty(); | 327 if (packets_.empty()) { |
284 rtp_packet->SetMarker(*last_packet); | 328 RTC_DCHECK_LE(rtp_packet->payload_size(), |
329 max_payload_len_ - last_packet_reduction_len_); | |
330 } | |
331 rtp_packet->SetMarker(packets_.empty()); | |
332 total_packets_--; | |
285 return true; | 333 return true; |
286 } | 334 } |
287 | 335 |
288 void RtpPacketizerH264::NextAggregatePacket(RtpPacketToSend* rtp_packet) { | 336 void RtpPacketizerH264::NextAggregatePacket(RtpPacketToSend* rtp_packet, |
289 uint8_t* buffer = rtp_packet->AllocatePayload(max_payload_len_); | 337 bool last) { |
338 uint8_t* buffer = rtp_packet->AllocatePayload( | |
339 last ? max_payload_len_ - last_packet_reduction_len_ : max_payload_len_); | |
290 RTC_DCHECK(buffer); | 340 RTC_DCHECK(buffer); |
291 PacketUnit* packet = &packets_.front(); | 341 PacketUnit* packet = &packets_.front(); |
292 RTC_CHECK(packet->first_fragment); | 342 RTC_CHECK(packet->first_fragment); |
293 // STAP-A NALU header. | 343 // STAP-A NALU header. |
294 buffer[0] = (packet->header & (kFBit | kNriMask)) | H264::NaluType::kStapA; | 344 buffer[0] = (packet->header & (kFBit | kNriMask)) | H264::NaluType::kStapA; |
295 size_t index = kNalHeaderSize; | 345 size_t index = kNalHeaderSize; |
296 bool is_last_fragment = packet->last_fragment; | 346 bool is_last_fragment = packet->last_fragment; |
297 while (packet->aggregated) { | 347 while (packet->aggregated) { |
298 const Fragment& fragment = packet->source_fragment; | 348 const Fragment& fragment = packet->source_fragment; |
299 // Add NAL unit length field. | 349 // Add NAL unit length field. |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
619 h264->packetization_type = kH264FuA; | 669 h264->packetization_type = kH264FuA; |
620 h264->nalu_type = original_nal_type; | 670 h264->nalu_type = original_nal_type; |
621 if (first_fragment) { | 671 if (first_fragment) { |
622 h264->nalus[h264->nalus_length] = nalu; | 672 h264->nalus[h264->nalus_length] = nalu; |
623 h264->nalus_length = 1; | 673 h264->nalus_length = 1; |
624 } | 674 } |
625 return true; | 675 return true; |
626 } | 676 } |
627 | 677 |
628 } // namespace webrtc | 678 } // namespace webrtc |
OLD | NEW |