Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_format_vp8.cc
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 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h"
12
13 #include <assert.h>   // assert
14 #include <string.h>  // memcpy
15
16 #include <vector>
17
18 #include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h"
19
20 namespace webrtc {
21
22 // Define how the VP8PacketizerModes are implemented.
23 // Modes are: kStrict, kAggregate, kEqualSize.
24 const RtpPacketizerVp8::AggregationMode RtpPacketizerVp8::aggr_modes_
25     [kNumModes] = {kAggrNone, kAggrPartitions, kAggrFragments};
26 const bool RtpPacketizerVp8::balance_modes_[kNumModes] = {true, true, true};
27 const bool RtpPacketizerVp8::separate_first_modes_[kNumModes] = {true, false,
28                                                                  false};
29
30 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
31                                    int max_payload_len,
32                                    VP8PacketizerMode mode)
33     : payload_data_(NULL),
34       payload_size_(0),
35       vp8_fixed_payload_descriptor_bytes_(1),
36       aggr_mode_(aggr_modes_[mode]),
37       balance_(balance_modes_[mode]),
38       separate_first_(separate_first_modes_[mode]),
39       hdr_info_(hdr_info),
40       num_partitions_(0),
41       max_payload_len_(max_payload_len),
42       packets_calculated_(false) {
43 }
44
45 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
46                                    int max_payload_len)
47     : payload_data_(NULL),
48       payload_size_(0),
49       part_info_(),
50       vp8_fixed_payload_descriptor_bytes_(1),
51       aggr_mode_(aggr_modes_[kEqualSize]),
52       balance_(balance_modes_[kEqualSize]),
53       separate_first_(separate_first_modes_[kEqualSize]),
54       hdr_info_(hdr_info),
55       num_partitions_(0),
56       max_payload_len_(max_payload_len),
57       packets_calculated_(false) {
58 }
59
60 RtpPacketizerVp8::~RtpPacketizerVp8() {
61 }
62
63 void RtpPacketizerVp8::SetPayloadData(
64     const uint8_t* payload_data,
65     size_t payload_size,
66     const RTPFragmentationHeader* fragmentation) {
67   payload_data_ = payload_data;
68   payload_size_ = payload_size;
69   if (fragmentation) {
70     part_info_.CopyFrom(*fragmentation);
71     num_partitions_ = fragmentation->fragmentationVectorSize;
72   } else {
73     part_info_.VerifyAndAllocateFragmentationHeader(1);
74     part_info_.fragmentationLength[0] = payload_size;
75     part_info_.fragmentationOffset[0] = 0;
76     num_partitions_ = part_info_.fragmentationVectorSize;
77   }
78 }
79
80 bool RtpPacketizerVp8::NextPacket(uint8_t* buffer,
81                                   size_t* bytes_to_send,
82                                   bool* last_packet) {
83   if (!packets_calculated_) {
84     int ret = 0;
85     if (aggr_mode_ == kAggrPartitions && balance_) {
86       ret = GeneratePacketsBalancedAggregates();
87     } else {
88       ret = GeneratePackets();
89     }
90     if (ret < 0) {
91       return false;
92     }
93   }
94   if (packets_.empty()) {
95     return false;
96   }
97   InfoStruct packet_info = packets_.front();
98   packets_.pop();
99
100   int bytes = WriteHeaderAndPayload(packet_info, buffer, max_payload_len_);
101   if (bytes < 0) {
102     return false;
103   }
104   *bytes_to_send = bytes;
105
106   *last_packet = packets_.empty();
107   return true;
108 }
109
110 int RtpPacketizerVp8::CalcNextSize(int max_payload_len,
111                                    int remaining_bytes,
112                                    bool split_payload) const {
113   if (max_payload_len == 0 || remaining_bytes == 0) {
114     return 0;
115   }
116   if (!split_payload) {
117     return max_payload_len >= remaining_bytes ? remaining_bytes : 0;
118   }
119
120   if (balance_) {
121     // Balance payload sizes to produce (almost) equal size
122     // fragments.
123     // Number of fragments for remaining_bytes:
124     int num_frags = remaining_bytes / max_payload_len + 1;
125     // Number of bytes in this fragment:
126     return static_cast<int>(static_cast<double>(remaining_bytes)
127                             / num_frags + 0.5);
128   } else {
129     return max_payload_len >= remaining_bytes ? remaining_bytes
130         : max_payload_len;
131   }
132 }
133
134 int RtpPacketizerVp8::GeneratePackets() {
135   if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_
136       + PayloadDescriptorExtraLength() + 1) {
137     // The provided payload length is not long enough for the payload
138     // descriptor and one payload byte. Return an error.
139     return -1;
140   }
141   int total_bytes_processed = 0;
142   bool start_on_new_fragment = true;
143   bool beginning = true;
144   int part_ix = 0;
145   while (total_bytes_processed < payload_size_) {
146     int packet_bytes = 0;  // How much data to send in this packet.
147     bool split_payload = true;  // Splitting of partitions is initially allowed.
148     int remaining_in_partition = part_info_.fragmentationOffset[part_ix] -
149         total_bytes_processed + part_info_.fragmentationLength[part_ix];
150     int rem_payload_len = max_payload_len_ -
151         (vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength());
152     int first_partition_in_packet = part_ix;
153
154     while (int next_size = CalcNextSize(rem_payload_len, remaining_in_partition,
155                                         split_payload)) {
156       packet_bytes += next_size;
157       rem_payload_len -= next_size;
158       remaining_in_partition -= next_size;
159
160       if (remaining_in_partition == 0 && !(beginning && separate_first_)) {
161         // Advance to next partition?
162         // Check that there are more partitions; verify that we are either
163         // allowed to aggregate fragments, or that we are allowed to
164         // aggregate intact partitions and that we started this packet
165         // with an intact partition (indicated by first_fragment_ == true).
166         if (part_ix + 1 < num_partitions_ &&
167             ((aggr_mode_ == kAggrFragments) ||
168                 (aggr_mode_ == kAggrPartitions && start_on_new_fragment))) {
169           assert(part_ix < num_partitions_);
170           remaining_in_partition = part_info_.fragmentationLength[++part_ix];
171           // Disallow splitting unless kAggrFragments. In kAggrPartitions,
172           // we can only aggregate intact partitions.
173           split_payload = (aggr_mode_ == kAggrFragments);
174         }
175       } else if (balance_ && remaining_in_partition > 0) {
176         break;
177       }
178     }
179     if (remaining_in_partition == 0) {
180       ++part_ix;  // Advance to next partition.
181     }
182     assert(packet_bytes > 0);
183
184     QueuePacket(total_bytes_processed, packet_bytes, first_partition_in_packet,
185                 start_on_new_fragment);
186     total_bytes_processed += packet_bytes;
187     start_on_new_fragment = (remaining_in_partition == 0);
188     beginning = false;  // Next packet cannot be first packet in frame.
189   }
190   packets_calculated_ = true;
191   assert(total_bytes_processed == payload_size_);
192   return 0;
193 }
194
195 int RtpPacketizerVp8::GeneratePacketsBalancedAggregates() {
196   if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_
197       + PayloadDescriptorExtraLength() + 1) {
198     // The provided payload length is not long enough for the payload
199     // descriptor and one payload byte. Return an error.
200     return -1;
201   }
202   std::vector<int> partition_decision;
203   const int overhead = vp8_fixed_payload_descriptor_bytes_ +
204       PayloadDescriptorExtraLength();
205   const uint32_t max_payload_len = max_payload_len_ - overhead;
206   int min_size, max_size;
207   AggregateSmallPartitions(&partition_decision, &min_size, &max_size);
208
209   int total_bytes_processed = 0;
210   int part_ix = 0;
211   while (part_ix < num_partitions_) {
212     if (partition_decision[part_ix] == -1) {
213       // Split large partitions.
214       int remaining_partition = part_info_.fragmentationLength[part_ix];
215       int num_fragments = Vp8PartitionAggregator::CalcNumberOfFragments(
216           remaining_partition, max_payload_len, overhead, min_size, max_size);
217       const int packet_bytes =
218           (remaining_partition + num_fragments - 1) / num_fragments;
219       for (int n = 0; n < num_fragments; ++n) {
220         const int this_packet_bytes = packet_bytes < remaining_partition ?
221             packet_bytes : remaining_partition;
222         QueuePacket(total_bytes_processed, this_packet_bytes, part_ix,
223                     (n == 0));
224         remaining_partition -= this_packet_bytes;
225         total_bytes_processed += this_packet_bytes;
226         if (this_packet_bytes < min_size) {
227           min_size = this_packet_bytes;
228         }
229         if (this_packet_bytes > max_size) {
230           max_size = this_packet_bytes;
231         }
232       }
233       assert(remaining_partition == 0);
234       ++part_ix;
235     } else {
236       int this_packet_bytes = 0;
237       const int first_partition_in_packet = part_ix;
238       const int aggregation_index = partition_decision[part_ix];
239       while (static_cast<size_t>(part_ix) < partition_decision.size() &&
240           partition_decision[part_ix] == aggregation_index) {
241         // Collect all partitions that were aggregated into the same packet.
242         this_packet_bytes += part_info_.fragmentationLength[part_ix];
243         ++part_ix;
244       }
245       QueuePacket(total_bytes_processed, this_packet_bytes,
246                   first_partition_in_packet, true);
247       total_bytes_processed += this_packet_bytes;
248     }
249   }
250   packets_calculated_ = true;
251   return 0;
252 }
253
254 void RtpPacketizerVp8::AggregateSmallPartitions(std::vector<int>* partition_vec,
255                                                 int* min_size,
256                                                 int* max_size) {
257   assert(min_size && max_size);
258   *min_size = -1;
259   *max_size = -1;
260   assert(partition_vec);
261   partition_vec->assign(num_partitions_, -1);
262   const int overhead = vp8_fixed_payload_descriptor_bytes_ +
263       PayloadDescriptorExtraLength();
264   const uint32_t max_payload_len = max_payload_len_ - overhead;
265   int first_in_set = 0;
266   int last_in_set = 0;
267   int num_aggregate_packets = 0;
268   // Find sets of partitions smaller than max_payload_len_.
269   while (first_in_set < num_partitions_) {
270     if (part_info_.fragmentationLength[first_in_set] < max_payload_len) {
271       // Found start of a set.
272       last_in_set = first_in_set;
273       while (last_in_set + 1 < num_partitions_ &&
274           part_info_.fragmentationLength[last_in_set + 1] < max_payload_len) {
275         ++last_in_set;
276       }
277       // Found end of a set. Run optimized aggregator. It is ok if start == end.
278       Vp8PartitionAggregator aggregator(part_info_, first_in_set,
279                                         last_in_set);
280       if (*min_size >= 0 && *max_size >= 0) {
281         aggregator.SetPriorMinMax(*min_size, *max_size);
282       }
283       Vp8PartitionAggregator::ConfigVec optimal_config =
284           aggregator.FindOptimalConfiguration(max_payload_len, overhead);
285       aggregator.CalcMinMax(optimal_config, min_size, max_size);
286       for (int i = first_in_set, j = 0; i <= last_in_set; ++i, ++j) {
287         // Transfer configuration for this set of partitions to the joint
288         // partition vector representing all partitions in the frame.
289         (*partition_vec)[i] = num_aggregate_packets + optimal_config[j];
290       }
291       num_aggregate_packets += optimal_config.back() + 1;
292       first_in_set = last_in_set;
293     }
294     ++first_in_set;
295   }
296 }
297
298 void RtpPacketizerVp8::QueuePacket(int start_pos,
299                                    int packet_size,
300                                    int first_partition_in_packet,
301                                    bool start_on_new_fragment) {
302   // Write info to packet info struct and store in packet info queue.
303   InfoStruct packet_info;
304   packet_info.payload_start_pos = start_pos;
305   packet_info.size = packet_size;
306   packet_info.first_partition_ix = first_partition_in_packet;
307   packet_info.first_fragment = start_on_new_fragment;
308   packets_.push(packet_info);
309 }
310
311 int RtpPacketizerVp8::WriteHeaderAndPayload(const InfoStruct& packet_info,
312                                             uint8_t* buffer,
313                                             int buffer_length) const {
314   // Write the VP8 payload descriptor.
315   //       0
316   //       0 1 2 3 4 5 6 7 8
317   //      +-+-+-+-+-+-+-+-+-+
318   //      |X| |N|S| PART_ID |
319   //      +-+-+-+-+-+-+-+-+-+
320   // X:   |I|L|T|K|         | (mandatory if any of the below are used)
321   //      +-+-+-+-+-+-+-+-+-+
322   // I:   |PictureID (8/16b)| (optional)
323   //      +-+-+-+-+-+-+-+-+-+
324   // L:   |   TL0PIC_IDX    | (optional)
325   //      +-+-+-+-+-+-+-+-+-+
326   // T/K: |TID:Y|  KEYIDX   | (optional)
327   //      +-+-+-+-+-+-+-+-+-+
328
329   assert(packet_info.size > 0);
330   buffer[0] = 0;
331   if (XFieldPresent())            buffer[0] |= kXBit;
332   if (hdr_info_.nonReference)     buffer[0] |= kNBit;
333   if (packet_info.first_fragment) buffer[0] |= kSBit;
334   buffer[0] |= (packet_info.first_partition_ix & kPartIdField);
335
336   const int extension_length = WriteExtensionFields(buffer, buffer_length);
337
338   memcpy(&buffer[vp8_fixed_payload_descriptor_bytes_ + extension_length],
339          &payload_data_[packet_info.payload_start_pos], packet_info.size);
340
341   // Return total length of written data.
342   return packet_info.size + vp8_fixed_payload_descriptor_bytes_
343       + extension_length;
344 }
345
346 int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer,
347                                            int buffer_length) const {
348   int extension_length = 0;
349   if (XFieldPresent()) {
350     uint8_t* x_field = buffer + vp8_fixed_payload_descriptor_bytes_;
351     *x_field = 0;
352     extension_length = 1;  // One octet for the X field.
353     if (PictureIdPresent()) {
354       if (WritePictureIDFields(x_field, buffer, buffer_length,
355                                &extension_length) < 0) {
356         return -1;
357       }
358     }
359     if (TL0PicIdxFieldPresent()) {
360       if (WriteTl0PicIdxFields(x_field, buffer, buffer_length,
361                                &extension_length) < 0) {
362         return -1;
363       }
364     }
365     if (TIDFieldPresent() || KeyIdxFieldPresent()) {
366       if (WriteTIDAndKeyIdxFields(x_field, buffer, buffer_length,
367                                   &extension_length) < 0) {
368         return -1;
369       }
370     }
371     assert(extension_length == PayloadDescriptorExtraLength());
372   }
373   return extension_length;
374 }
375
376 int RtpPacketizerVp8::WritePictureIDFields(uint8_t* x_field,
377                                            uint8_t* buffer,
378                                            int buffer_length,
379                                            int* extension_length) const {
380   *x_field |= kIBit;
381   const int pic_id_length = WritePictureID(
382       buffer + vp8_fixed_payload_descriptor_bytes_ + *extension_length,
383       buffer_length - vp8_fixed_payload_descriptor_bytes_
384       - *extension_length);
385   if (pic_id_length < 0) return -1;
386   *extension_length += pic_id_length;
387   return 0;
388 }
389
390 int RtpPacketizerVp8::WritePictureID(uint8_t* buffer, int buffer_length) const {
391   const uint16_t pic_id =
392       static_cast<uint16_t> (hdr_info_.pictureId);
393   int picture_id_len = PictureIdLength();
394   if (picture_id_len > buffer_length) return -1;
395   if (picture_id_len == 2) {
396     buffer[0] = 0x80 | ((pic_id >> 8) & 0x7F);
397     buffer[1] = pic_id & 0xFF;
398   } else if (picture_id_len == 1) {
399     buffer[0] = pic_id & 0x7F;
400   }
401   return picture_id_len;
402 }
403
404 int RtpPacketizerVp8::WriteTl0PicIdxFields(uint8_t* x_field,
405                                            uint8_t* buffer,
406                                            int buffer_length,
407                                            int* extension_length) const {
408   if (buffer_length < vp8_fixed_payload_descriptor_bytes_ + *extension_length
409       + 1) {
410     return -1;
411   }
412   *x_field |= kLBit;
413   buffer[vp8_fixed_payload_descriptor_bytes_
414          + *extension_length] = hdr_info_.tl0PicIdx;
415   ++*extension_length;
416   return 0;
417 }
418
419 int RtpPacketizerVp8::WriteTIDAndKeyIdxFields(uint8_t* x_field,
420                                               uint8_t* buffer,
421                                               int buffer_length,
422                                               int* extension_length) const {
423   if (buffer_length < vp8_fixed_payload_descriptor_bytes_ + *extension_length
424       + 1) {
425     return -1;
426   }
427   uint8_t* data_field =
428       &buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length];
429   *data_field = 0;
430   if (TIDFieldPresent()) {
431     *x_field |= kTBit;
432     assert(hdr_info_.temporalIdx <= 3);
433     *data_field |= hdr_info_.temporalIdx << 6;
434     *data_field |= hdr_info_.layerSync ? kYBit : 0;
435   }
436   if (KeyIdxFieldPresent()) {
437     *x_field |= kKBit;
438     *data_field |= (hdr_info_.keyIdx & kKeyIdxField);
439   }
440   ++*extension_length;
441   return 0;
442 }
443
444 int RtpPacketizerVp8::PayloadDescriptorExtraLength() const {
445   int length_bytes = PictureIdLength();
446   if (TL0PicIdxFieldPresent()) ++length_bytes;
447   if (TIDFieldPresent() || KeyIdxFieldPresent()) ++length_bytes;
448   if (length_bytes > 0) ++length_bytes;  // Include the extension field.
449   return length_bytes;
450 }
451
452 int RtpPacketizerVp8::PictureIdLength() const {
453   if (hdr_info_.pictureId == kNoPictureId) {
454     return 0;
455   }
456   if (hdr_info_.pictureId <= 0x7F) {
457     return 1;
458   }
459   return 2;
460 }
461
462 bool RtpPacketizerVp8::XFieldPresent() const {
463   return (TIDFieldPresent() || TL0PicIdxFieldPresent() || PictureIdPresent()
464       || KeyIdxFieldPresent());
465 }
466
467 bool RtpPacketizerVp8::TIDFieldPresent() const {
468   assert((hdr_info_.layerSync == false) ||
469          (hdr_info_.temporalIdx != kNoTemporalIdx));
470   return (hdr_info_.temporalIdx != kNoTemporalIdx);
471 }
472
473 bool RtpPacketizerVp8::KeyIdxFieldPresent() const {
474   return (hdr_info_.keyIdx != kNoKeyIdx);
475 }
476
477 bool RtpPacketizerVp8::TL0PicIdxFieldPresent() const {
478   return (hdr_info_.tl0PicIdx != kNoTl0PicIdx);
479 }
480 }  // namespace webrtc