OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 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_vp9.h" | |
12 | |
13 #include <assert.h> | |
14 #include <string.h> | |
15 | |
16 #include <cmath> | |
17 | |
18 #include "webrtc/base/bitbuffer.h" | |
19 #include "webrtc/base/checks.h" | |
20 #include "webrtc/system_wrappers/interface/logging.h" | |
21 | |
22 #define RETURN_FALSE_ON_ERROR(x) \ | |
23 if (!(x)) { \ | |
24 return false; \ | |
25 } | |
26 | |
27 namespace webrtc { | |
28 namespace { | |
29 // Length of VP9 payload descriptors' fixed part. | |
30 const size_t kFixedPayloadDescriptorBytes = 1; | |
31 | |
32 // Packet fragmentation mode. If true, packets are split into (almost) equal | |
33 // sizes. Otherwise, as many bytes as possible are fit into one packet. | |
34 const bool kBalancedMode = true; | |
35 | |
36 const uint32_t kReservedBitValue0 = 0; | |
37 | |
38 uint8_t TemporalIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | |
39 return (hdr.temporalIdx == kNoTemporalIdx) ? def : hdr.temporalIdx; | |
40 } | |
41 | |
42 uint8_t SpatialIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | |
43 return (hdr.spatialIdx == kNoSpatialIdx) ? def : hdr.spatialIdx; | |
44 } | |
45 | |
46 int16_t Tl0PicIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | |
47 return (hdr.tl0PicIdx == kNoTl0PicIdx) ? def : hdr.tl0PicIdx; | |
48 } | |
49 | |
50 uint8_t GofIdxField(const RTPVideoHeaderVP9& hdr, uint8_t def) { | |
51 return (hdr.gofIdx == kNoGofIdx) ? def : hdr.gofIdx; | |
52 } | |
53 | |
54 // Picture ID: | |
55 // | |
56 // +-+-+-+-+-+-+-+-+ | |
57 // I: |M| PICTURE ID | M:0 => picture id is 7 bits. | |
58 // +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. | |
59 // M: | EXTENDED PID | | |
60 // +-+-+-+-+-+-+-+-+ | |
61 // | |
62 size_t PictureIdLength(const RTPVideoHeaderVP9& hdr) { | |
63 if (hdr.pictureId == kNoPictureId) | |
64 return 0; | |
65 return (hdr.maxPictureId == kMaxOneBytePictureId) ? 1 : 2; | |
66 } | |
67 | |
68 bool PictureIdPresent(const RTPVideoHeaderVP9& hdr) { | |
69 return PictureIdLength(hdr) > 0; | |
70 } | |
71 | |
72 // Layer indices: | |
73 // | |
74 // Flexible mode (F=1): Non-flexible mode (F=0): | |
75 // | |
76 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ | |
77 // L: | T |U| S |D| |GOF_IDX| S |D| | |
78 // +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ | |
79 // | TL0PICIDX | | |
80 // +-+-+-+-+-+-+-+-+ | |
81 // | |
82 size_t LayerInfoLength(const RTPVideoHeaderVP9& hdr) { | |
83 if (hdr.flexibleMode) | |
stefan-webrtc
2015/07/14 09:40:10
if {} else {}
åsapersson
2015/07/14 10:53:55
Done.
| |
84 return (hdr.temporalIdx == kNoTemporalIdx && | |
85 hdr.spatialIdx == kNoSpatialIdx) ? 0 : 1; | |
86 else | |
87 return (hdr.gofIdx == kNoGofIdx && hdr.spatialIdx == kNoSpatialIdx) ? 0 : 2; | |
88 } | |
89 | |
90 bool LayerInfoPresent(const RTPVideoHeaderVP9& hdr) { | |
91 return LayerInfoLength(hdr) > 0; | |
92 } | |
93 | |
94 // Reference indices: | |
95 // | |
96 // +-+-+-+-+-+-+-+-+ -| P=1,F=1: At least one reference index | |
97 // P,F: | P_DIFF |X|N| . has to be specified. | |
98 // +-+-+-+-+-+-+-+-+ . up to 3 times | |
99 // X: |EXTENDED P_DIFF| . X=1: Extended P_DIFF is used (14 | |
100 // +-+-+-+-+-+-+-+-+ -| bits). Else 6 bits is used. | |
101 // N=1: An additional P_DIFF follows | |
102 // current P_DIFF. | |
103 size_t RefIndicesLength(const RTPVideoHeaderVP9& hdr) { | |
104 if (!hdr.interPicPredicted || !hdr.flexibleMode) | |
105 return 0; | |
106 | |
107 DCHECK_GT(hdr.numRefPics, 0U); | |
108 DCHECK_LE(hdr.numRefPics, kMaxVp9RefPics); | |
109 size_t length = 0; | |
110 for (size_t i = 0; i < hdr.numRefPics; ++i) { | |
111 length += hdr.pidDiff[i] > 0x3F ? 2 : 1; | |
stefan-webrtc
2015/07/14 09:40:10
It is not entirely clear to me where 0x3F comes fr
åsapersson
2015/07/14 10:53:54
Added comment.
stefan-webrtc
2015/07/28 06:58:14
Maybe we should DCHECK that P_DIFF doesn't become
| |
112 } | |
113 return length; | |
114 } | |
115 | |
116 // Scalability structure (SS). | |
117 // | |
118 // +-+-+-+-+-+-+-+-+ | |
119 // V: | N_S |Y| N_G | | |
120 // +-+-+-+-+-+-+-+-+ -| | |
121 // Y: | WIDTH | (OPTIONAL) . | |
122 // + + . | |
123 // | | (OPTIONAL) . | |
124 // +-+-+-+-+-+-+-+-+ . N_S + 1 times | |
125 // | HEIGHT | (OPTIONAL) . | |
126 // + + . | |
127 // | | (OPTIONAL) . | |
128 // +-+-+-+-+-+-+-+-+ -| -| | |
129 // N_G: | T |U| R |-|-| (OPTIONAL) . | |
130 // +-+-+-+-+-+-+-+-+ -| . N_G + 1 times | |
131 // | P_DIFF | (OPTIONAL) . R times . | |
132 // +-+-+-+-+-+-+-+-+ -| -| | |
133 // | |
134 size_t SsDataLength(const RTPVideoHeaderVP9& hdr) { | |
135 if (!hdr.ssDataAvailable) | |
136 return 0; | |
137 | |
138 DCHECK_GT(hdr.numSpatialLayers, 0U); | |
139 DCHECK_LE(hdr.numSpatialLayers, kMaxVp9NumberOfSpatialLayers); | |
140 DCHECK_GT(hdr.gof.numFramesInGof, 0U); | |
141 DCHECK_LE(hdr.gof.numFramesInGof, kMaxVp9FramesInGof); | |
142 size_t length = 1; // V | |
143 if (hdr.spatialLayerResolutionPresent) { | |
144 length += 4 * hdr.numSpatialLayers; // Y | |
145 } | |
146 length += hdr.gof.numFramesInGof; // N_G | |
stefan-webrtc
2015/07/14 09:40:10
I'm not sure I follow this. Is this supposed to re
åsapersson
2015/07/14 10:53:54
Updated comment.
| |
147 for (size_t i = 0; i < hdr.gof.numFramesInGof; ++i) { | |
148 DCHECK_LE(hdr.gof.numRefPics[i], kMaxVp9RefPics); | |
149 length += hdr.gof.numRefPics[i]; | |
150 } | |
151 return length; | |
152 } | |
153 | |
154 size_t PayloadDescriptorLengthMinusSsData(const RTPVideoHeaderVP9& hdr) { | |
155 return kFixedPayloadDescriptorBytes + PictureIdLength(hdr) + | |
156 LayerInfoLength(hdr) + RefIndicesLength(hdr); | |
157 } | |
158 | |
159 size_t PayloadDescriptorLength(const RTPVideoHeaderVP9& hdr) { | |
160 return PayloadDescriptorLengthMinusSsData(hdr) + SsDataLength(hdr); | |
161 } | |
162 | |
163 void QueuePacket(size_t start_pos, | |
164 size_t size, | |
165 bool layer_begin, | |
166 bool layer_end, | |
167 RtpPacketizerVp9::PacketInfoQueue* packets) { | |
168 RtpPacketizerVp9::PacketInfo packet_info; | |
169 packet_info.payload_start_pos = start_pos; | |
170 packet_info.size = size; | |
171 packet_info.layer_begin = layer_begin; | |
172 packet_info.layer_end = layer_end; | |
173 packets->push(packet_info); | |
174 } | |
175 | |
176 // Picture ID: | |
177 // | |
178 // +-+-+-+-+-+-+-+-+ | |
179 // I: |M| PICTURE ID | M:0 => picture id is 7 bits. | |
180 // +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. | |
181 // M: | EXTENDED PID | | |
182 // +-+-+-+-+-+-+-+-+ | |
183 // | |
184 bool WritePictureId(const RTPVideoHeaderVP9& vp9, | |
185 rtc::BitBufferWriter* writer) { | |
186 uint32_t m_bit = (PictureIdLength(vp9) == 2) ? 1 : 0; | |
187 RETURN_FALSE_ON_ERROR(writer->WriteBits(m_bit, 1)); | |
188 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.pictureId, m_bit ? 15 : 7)); | |
189 return true; | |
190 } | |
191 | |
192 // Layer indices: | |
193 // | |
194 // Flexible mode (F=1): | |
195 // | |
196 // +-+-+-+-+-+-+-+-+ | |
197 // L: | T |U| S |D| | |
198 // +-+-+-+-+-+-+-+-+ | |
199 // | |
200 bool WriteLayerInfoFlexibleMode(const RTPVideoHeaderVP9& vp9, | |
201 rtc::BitBufferWriter* writer) { | |
202 RETURN_FALSE_ON_ERROR(writer->WriteBits(TemporalIdxField(vp9, 0), 3)); | |
203 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.temporalUpSwitch ? 1 : 0, 1)); | |
204 RETURN_FALSE_ON_ERROR(writer->WriteBits(SpatialIdxField(vp9, 0), 3)); | |
205 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.interLayerPredicted ? 1 : 0, 1)); | |
206 return true; | |
207 } | |
208 | |
209 // Non-flexible mode (F=0): | |
210 // | |
211 // +-+-+-+-+-+-+-+-+ | |
212 // L: |GOF_IDX| S |D| | |
213 // +-+-+-+-+-+-+-+-+ | |
214 // | TL0PICIDX | | |
215 // +-+-+-+-+-+-+-+-+ | |
216 // | |
217 bool WriteLayerInfoNonFlexibleMode(const RTPVideoHeaderVP9& vp9, | |
218 rtc::BitBufferWriter* writer) { | |
219 RETURN_FALSE_ON_ERROR(writer->WriteBits(GofIdxField(vp9, 0), 4)); | |
220 RETURN_FALSE_ON_ERROR(writer->WriteBits(SpatialIdxField(vp9, 0), 3)); | |
221 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.interLayerPredicted ? 1 : 0, 1)); | |
222 RETURN_FALSE_ON_ERROR(writer->WriteUInt8(Tl0PicIdxField(vp9, 0))); | |
223 return true; | |
224 } | |
225 | |
226 bool WriteLayerInfo(const RTPVideoHeaderVP9& vp9, | |
227 rtc::BitBufferWriter* writer) { | |
228 if (vp9.flexibleMode) { | |
229 return WriteLayerInfoFlexibleMode(vp9, writer); | |
230 } else { | |
231 return WriteLayerInfoNonFlexibleMode(vp9, writer); | |
232 } | |
233 } | |
234 | |
235 // Reference indices: | |
236 // | |
237 // +-+-+-+-+-+-+-+-+ -| P=1,F=1: At least one reference index | |
238 // P,F: | P_DIFF |X|N| . has to be specified. | |
239 // +-+-+-+-+-+-+-+-+ . up to 3 times | |
240 // X: |EXTENDED P_DIFF| . X=1: Extended P_DIFF is used (14 | |
241 // +-+-+-+-+-+-+-+-+ -| bits). Else 6 bits is used. | |
242 // N=1: An additional P_DIFF follows | |
243 // current P_DIFF. | |
244 bool WriteRefIndices(const RTPVideoHeaderVP9& vp9, | |
245 rtc::BitBufferWriter* writer) { | |
246 if (!PictureIdPresent(vp9) || | |
247 vp9.numRefPics == 0 || vp9.numRefPics > kMaxVp9RefPics) { | |
248 return false; | |
249 } | |
250 for (size_t i = 0; i < vp9.numRefPics; ++i) { | |
251 uint32_t x_bit = (vp9.pidDiff[i] > 0x3F) ? 1 : 0; | |
252 uint32_t n_bit = (i == vp9.numRefPics - 1) ? 0 : 1; | |
253 if (x_bit) { | |
254 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.pidDiff[i] >> 8, 6)); | |
255 RETURN_FALSE_ON_ERROR(writer->WriteBits(x_bit, 1)); | |
256 RETURN_FALSE_ON_ERROR(writer->WriteBits(n_bit, 1)); | |
257 RETURN_FALSE_ON_ERROR(writer->WriteUInt8(vp9.pidDiff[i])); | |
258 } else { | |
259 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.pidDiff[i], 6)); | |
260 RETURN_FALSE_ON_ERROR(writer->WriteBits(x_bit, 1)); | |
261 RETURN_FALSE_ON_ERROR(writer->WriteBits(n_bit, 1)); | |
262 } | |
263 } | |
264 return true; | |
265 } | |
266 | |
267 // Scalability structure (SS). | |
268 // | |
269 // +-+-+-+-+-+-+-+-+ | |
270 // V: | N_S |Y| N_G | | |
271 // +-+-+-+-+-+-+-+-+ -| | |
272 // Y: | WIDTH | (OPTIONAL) . | |
273 // + + . | |
274 // | | (OPTIONAL) . | |
275 // +-+-+-+-+-+-+-+-+ . N_S + 1 times | |
276 // | HEIGHT | (OPTIONAL) . | |
277 // + + . | |
278 // | | (OPTIONAL) . | |
279 // +-+-+-+-+-+-+-+-+ -| -| | |
280 // N_G: | T |U| R |-|-| (OPTIONAL) . | |
281 // +-+-+-+-+-+-+-+-+ -| . N_G + 1 times | |
282 // | P_DIFF | (OPTIONAL) . R times . | |
283 // +-+-+-+-+-+-+-+-+ -| -| | |
284 // | |
285 bool WriteSsData(const RTPVideoHeaderVP9& vp9, rtc::BitBufferWriter* writer) { | |
286 if (vp9.numSpatialLayers == 0 || | |
287 vp9.numSpatialLayers > kMaxVp9NumberOfSpatialLayers || | |
288 vp9.gof.numFramesInGof == 0 || | |
289 vp9.gof.numFramesInGof > kMaxVp9FramesInGof) { | |
290 return false; | |
291 } | |
stefan-webrtc
2015/07/14 09:40:10
I think we should DCHECK on these instead.
åsapersson
2015/07/14 10:53:55
Done.
| |
292 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.numSpatialLayers - 1, 3)); | |
293 RETURN_FALSE_ON_ERROR( | |
294 writer->WriteBits(vp9.spatialLayerResolutionPresent ? 1 : 0, 1)); | |
295 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.gof.numFramesInGof - 1, 4)); | |
296 | |
297 if (vp9.spatialLayerResolutionPresent) { | |
298 for (size_t i = 0; i < vp9.numSpatialLayers; ++i) { | |
299 RETURN_FALSE_ON_ERROR(writer->WriteUInt16(vp9.width[i])); | |
300 RETURN_FALSE_ON_ERROR(writer->WriteUInt16(vp9.height[i])); | |
301 } | |
302 } | |
303 for (size_t i = 0; i < vp9.gof.numFramesInGof; ++i) { | |
304 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.gof.temporalIdx[i], 3)); | |
305 RETURN_FALSE_ON_ERROR( | |
306 writer->WriteBits(vp9.gof.temporalUpSwitch[i] ? 1 : 0, 1)); | |
307 RETURN_FALSE_ON_ERROR(writer->WriteBits(vp9.gof.numRefPics[i], 2)); | |
308 RETURN_FALSE_ON_ERROR(writer->WriteBits(kReservedBitValue0, 2)); | |
309 for (size_t r = 0; r < vp9.gof.numRefPics[i]; ++r) { | |
310 RETURN_FALSE_ON_ERROR(writer->WriteUInt8(vp9.gof.pidDiff[i][r])); | |
311 } | |
312 } | |
313 return true; | |
314 } | |
315 | |
316 // Picture ID: | |
317 // | |
318 // +-+-+-+-+-+-+-+-+ | |
319 // I: |M| PICTURE ID | M:0 => picture id is 7 bits. | |
320 // +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. | |
321 // M: | EXTENDED PID | | |
322 // +-+-+-+-+-+-+-+-+ | |
323 // | |
324 bool ParsePictureId(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { | |
325 uint32_t picture_id; | |
326 uint32_t m_bit; | |
327 RETURN_FALSE_ON_ERROR(parser->ReadBits(&m_bit, 1)); | |
328 if (m_bit) { | |
329 RETURN_FALSE_ON_ERROR(parser->ReadBits(&picture_id, 15)); | |
330 vp9->maxPictureId = kMaxTwoBytePictureId; | |
331 } else { | |
332 RETURN_FALSE_ON_ERROR(parser->ReadBits(&picture_id, 7)); | |
333 vp9->maxPictureId = kMaxOneBytePictureId; | |
334 } | |
335 vp9->pictureId = picture_id; | |
336 return true; | |
337 } | |
338 | |
339 // Layer indices (flexible mode): | |
340 // | |
341 // +-+-+-+-+-+-+-+-+ | |
342 // L: | T |U| S |D| | |
343 // +-+-+-+-+-+-+-+-+ | |
344 // | |
345 bool ParseLayerInfoFlexibleMode(rtc::BitBuffer* parser, | |
346 RTPVideoHeaderVP9* vp9) { | |
347 uint32_t t, u_bit, s, d_bit; | |
348 RETURN_FALSE_ON_ERROR(parser->ReadBits(&t, 3)); | |
349 RETURN_FALSE_ON_ERROR(parser->ReadBits(&u_bit, 1)); | |
350 RETURN_FALSE_ON_ERROR(parser->ReadBits(&s, 3)); | |
351 RETURN_FALSE_ON_ERROR(parser->ReadBits(&d_bit, 1)); | |
352 vp9->temporalIdx = t; | |
353 vp9->temporalUpSwitch = u_bit ? true : false; | |
354 vp9->spatialIdx = s; | |
355 vp9->interLayerPredicted = d_bit ? true : false; | |
356 return true; | |
357 } | |
358 | |
359 // Layer indices (non-flexible mode): | |
360 // | |
361 // +-+-+-+-+-+-+-+-+ | |
362 // L: |GOF_IDX| S |D| | |
363 // +-+-+-+-+-+-+-+-+ | |
364 // | TL0PICIDX | | |
365 // +-+-+-+-+-+-+-+-+ | |
366 // | |
367 bool ParseLayerInfoNonFlexibleMode(rtc::BitBuffer* parser, | |
368 RTPVideoHeaderVP9* vp9) { | |
369 uint32_t gof_idx, s, d_bit; | |
370 uint8_t tl0picidx; | |
371 RETURN_FALSE_ON_ERROR(parser->ReadBits(&gof_idx, 4)); | |
372 RETURN_FALSE_ON_ERROR(parser->ReadBits(&s, 3)); | |
373 RETURN_FALSE_ON_ERROR(parser->ReadBits(&d_bit, 1)); | |
374 RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&tl0picidx)); | |
375 vp9->gofIdx = gof_idx; | |
376 vp9->spatialIdx = s; | |
377 vp9->interLayerPredicted = d_bit ? true : false; | |
378 vp9->tl0PicIdx = tl0picidx; | |
379 return true; | |
380 } | |
381 | |
382 bool ParseLayerInfo(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { | |
383 if (vp9->flexibleMode) { | |
384 return ParseLayerInfoFlexibleMode(parser, vp9); | |
385 } else { | |
386 return ParseLayerInfoNonFlexibleMode(parser, vp9); | |
387 } | |
388 } | |
389 | |
390 // Reference indices: | |
391 // | |
392 // +-+-+-+-+-+-+-+-+ -| P=1,F=1: At least one reference index | |
393 // P,F: | P_DIFF |X|N| . has to be specified. | |
394 // +-+-+-+-+-+-+-+-+ . up to 3 times | |
395 // X: |EXTENDED P_DIFF| . X=1: Extended P_DIFF is used (14 | |
396 // +-+-+-+-+-+-+-+-+ -| bits). Else 6 bits is used. | |
397 // N=1: An additional P_DIFF follows | |
398 // current P_DIFF. | |
399 bool ParseRefIndices(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { | |
400 if (vp9->pictureId == kNoPictureId) | |
401 return false; | |
402 | |
403 vp9->numRefPics = 0; | |
404 uint32_t n_bit; | |
405 do { | |
406 if (vp9->numRefPics == kMaxVp9RefPics) | |
407 return false; | |
408 | |
409 uint32_t p_diff, x_bit; | |
410 RETURN_FALSE_ON_ERROR(parser->ReadBits(&p_diff, 6)); | |
411 RETURN_FALSE_ON_ERROR(parser->ReadBits(&x_bit, 1)); | |
412 RETURN_FALSE_ON_ERROR(parser->ReadBits(&n_bit, 1)); | |
413 | |
414 if (x_bit) { | |
415 // P_DIFF is 14 bits. | |
416 uint8_t ext_p_diff; | |
417 RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&ext_p_diff)); | |
418 p_diff = (p_diff << 8) + ext_p_diff; | |
419 } | |
420 | |
421 vp9->pidDiff[vp9->numRefPics] = p_diff; | |
422 uint32_t scaled_pid = vp9->pictureId; | |
423 while (p_diff > scaled_pid) { | |
424 scaled_pid += vp9->maxPictureId + 1; | |
425 } | |
426 vp9->refPictureId[vp9->numRefPics++] = scaled_pid - p_diff; | |
427 } while (n_bit); | |
428 | |
429 return true; | |
430 } | |
431 | |
432 // Scalability structure (SS). | |
433 // | |
434 // +-+-+-+-+-+-+-+-+ | |
435 // V: | N_S |Y| N_G | | |
436 // +-+-+-+-+-+-+-+-+ -| | |
437 // Y: | WIDTH | (OPTIONAL) . | |
438 // + + . | |
439 // | | (OPTIONAL) . | |
440 // +-+-+-+-+-+-+-+-+ . N_S + 1 times | |
441 // | HEIGHT | (OPTIONAL) . | |
442 // + + . | |
443 // | | (OPTIONAL) . | |
444 // +-+-+-+-+-+-+-+-+ -| -| | |
445 // N_G: | T |U| R |-|-| (OPTIONAL) . | |
446 // +-+-+-+-+-+-+-+-+ -| . N_G + 1 times | |
447 // | P_DIFF | (OPTIONAL) . R times . | |
448 // +-+-+-+-+-+-+-+-+ -| -| | |
449 // | |
450 bool ParseSsData(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { | |
451 uint32_t n_s, y_bit, n_g; | |
452 RETURN_FALSE_ON_ERROR(parser->ReadBits(&n_s, 3)); | |
453 RETURN_FALSE_ON_ERROR(parser->ReadBits(&y_bit, 1)); | |
454 RETURN_FALSE_ON_ERROR(parser->ReadBits(&n_g, 4)); | |
455 vp9->numSpatialLayers = n_s + 1; | |
456 vp9->spatialLayerResolutionPresent = y_bit ? true : false; | |
457 vp9->gof.numFramesInGof = n_g + 1; | |
458 | |
459 if (y_bit) { | |
460 for (size_t i = 0; i < vp9->numSpatialLayers; ++i) { | |
461 RETURN_FALSE_ON_ERROR(parser->ReadUInt16(&vp9->width[i])); | |
462 RETURN_FALSE_ON_ERROR(parser->ReadUInt16(&vp9->height[i])); | |
463 } | |
464 } | |
465 for (size_t i = 0; i < vp9->gof.numFramesInGof; ++i) { | |
466 uint32_t t, u_bit, r; | |
467 RETURN_FALSE_ON_ERROR(parser->ReadBits(&t, 3)); | |
468 RETURN_FALSE_ON_ERROR(parser->ReadBits(&u_bit, 1)); | |
469 RETURN_FALSE_ON_ERROR(parser->ReadBits(&r, 2)); | |
470 RETURN_FALSE_ON_ERROR(parser->ConsumeBits(2)); | |
471 vp9->gof.temporalIdx[i] = t; | |
472 vp9->gof.temporalUpSwitch[i] = u_bit ? true : false; | |
473 vp9->gof.numRefPics[i] = r; | |
474 | |
475 for (size_t p = 0; p < vp9->gof.numRefPics[i]; ++p) { | |
476 uint8_t p_diff; | |
477 RETURN_FALSE_ON_ERROR(parser->ReadUInt8(&p_diff)); | |
478 vp9->gof.pidDiff[i][p] = p_diff; | |
479 } | |
480 } | |
481 return true; | |
482 } | |
483 | |
484 // Gets the size of next payload chunk to send. Returns 0 on error. | |
485 size_t CalcNextSize(size_t max_length, size_t rem_bytes) { | |
486 if (max_length == 0 || rem_bytes == 0) { | |
487 return 0; | |
488 } | |
489 if (kBalancedMode) { | |
490 size_t num_frags = std::ceil(static_cast<double>(rem_bytes) / max_length); | |
491 return static_cast<size_t>( | |
492 static_cast<double>(rem_bytes) / num_frags + 0.5); | |
493 } | |
494 return max_length >= rem_bytes ? rem_bytes : max_length; | |
495 } | |
496 } // namespace | |
497 | |
498 | |
499 RtpPacketizerVp9::RtpPacketizerVp9(const RTPVideoHeaderVP9& hdr, | |
500 size_t max_payload_length) | |
501 : hdr_(hdr), | |
502 max_payload_length_(max_payload_length), | |
503 payload_(nullptr), | |
504 payload_size_(0) { | |
505 } | |
506 | |
507 RtpPacketizerVp9::~RtpPacketizerVp9() { | |
508 } | |
509 | |
510 ProtectionType RtpPacketizerVp9::GetProtectionType() { | |
511 bool protect = | |
512 hdr_.temporalIdx == 0 || hdr_.temporalIdx == kNoTemporalIdx; | |
513 return protect ? kProtectedPacket : kUnprotectedPacket; | |
514 } | |
515 | |
516 StorageType RtpPacketizerVp9::GetStorageType(uint32_t retransmission_settings) { | |
517 StorageType storage = kAllowRetransmission; | |
518 if (hdr_.temporalIdx == 0 && | |
519 !(retransmission_settings & kRetransmitBaseLayer)) { | |
520 storage = kDontRetransmit; | |
521 } else if (hdr_.temporalIdx != kNoTemporalIdx && hdr_.temporalIdx > 0 && | |
522 !(retransmission_settings & kRetransmitHigherLayers)) { | |
523 storage = kDontRetransmit; | |
524 } | |
525 return storage; | |
526 } | |
527 | |
528 std::string RtpPacketizerVp9::ToString() { | |
529 return "RtpPacketizerVp9"; | |
530 } | |
531 | |
532 void RtpPacketizerVp9::SetPayloadData( | |
533 const uint8_t* payload, | |
534 size_t payload_size, | |
535 const RTPFragmentationHeader* fragmentation) { | |
536 payload_ = payload; | |
537 payload_size_ = payload_size; | |
538 GeneratePackets(); | |
539 } | |
540 | |
541 void RtpPacketizerVp9::GeneratePackets() { | |
542 if (max_payload_length_ < PayloadDescriptorLength(hdr_) + 1) { | |
543 LOG(LS_ERROR) << "Payload header and one payload byte won't fit."; | |
544 return; | |
545 } | |
546 size_t bytes_processed = 0; | |
547 while (bytes_processed < payload_size_) { | |
548 size_t rem_bytes = payload_size_ - bytes_processed; | |
549 size_t rem_payload_len = max_payload_length_ - | |
550 (bytes_processed ? PayloadDescriptorLengthMinusSsData(hdr_) | |
551 : PayloadDescriptorLength(hdr_)); | |
552 | |
553 size_t packet_bytes = CalcNextSize(rem_payload_len, rem_bytes); | |
554 if (packet_bytes == 0) { | |
555 LOG(LS_ERROR) << "Failed to generate VP9 packets."; | |
556 while (!packets_.empty()) | |
557 packets_.pop(); | |
558 return; | |
559 } | |
560 QueuePacket(bytes_processed, packet_bytes, bytes_processed == 0, | |
561 rem_bytes == packet_bytes, &packets_); | |
562 bytes_processed += packet_bytes; | |
563 } | |
564 assert(bytes_processed == payload_size_); | |
565 } | |
566 | |
567 bool RtpPacketizerVp9::NextPacket(uint8_t* buffer, | |
568 size_t* bytes_to_send, | |
569 bool* last_packet) { | |
570 if (packets_.empty()) { | |
571 return false; | |
572 } | |
573 PacketInfo packet_info = packets_.front(); | |
574 packets_.pop(); | |
575 | |
576 if (!WriteHeaderAndPayload(packet_info, buffer, bytes_to_send)) { | |
577 return false; | |
578 } | |
579 *last_packet = packets_.empty(); | |
580 return true; | |
581 } | |
582 | |
583 // VP9 format: | |
584 // | |
585 // Payload descriptor for F = 1 (flexible mode) | |
586 // 0 1 2 3 4 5 6 7 | |
587 // +-+-+-+-+-+-+-+-+ | |
588 // |I|P|L|F|B|E|V|-| (REQUIRED) | |
589 // +-+-+-+-+-+-+-+-+ | |
590 // I: |M| PICTURE ID | (RECOMMENDED) | |
591 // +-+-+-+-+-+-+-+-+ | |
592 // M: | EXTENDED PID | (RECOMMENDED) | |
593 // +-+-+-+-+-+-+-+-+ | |
594 // L: | T |U| S |D| (CONDITIONALLY RECOMMENDED) | |
595 // +-+-+-+-+-+-+-+-+ -| | |
596 // P,F: | P_DIFF |X|N| (CONDITIONALLY RECOMMENDED) . | |
597 // +-+-+-+-+-+-+-+-+ . up to 3 times | |
598 // X: |EXTENDED P_DIFF| . | |
599 // +-+-+-+-+-+-+-+-+ -| | |
600 // V: | SS | | |
601 // | .. | | |
602 // +-+-+-+-+-+-+-+-+ | |
603 // | |
604 // Payload descriptor for F = 0 (non-flexible mode) | |
605 // 0 1 2 3 4 5 6 7 | |
606 // +-+-+-+-+-+-+-+-+ | |
607 // |I|P|L|F|B|E|V|-| (REQUIRED) | |
608 // +-+-+-+-+-+-+-+-+ | |
609 // I: |M| PICTURE ID | (RECOMMENDED) | |
610 // +-+-+-+-+-+-+-+-+ | |
611 // M: | EXTENDED PID | (RECOMMENDED) | |
612 // +-+-+-+-+-+-+-+-+ | |
613 // L: |GOF_IDX| S |D| (CONDITIONALLY RECOMMENDED) | |
614 // +-+-+-+-+-+-+-+-+ | |
615 // | TL0PICIDX | (CONDITIONALLY REQUIRED) | |
616 // +-+-+-+-+-+-+-+-+ | |
617 // V: | SS | | |
618 // | .. | | |
619 // +-+-+-+-+-+-+-+-+ | |
620 | |
621 bool RtpPacketizerVp9::WriteHeaderAndPayload(const PacketInfo& packet_info, | |
622 uint8_t* buffer, | |
623 size_t* bytes_to_send) const { | |
624 size_t header_length; | |
625 if (!WriteHeader(packet_info, buffer, &header_length)) | |
626 return false; | |
627 | |
628 // Copy payload data. | |
629 memcpy(&buffer[header_length], | |
630 &payload_[packet_info.payload_start_pos], packet_info.size); | |
631 | |
632 *bytes_to_send = header_length + packet_info.size; | |
633 return true; | |
634 } | |
635 | |
636 bool RtpPacketizerVp9::WriteHeader(const PacketInfo& packet_info, | |
637 uint8_t* buffer, | |
638 size_t* header_length) const { | |
639 // Required payload descriptor byte. | |
640 uint32_t i_bit = PictureIdPresent(hdr_) ? 1 : 0; | |
641 uint32_t p_bit = hdr_.interPicPredicted ? 1 : 0; | |
642 uint32_t l_bit = LayerInfoPresent(hdr_) ? 1 : 0; | |
643 uint32_t f_bit = hdr_.flexibleMode ? 1 : 0; | |
644 uint32_t b_bit = (hdr_.beginningOfFrame && | |
645 packet_info.layer_begin) ? 1 : 0; | |
646 uint32_t e_bit = (hdr_.endOfFrame && packet_info.layer_end) ? 1 : 0; | |
647 uint32_t v_bit = (hdr_.ssDataAvailable && b_bit) ? 1 : 0; | |
648 | |
649 rtc::BitBufferWriter writer(buffer, max_payload_length_); | |
650 RETURN_FALSE_ON_ERROR(writer.WriteBits(i_bit, 1)); | |
651 RETURN_FALSE_ON_ERROR(writer.WriteBits(p_bit, 1)); | |
652 RETURN_FALSE_ON_ERROR(writer.WriteBits(l_bit, 1)); | |
653 RETURN_FALSE_ON_ERROR(writer.WriteBits(f_bit, 1)); | |
654 RETURN_FALSE_ON_ERROR(writer.WriteBits(b_bit, 1)); | |
655 RETURN_FALSE_ON_ERROR(writer.WriteBits(e_bit, 1)); | |
656 RETURN_FALSE_ON_ERROR(writer.WriteBits(v_bit, 1)); | |
657 RETURN_FALSE_ON_ERROR(writer.WriteBits(kReservedBitValue0, 1)); | |
658 | |
659 // Add fields that are present. | |
660 if (i_bit && !WritePictureId(hdr_, &writer)) { | |
661 LOG(LS_ERROR) << "Failed writing VP9 picture id."; | |
662 return false; | |
663 } | |
664 if (l_bit && !WriteLayerInfo(hdr_, &writer)) { | |
665 LOG(LS_ERROR) << "Failed writing VP9 layer info."; | |
666 return false; | |
667 } | |
668 if (p_bit && f_bit && !WriteRefIndices(hdr_, &writer)) { | |
669 LOG(LS_ERROR) << "Failed writing VP9 ref indices."; | |
670 return false; | |
671 } | |
672 if (v_bit && !WriteSsData(hdr_, &writer)) { | |
673 LOG(LS_ERROR) << "Failed writing VP9 SS data."; | |
674 return false; | |
675 } | |
676 | |
677 size_t offset_bytes = 0; | |
678 size_t offset_bits = 0; | |
679 writer.GetCurrentOffset(&offset_bytes, &offset_bits); | |
680 assert(offset_bits == 0); | |
681 | |
682 *header_length = offset_bytes; | |
683 return true; | |
684 } | |
685 | |
686 bool RtpDepacketizerVp9::Parse(ParsedPayload* parsed_payload, | |
687 const uint8_t* payload, | |
688 size_t payload_length) { | |
689 assert(parsed_payload != nullptr); | |
690 if (payload_length == 0) { | |
691 LOG(LS_ERROR) << "Payload length is zero."; | |
692 return false; | |
693 } | |
694 | |
695 // Parse mandatory first byte of payload descriptor. | |
696 rtc::BitBuffer parser(payload, payload_length); | |
697 uint32_t i_bit, p_bit, l_bit, f_bit, b_bit, e_bit, v_bit; | |
698 RETURN_FALSE_ON_ERROR(parser.ReadBits(&i_bit, 1)); | |
699 RETURN_FALSE_ON_ERROR(parser.ReadBits(&p_bit, 1)); | |
700 RETURN_FALSE_ON_ERROR(parser.ReadBits(&l_bit, 1)); | |
701 RETURN_FALSE_ON_ERROR(parser.ReadBits(&f_bit, 1)); | |
702 RETURN_FALSE_ON_ERROR(parser.ReadBits(&b_bit, 1)); | |
703 RETURN_FALSE_ON_ERROR(parser.ReadBits(&e_bit, 1)); | |
704 RETURN_FALSE_ON_ERROR(parser.ReadBits(&v_bit, 1)); | |
705 RETURN_FALSE_ON_ERROR(parser.ConsumeBits(1)); | |
706 | |
707 // Parsed payload. | |
708 parsed_payload->type.Video.width = 0; | |
709 parsed_payload->type.Video.height = 0; | |
710 parsed_payload->type.Video.simulcastIdx = 0; | |
711 // TODO(asapersson): Add when type is added. | |
712 // parsed_payload->type.Video.codec = kRtpVideoVp9; | |
713 | |
714 parsed_payload->frame_type = p_bit ? kVideoFrameDelta : kVideoFrameKey; | |
715 | |
716 RTPVideoHeaderVP9* vp9 = &parsed_payload->type.Video.codecHeader.VP9; | |
717 vp9->InitRTPVideoHeaderVP9(); | |
718 vp9->interPicPredicted = p_bit ? true : false; | |
719 vp9->flexibleMode = f_bit ? true : false; | |
720 vp9->beginningOfFrame = b_bit ? true : false; | |
721 vp9->endOfFrame = e_bit ? true : false; | |
722 vp9->ssDataAvailable = v_bit ? true : false; | |
723 vp9->temporalIdx = 0; | |
724 vp9->spatialIdx = 0; | |
725 | |
726 // Parse fields that are present. | |
727 if (i_bit && !ParsePictureId(&parser, vp9)) { | |
728 LOG(LS_ERROR) << "Failed parsing VP9 picture id."; | |
729 return false; | |
730 } | |
731 if (l_bit && !ParseLayerInfo(&parser, vp9)) { | |
732 LOG(LS_ERROR) << "Failed parsing VP9 layer info."; | |
733 return false; | |
734 } | |
735 if (p_bit && f_bit && !ParseRefIndices(&parser, vp9)) { | |
736 LOG(LS_ERROR) << "Failed parsing VP9 ref indices."; | |
737 return false; | |
738 } | |
739 if (v_bit) { | |
740 if (!ParseSsData(&parser, vp9)) { | |
741 LOG(LS_ERROR) << "Failed parsing VP9 SS data."; | |
742 return false; | |
743 } | |
744 if (vp9->spatialLayerResolutionPresent) { | |
745 // TODO(asapersson): Add support for spatial layers. | |
746 parsed_payload->type.Video.width = vp9->width[0]; | |
747 parsed_payload->type.Video.height = vp9->height[0]; | |
748 } | |
749 } | |
750 parsed_payload->type.Video.isFirstPacket = b_bit && (vp9->spatialIdx == 0); | |
751 | |
752 uint64_t rem_bits = parser.RemainingBitCount(); | |
753 assert(rem_bits % 8 == 0); | |
754 parsed_payload->payload_length = rem_bits / 8; | |
755 if (parsed_payload->payload_length == 0) { | |
756 LOG(LS_ERROR) << "Failed parsing VP9 payload data."; | |
757 return false; | |
758 } | |
759 parsed_payload->payload = | |
760 payload + payload_length - parsed_payload->payload_length; | |
761 | |
762 return true; | |
763 } | |
764 } // namespace webrtc | |
OLD | NEW |