LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/rtp_rtcp/source - rtp_format_vp9.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 339 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13