Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(184)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_format_vp9.cc

Issue 1232023006: Add support for VP9 packetization/depacketization. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698