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 |