| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 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 |
| 11 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
| 12 | 12 |
| 13 #include <assert.h> // assert | 13 #include <assert.h> // assert |
| 14 #include <string.h> // memcpy | 14 #include <string.h> // memcpy |
| 15 | 15 |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" |
| 19 #include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h" | 19 #include "webrtc/modules/rtp_rtcp/source/vp8_partition_aggregator.h" |
| 20 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 20 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| 21 | 21 |
| 22 namespace webrtc { | 22 namespace webrtc { |
| 23 namespace { | 23 namespace { |
| 24 int ParseVP8PictureID(RTPVideoHeaderVP8* vp8, | 24 int ParseVP8PictureID(RTPVideoHeaderVP8* vp8, |
| 25 const uint8_t** data, | 25 const uint8_t** data, |
| 26 size_t* data_length, | 26 size_t* data_length, |
| 27 size_t* parsed_bytes) { | 27 size_t* parsed_bytes) { |
| 28 assert(vp8 != NULL); | 28 assert(vp8 != nullptr); |
| 29 if (*data_length == 0) | 29 if (*data_length == 0) |
| 30 return -1; | 30 return -1; |
| 31 | 31 |
| 32 vp8->pictureId = (**data & 0x7F); | 32 vp8->pictureId = (**data & 0x7F); |
| 33 if (**data & 0x80) { | 33 if (**data & 0x80) { |
| 34 (*data)++; | 34 (*data)++; |
| 35 (*parsed_bytes)++; | 35 (*parsed_bytes)++; |
| 36 if (--(*data_length) == 0) | 36 if (--(*data_length) == 0) |
| 37 return -1; | 37 return -1; |
| 38 // PictureId is 15 bits | 38 // PictureId is 15 bits |
| 39 vp8->pictureId = (vp8->pictureId << 8) + **data; | 39 vp8->pictureId = (vp8->pictureId << 8) + **data; |
| 40 } | 40 } |
| 41 (*data)++; | 41 (*data)++; |
| 42 (*parsed_bytes)++; | 42 (*parsed_bytes)++; |
| 43 (*data_length)--; | 43 (*data_length)--; |
| 44 return 0; | 44 return 0; |
| 45 } | 45 } |
| 46 | 46 |
| 47 int ParseVP8Tl0PicIdx(RTPVideoHeaderVP8* vp8, | 47 int ParseVP8Tl0PicIdx(RTPVideoHeaderVP8* vp8, |
| 48 const uint8_t** data, | 48 const uint8_t** data, |
| 49 size_t* data_length, | 49 size_t* data_length, |
| 50 size_t* parsed_bytes) { | 50 size_t* parsed_bytes) { |
| 51 assert(vp8 != NULL); | 51 assert(vp8 != nullptr); |
| 52 if (*data_length == 0) | 52 if (*data_length == 0) |
| 53 return -1; | 53 return -1; |
| 54 | 54 |
| 55 vp8->tl0PicIdx = **data; | 55 vp8->tl0PicIdx = **data; |
| 56 (*data)++; | 56 (*data)++; |
| 57 (*parsed_bytes)++; | 57 (*parsed_bytes)++; |
| 58 (*data_length)--; | 58 (*data_length)--; |
| 59 return 0; | 59 return 0; |
| 60 } | 60 } |
| 61 | 61 |
| 62 int ParseVP8TIDAndKeyIdx(RTPVideoHeaderVP8* vp8, | 62 int ParseVP8TIDAndKeyIdx(RTPVideoHeaderVP8* vp8, |
| 63 const uint8_t** data, | 63 const uint8_t** data, |
| 64 size_t* data_length, | 64 size_t* data_length, |
| 65 size_t* parsed_bytes, | 65 size_t* parsed_bytes, |
| 66 bool has_tid, | 66 bool has_tid, |
| 67 bool has_key_idx) { | 67 bool has_key_idx) { |
| 68 assert(vp8 != NULL); | 68 assert(vp8 != nullptr); |
| 69 if (*data_length == 0) | 69 if (*data_length == 0) |
| 70 return -1; | 70 return -1; |
| 71 | 71 |
| 72 if (has_tid) { | 72 if (has_tid) { |
| 73 vp8->temporalIdx = ((**data >> 6) & 0x03); | 73 vp8->temporalIdx = ((**data >> 6) & 0x03); |
| 74 vp8->layerSync = (**data & 0x20) ? true : false; // Y bit | 74 vp8->layerSync = (**data & 0x20) ? true : false; // Y bit |
| 75 } | 75 } |
| 76 if (has_key_idx) { | 76 if (has_key_idx) { |
| 77 vp8->keyIdx = (**data & 0x1F); | 77 vp8->keyIdx = (**data & 0x1F); |
| 78 } | 78 } |
| 79 (*data)++; | 79 (*data)++; |
| 80 (*parsed_bytes)++; | 80 (*parsed_bytes)++; |
| 81 (*data_length)--; | 81 (*data_length)--; |
| 82 return 0; | 82 return 0; |
| 83 } | 83 } |
| 84 | 84 |
| 85 int ParseVP8Extension(RTPVideoHeaderVP8* vp8, | 85 int ParseVP8Extension(RTPVideoHeaderVP8* vp8, |
| 86 const uint8_t* data, | 86 const uint8_t* data, |
| 87 size_t data_length) { | 87 size_t data_length) { |
| 88 assert(vp8 != NULL); | 88 assert(vp8 != nullptr); |
| 89 assert(data_length > 0); | 89 assert(data_length > 0); |
| 90 size_t parsed_bytes = 0; | 90 size_t parsed_bytes = 0; |
| 91 // Optional X field is present. | 91 // Optional X field is present. |
| 92 bool has_picture_id = (*data & 0x80) ? true : false; // I bit | 92 bool has_picture_id = (*data & 0x80) ? true : false; // I bit |
| 93 bool has_tl0_pic_idx = (*data & 0x40) ? true : false; // L bit | 93 bool has_tl0_pic_idx = (*data & 0x40) ? true : false; // L bit |
| 94 bool has_tid = (*data & 0x20) ? true : false; // T bit | 94 bool has_tid = (*data & 0x20) ? true : false; // T bit |
| 95 bool has_key_idx = (*data & 0x10) ? true : false; // K bit | 95 bool has_key_idx = (*data & 0x10) ? true : false; // K bit |
| 96 | 96 |
| 97 // Advance data and decrease remaining payload size. | 97 // Advance data and decrease remaining payload size. |
| 98 data++; | 98 data++; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 117 0) { | 117 0) { |
| 118 return -1; | 118 return -1; |
| 119 } | 119 } |
| 120 } | 120 } |
| 121 return static_cast<int>(parsed_bytes); | 121 return static_cast<int>(parsed_bytes); |
| 122 } | 122 } |
| 123 | 123 |
| 124 int ParseVP8FrameSize(RtpDepacketizer::ParsedPayload* parsed_payload, | 124 int ParseVP8FrameSize(RtpDepacketizer::ParsedPayload* parsed_payload, |
| 125 const uint8_t* data, | 125 const uint8_t* data, |
| 126 size_t data_length) { | 126 size_t data_length) { |
| 127 assert(parsed_payload != NULL); | 127 assert(parsed_payload != nullptr); |
| 128 if (parsed_payload->frame_type != kVideoFrameKey) { | 128 if (parsed_payload->frame_type != kVideoFrameKey) { |
| 129 // Included in payload header for I-frames. | 129 // Included in payload header for I-frames. |
| 130 return 0; | 130 return 0; |
| 131 } | 131 } |
| 132 if (data_length < 10) { | 132 if (data_length < 10) { |
| 133 // For an I-frame we should always have the uncompressed VP8 header | 133 // For an I-frame we should always have the uncompressed VP8 header |
| 134 // in the beginning of the partition. | 134 // in the beginning of the partition. |
| 135 return -1; | 135 return -1; |
| 136 } | 136 } |
| 137 parsed_payload->type.Video.width = ((data[7] << 8) + data[6]) & 0x3FFF; | 137 parsed_payload->type.Video.width = ((data[7] << 8) + data[6]) & 0x3FFF; |
| 138 parsed_payload->type.Video.height = ((data[9] << 8) + data[8]) & 0x3FFF; | 138 parsed_payload->type.Video.height = ((data[9] << 8) + data[8]) & 0x3FFF; |
| 139 return 0; | 139 return 0; |
| 140 } | 140 } |
| 141 } // namespace | 141 } // namespace |
| 142 | 142 |
| 143 // Define how the VP8PacketizerModes are implemented. | 143 // Define how the VP8PacketizerModes are implemented. |
| 144 // Modes are: kStrict, kAggregate, kEqualSize. | 144 // Modes are: kStrict, kAggregate, kEqualSize. |
| 145 const RtpPacketizerVp8::AggregationMode RtpPacketizerVp8::aggr_modes_ | 145 const RtpPacketizerVp8::AggregationMode RtpPacketizerVp8::aggr_modes_ |
| 146 [kNumModes] = {kAggrNone, kAggrPartitions, kAggrFragments}; | 146 [kNumModes] = {kAggrNone, kAggrPartitions, kAggrFragments}; |
| 147 const bool RtpPacketizerVp8::balance_modes_[kNumModes] = {true, true, true}; | 147 const bool RtpPacketizerVp8::balance_modes_[kNumModes] = {true, true, true}; |
| 148 const bool RtpPacketizerVp8::separate_first_modes_[kNumModes] = {true, false, | 148 const bool RtpPacketizerVp8::separate_first_modes_[kNumModes] = {true, false, |
| 149 false}; | 149 false}; |
| 150 | 150 |
| 151 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, | 151 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, |
| 152 size_t max_payload_len, | 152 size_t max_payload_len, |
| 153 VP8PacketizerMode mode) | 153 VP8PacketizerMode mode) |
| 154 : payload_data_(NULL), | 154 : payload_data_(nullptr), |
| 155 payload_size_(0), | 155 payload_size_(0), |
| 156 vp8_fixed_payload_descriptor_bytes_(1), | 156 vp8_fixed_payload_descriptor_bytes_(1), |
| 157 aggr_mode_(aggr_modes_[mode]), | 157 aggr_mode_(aggr_modes_[mode]), |
| 158 balance_(balance_modes_[mode]), | 158 balance_(balance_modes_[mode]), |
| 159 separate_first_(separate_first_modes_[mode]), | 159 separate_first_(separate_first_modes_[mode]), |
| 160 hdr_info_(hdr_info), | 160 hdr_info_(hdr_info), |
| 161 num_partitions_(0), | 161 num_partitions_(0), |
| 162 max_payload_len_(max_payload_len), | 162 max_payload_len_(max_payload_len), |
| 163 packets_calculated_(false) { | 163 packets_calculated_(false) {} |
| 164 } | |
| 165 | 164 |
| 166 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, | 165 RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info, |
| 167 size_t max_payload_len) | 166 size_t max_payload_len) |
| 168 : payload_data_(NULL), | 167 : payload_data_(nullptr), |
| 169 payload_size_(0), | 168 payload_size_(0), |
| 170 part_info_(), | 169 part_info_(), |
| 171 vp8_fixed_payload_descriptor_bytes_(1), | 170 vp8_fixed_payload_descriptor_bytes_(1), |
| 172 aggr_mode_(aggr_modes_[kEqualSize]), | 171 aggr_mode_(aggr_modes_[kEqualSize]), |
| 173 balance_(balance_modes_[kEqualSize]), | 172 balance_(balance_modes_[kEqualSize]), |
| 174 separate_first_(separate_first_modes_[kEqualSize]), | 173 separate_first_(separate_first_modes_[kEqualSize]), |
| 175 hdr_info_(hdr_info), | 174 hdr_info_(hdr_info), |
| 176 num_partitions_(0), | 175 num_partitions_(0), |
| 177 max_payload_len_(max_payload_len), | 176 max_payload_len_(max_payload_len), |
| 178 packets_calculated_(false) { | 177 packets_calculated_(false) {} |
| 179 } | |
| 180 | 178 |
| 181 RtpPacketizerVp8::~RtpPacketizerVp8() { | 179 RtpPacketizerVp8::~RtpPacketizerVp8() { |
| 182 } | 180 } |
| 183 | 181 |
| 184 void RtpPacketizerVp8::SetPayloadData( | 182 void RtpPacketizerVp8::SetPayloadData( |
| 185 const uint8_t* payload_data, | 183 const uint8_t* payload_data, |
| 186 size_t payload_size, | 184 size_t payload_size, |
| 187 const RTPFragmentationHeader* fragmentation) { | 185 const RTPFragmentationHeader* fragmentation) { |
| 188 payload_data_ = payload_data; | 186 payload_data_ = payload_data; |
| 189 payload_size_ = payload_size; | 187 payload_size_ = payload_size; |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 // Payload header (considered part of the actual payload, sent to decoder) | 660 // Payload header (considered part of the actual payload, sent to decoder) |
| 663 // 0 1 2 3 4 5 6 7 | 661 // 0 1 2 3 4 5 6 7 |
| 664 // +-+-+-+-+-+-+-+-+ | 662 // +-+-+-+-+-+-+-+-+ |
| 665 // |Size0|H| VER |P| | 663 // |Size0|H| VER |P| |
| 666 // +-+-+-+-+-+-+-+-+ | 664 // +-+-+-+-+-+-+-+-+ |
| 667 // | ... | | 665 // | ... | |
| 668 // + + | 666 // + + |
| 669 bool RtpDepacketizerVp8::Parse(ParsedPayload* parsed_payload, | 667 bool RtpDepacketizerVp8::Parse(ParsedPayload* parsed_payload, |
| 670 const uint8_t* payload_data, | 668 const uint8_t* payload_data, |
| 671 size_t payload_data_length) { | 669 size_t payload_data_length) { |
| 672 assert(parsed_payload != NULL); | 670 assert(parsed_payload != nullptr); |
| 673 if (payload_data_length == 0) { | 671 if (payload_data_length == 0) { |
| 674 LOG(LS_ERROR) << "Empty payload."; | 672 LOG(LS_ERROR) << "Empty payload."; |
| 675 return false; | 673 return false; |
| 676 } | 674 } |
| 677 | 675 |
| 678 // Parse mandatory first byte of payload descriptor. | 676 // Parse mandatory first byte of payload descriptor. |
| 679 bool extension = (*payload_data & 0x80) ? true : false; // X bit | 677 bool extension = (*payload_data & 0x80) ? true : false; // X bit |
| 680 bool beginning_of_partition = (*payload_data & 0x10) ? true : false; // S bit | 678 bool beginning_of_partition = (*payload_data & 0x10) ? true : false; // S bit |
| 681 int partition_id = (*payload_data & 0x0F); // PartID field | 679 int partition_id = (*payload_data & 0x0F); // PartID field |
| 682 | 680 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 if (ParseVP8FrameSize(parsed_payload, payload_data, payload_data_length) != | 734 if (ParseVP8FrameSize(parsed_payload, payload_data, payload_data_length) != |
| 737 0) { | 735 0) { |
| 738 return false; | 736 return false; |
| 739 } | 737 } |
| 740 | 738 |
| 741 parsed_payload->payload = payload_data; | 739 parsed_payload->payload = payload_data; |
| 742 parsed_payload->payload_length = payload_data_length; | 740 parsed_payload->payload_length = payload_data_length; |
| 743 return true; | 741 return true; |
| 744 } | 742 } |
| 745 } // namespace webrtc | 743 } // namespace webrtc |
| OLD | NEW |