modules/rtp_rtcp/source/h264_sps_parser_unittest.cc
void GenerateFakeSps(uint16_t width, uint16_t height, uint8_t buffer[]) {
  uint8_t rbsp[kSpsBufferMaxSize] = {0};
  rtc::BitBufferWriter writer(rbsp, kSpsBufferMaxSize);
  // Profile byte.
  writer.WriteUInt8(0);
  // Constraint sets and reserved zero bits.
  writer.WriteUInt8(0);
  // level_idc.
  writer.WriteUInt8(0x3u);
  // seq_paramter_set_id.
  writer.WriteExponentialGolomb(0);
  // Profile is not special, so we skip all the chroma format settings.

  // Now some bit magic.
  // log2_max_frame_num_minus4: ue(v). 0 is fine.
  writer.WriteExponentialGolomb(0);
  // pic_order_cnt_type: ue(v). 0 is the type we want.
  writer.WriteExponentialGolomb(0);
  // log2_max_pic_order_cnt_lsb_minus4: ue(v). 0 is fine.
  writer.WriteExponentialGolomb(0);
  // max_num_ref_frames: ue(v). 0 is fine.
  writer.WriteExponentialGolomb(0);
  // gaps_in_frame_num_value_allowed_flag: u(1).
  writer.WriteBits(0, 1);
  // Next are width/height. First, calculate the mbs/map_units versions.
  uint16_t width_in_mbs_minus1 = (width + 15) / 16 - 1;

  // For the height, we're going to define frame_mbs_only_flag, so we need to
  // divide by 2. See the parser for the full calculation.
  uint16_t height_in_map_units_minus1 = ((height + 15) / 16 - 1) / 2;
  // Write each as ue(v).
  writer.WriteExponentialGolomb(width_in_mbs_minus1);
  writer.WriteExponentialGolomb(height_in_map_units_minus1);
  // frame_mbs_only_flag: u(1). Needs to be false.
  writer.WriteBits(0, 1);
  // mb_adaptive_frame_field_flag: u(1).
  writer.WriteBits(0, 1);
  // direct_8x8_inferene_flag: u(1).
  writer.WriteBits(0, 1);
  // frame_cropping_flag: u(1). 1, so we can supply crop.
  writer.WriteBits(1, 1);
  // Now we write the left/right/top/bottom crop. For simplicity, we'll put all
  // the crop at the left/top.
  // We picked a 4:2:0 format, so the crops are 1/2 the pixel crop values.
  // Left/right.
  writer.WriteExponentialGolomb(((16 - (width % 16)) % 16) / 2);
  writer.WriteExponentialGolomb(0);
  // Top/bottom.
  writer.WriteExponentialGolomb(((16 - (height % 16)) % 16) / 2);
  writer.WriteExponentialGolomb(0);

  // Get the number of bytes written (including the last partial byte).
  size_t byte_count, bit_offset;
  writer.GetCurrentOffset(&byte_count, &bit_offset);
  if (bit_offset > 0) {
    byte_count++;
  }

  // Now, we need to write the rbsp into bytes. To do that, we'll need to add
  // emulation 0x03 bytes if there's ever a sequence of 00 00 01 or 00 00 00 01.
  // To be simple, just add a 0x03 after every 0x00. Extra emulation doesn't
  // hurt.
  for (size_t i = 0; i < byte_count;) {
    // The -3 is intentional; we never need to write an emulation byte if the 00
    // is at the end.
    if (i < byte_count - 3 && rbsp[i] == 0 && rbsp[i + 1] == 0) {
      *buffer++ = rbsp[i];
      *buffer++ = rbsp[i + 1];
      *buffer++ = 0x3u;
      i += 2;
    } else {
      *buffer++ = rbsp[i];
      ++i;
    }
  }
}
// Generates a fake SPS with basically everything empty but the width/height.
// Pass in a buffer of at least kSpsBufferMaxSize.
// The fake SPS that this generates also always has at least one emulation byte
// at offset 2, since the first two bytes are always 0, and has a 0x3 as the
// level_idc, to make sure the parser doesn't eat all 0x3 bytes.
Generates a fake SPS with basically everything empty but the width/height.
Pass in a buffer of at least kSpsBufferMaxSize.
The fake SPS that this generates also always has at least one emulation byte
at offset 2, since the first two bytes are always 0, and has a 0x3 as the
level_idc, to make sure the parser doesn't eat all 0x3 bytes.
Generates a fake SPS with basically everything empty but the width / height . Pass in a buffer of at least kSpsBufferMaxSize . The fake SPS that this generates also always has at least one emulation byte at offset 2 since the first two bytes are always 0 and has a 0x3 as the level_idc to make sure the parser doesn ' t eat all 0x3 bytes .
void GenerateFakeSps(uint16_t width, uint16_t height, uint8_t buffer[]) {
  uint8_t rbsp[kSpsBufferMaxSize] = {0};
  rtc::BitBufferWriter writer(rbsp, kSpsBufferMaxSize);
  writer.WriteUInt8(0);
  writer.WriteUInt8(0);
  writer.WriteUInt8(0x3u);
  writer.WriteExponentialGolomb(0);
  writer.WriteExponentialGolomb(0);
  writer.WriteExponentialGolomb(0);
  writer.WriteExponentialGolomb(0);
  writer.WriteExponentialGolomb(0);
  writer.WriteBits(0, 1);
  uint16_t width_in_mbs_minus1 = (width + 15) / 16 - 1;
  uint16_t height_in_map_units_minus1 = ((height + 15) / 16 - 1) / 2;
  writer.WriteExponentialGolomb(width_in_mbs_minus1);
  writer.WriteExponentialGolomb(height_in_map_units_minus1);
  writer.WriteBits(0, 1);
  writer.WriteBits(0, 1);
  writer.WriteBits(0, 1);
  writer.WriteBits(1, 1);
  writer.WriteExponentialGolomb(((16 - (width % 16)) % 16) / 2);
  writer.WriteExponentialGolomb(0);
  writer.WriteExponentialGolomb(((16 - (height % 16)) % 16) / 2);
  writer.WriteExponentialGolomb(0);
  size_t byte_count, bit_offset;
  writer.GetCurrentOffset(&byte_count, &bit_offset);
  if (bit_offset > 0) {
    byte_count++;
  }
  for (size_t i = 0; i < byte_count;) {
    if (i < byte_count - 3 && rbsp[i] == 0 && rbsp[i + 1] == 0) {
      *buffer++ = rbsp[i];
      *buffer++ = rbsp[i + 1];
      *buffer++ = 0x3u;
      i += 2;
    } else {
      *buffer++ = rbsp[i];
      ++i;
    }
  }
}
void GenerateFakeSps ( uint16_t width , uint16_t height , uint8_t buffer [ ] ) { uint8_t rbsp [ kSpsBufferMaxSize ] = { 0 } ; rtc :: BitBufferWriter writer ( rbsp , kSpsBufferMaxSize ) ; writer . WriteUInt8 ( 0 ) ; writer . WriteUInt8 ( 0 ) ; writer . WriteUInt8 ( 0x3u ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteBits ( 0 , 1 ) ; uint16_t width_in_mbs_minus1 = ( width + 15 ) / 16 - 1 ; uint16_t height_in_map_units_minus1 = ( ( height + 15 ) / 16 - 1 ) / 2 ; writer . WriteExponentialGolomb ( width_in_mbs_minus1 ) ; writer . WriteExponentialGolomb ( height_in_map_units_minus1 ) ; writer . WriteBits ( 0 , 1 ) ; writer . WriteBits ( 0 , 1 ) ; writer . WriteBits ( 0 , 1 ) ; writer . WriteBits ( 1 , 1 ) ; writer . WriteExponentialGolomb ( ( ( 16 - ( width % 16 ) ) % 16 ) / 2 ) ; writer . WriteExponentialGolomb ( 0 ) ; writer . WriteExponentialGolomb ( ( ( 16 - ( height % 16 ) ) % 16 ) / 2 ) ; writer . WriteExponentialGolomb ( 0 ) ; size_t byte_count , bit_offset ; writer . GetCurrentOffset ( & byte_count , & bit_offset ) ; if ( bit_offset > 0 ) { byte_count ++ ; } for ( size_t i = 0 ; i < byte_count ; ) { if ( i < byte_count - 3 && rbsp [ i ] == 0 && rbsp [ i + 1 ] == 0 ) { * buffer ++ = rbsp [ i ] ; * buffer ++ = rbsp [ i + 1 ] ; * buffer ++ = 0x3u ; i += 2 ; } else { * buffer ++ = rbsp [ i ] ; ++ i ; } } }
Generates a fake SPS with basically everything empty but the width/height.
Generates a fake SPS with basically everything empty but the width / height .
// Profile byte. // Constraint sets and reserved zero bits. // level_idc. // seq_paramter_set_id. // Profile is not special, so we skip all the chroma format settings. // Now some bit magic. // log2_max_frame_num_minus4: ue(v). 0 is fine. // pic_order_cnt_type: ue(v). 0 is the type we want. // log2_max_pic_order_cnt_lsb_minus4: ue(v). 0 is fine. // max_num_ref_frames: ue(v). 0 is fine. // gaps_in_frame_num_value_allowed_flag: u(1). // Next are width/height. First, calculate the mbs/map_units versions. // For the height, we're going to define frame_mbs_only_flag, so we need to // divide by 2. See the parser for the full calculation. // Write each as ue(v). // frame_mbs_only_flag: u(1). Needs to be false. // mb_adaptive_frame_field_flag: u(1). // direct_8x8_inferene_flag: u(1). // frame_cropping_flag: u(1). 1, so we can supply crop. // Now we write the left/right/top/bottom crop. For simplicity, we'll put all // the crop at the left/top. // We picked a 4:2:0 format, so the crops are 1/2 the pixel crop values. // Left/right. // Top/bottom. // Get the number of bytes written (including the last partial byte). // Now, we need to write the rbsp into bytes. To do that, we'll need to add // emulation 0x03 bytes if there's ever a sequence of 00 00 01 or 00 00 00 01. // To be simple, just add a 0x03 after every 0x00. Extra emulation doesn't // hurt. // The -3 is intentional; we never need to write an emulation byte if the 00 // is at the end.