Shaka Packager SDK
h265_byte_to_unit_stream_converter.cc
1 // Copyright 2016 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/codecs/h265_byte_to_unit_stream_converter.h>
8 
9 #include <limits>
10 
11 #include <absl/log/check.h>
12 #include <absl/log/log.h>
13 
14 #include <packager/media/base/buffer_writer.h>
15 #include <packager/media/base/rcheck.h>
16 #include <packager/media/codecs/h265_parser.h>
17 
18 namespace shaka {
19 namespace media {
20 
23 
25  H26xStreamFormat stream_format)
26  : H26xByteToUnitStreamConverter(Nalu::kH265, stream_format) {}
27 
28 H265ByteToUnitStreamConverter::~H265ByteToUnitStreamConverter() {}
29 
31  std::vector<uint8_t>* decoder_config) const {
32  DCHECK(decoder_config);
33 
34  if (last_sps_.empty() || last_pps_.empty() || last_vps_.empty()) {
35  // No data available to construct HEVCDecoderConfigurationRecord.
36  return false;
37  }
38 
39  // We need to parse the SPS to get the data to add to the record.
40  int id;
41  Nalu nalu;
42  H265Parser parser;
43  RCHECK(nalu.Initialize(Nalu::kH265, last_sps_.data(), last_sps_.size()));
44  RCHECK(parser.ParseSps(nalu, &id) == H265Parser::kOk);
45  const H265Sps* sps = parser.GetSps(id);
46 
47  // Construct an HEVCDecoderConfigurationRecord containing a single SPS, PPS,
48  // and VPS NALU. Please refer to ISO/IEC 14496-15 for format specifics.
49  BufferWriter buffer(last_sps_.size() + last_pps_.size() + last_vps_.size() +
50  100);
51  buffer.AppendInt(static_cast<uint8_t>(1) /* version */);
52  // (1) general_profile_space, general_tier_flag, general_profile_idc
53  // (4) general_profile_compatibility_flags
54  // (6) general_constraint_indicator_flags
55  // (1) general_level_idc
56  for (int byte : sps->general_profile_tier_level_data)
57  buffer.AppendInt(static_cast<uint8_t>(byte));
58 
59  // The default value for this field is 0, which is Unknown.
60  int min_spatial_segmentation_idc =
61  sps->vui_parameters.min_spatial_segmentation_idc;
62 
63  buffer.AppendInt(
64  static_cast<uint16_t>(0xf000 | min_spatial_segmentation_idc));
65  buffer.AppendInt(static_cast<uint8_t>(0xfc) /* parallelismType = 0 */);
66  buffer.AppendInt(static_cast<uint8_t>(0xfc | sps->chroma_format_idc));
67  buffer.AppendInt(static_cast<uint8_t>(0xf8 | sps->bit_depth_luma_minus8));
68  buffer.AppendInt(static_cast<uint8_t>(0xf8 | sps->bit_depth_chroma_minus8));
69  buffer.AppendInt(static_cast<uint16_t>(0) /* avgFrameRate */);
70  // Following flags are 0:
71  // constantFrameRate
72  // numTemporalLayers
73  // temporalIdNested
74  buffer.AppendInt(static_cast<uint8_t>(kUnitStreamNaluLengthSize - 1));
75  buffer.AppendInt(static_cast<uint8_t>(3) /* numOfArrays */);
76 
77  // More parameter set NALUs may follow when strip_parameter_set_nalus is
78  // disabled.
79  const uint8_t array_completeness = strip_parameter_set_nalus() ? 0x80 : 0;
80 
81  // VPS
82  buffer.AppendInt(static_cast<uint8_t>(array_completeness | Nalu::H265_VPS));
83  buffer.AppendInt(static_cast<uint16_t>(1) /* numNalus */);
84  buffer.AppendInt(static_cast<uint16_t>(last_vps_.size()));
85  buffer.AppendVector(last_vps_);
86 
87  // SPS
88  buffer.AppendInt(static_cast<uint8_t>(array_completeness | Nalu::H265_SPS));
89  buffer.AppendInt(static_cast<uint16_t>(1) /* numNalus */);
90  buffer.AppendInt(static_cast<uint16_t>(last_sps_.size()));
91  buffer.AppendVector(last_sps_);
92 
93  // PPS
94  buffer.AppendInt(static_cast<uint8_t>(array_completeness | Nalu::H265_PPS));
95  buffer.AppendInt(static_cast<uint16_t>(1) /* numNalus */);
96  buffer.AppendInt(static_cast<uint16_t>(last_pps_.size()));
97  buffer.AppendVector(last_pps_);
98 
99  buffer.SwapBuffer(decoder_config);
100  return true;
101 }
102 
103 bool H265ByteToUnitStreamConverter::ProcessNalu(const Nalu& nalu) {
104  DCHECK(nalu.data());
105 
106  // Skip the start code, but keep the 2-byte NALU header.
107  const uint8_t* nalu_ptr = nalu.data();
108  const uint64_t nalu_size = nalu.payload_size() + nalu.header_size();
109 
110  switch (nalu.type()) {
111  case Nalu::H265_SPS:
112  if (strip_parameter_set_nalus())
113  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_sps_);
114  // Grab SPS NALU.
115  last_sps_.assign(nalu_ptr, nalu_ptr + nalu_size);
116  return strip_parameter_set_nalus();
117  case Nalu::H265_PPS:
118  if (strip_parameter_set_nalus())
119  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_pps_);
120  // Grab PPS NALU.
121  last_pps_.assign(nalu_ptr, nalu_ptr + nalu_size);
122  return strip_parameter_set_nalus();
123  case Nalu::H265_VPS:
124  if (strip_parameter_set_nalus())
125  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_vps_);
126  // Grab VPS NALU.
127  last_vps_.assign(nalu_ptr, nalu_ptr + nalu_size);
128  return strip_parameter_set_nalus();
129  case Nalu::H265_AUD:
130  // Ignore AUD NALU.
131  return true;
132  default:
133  // Have the base class handle other NALU types.
134  return false;
135  }
136 }
137 
138 } // namespace media
139 } // namespace shaka
bool GetDecoderConfigurationRecord(std::vector< uint8_t > *decoder_config) const override
Result ParseSps(const Nalu &nalu, int *sps_id)
Definition: h265_parser.cc:528
const H265Sps * GetSps(int sps_id)
Definition: h265_parser.cc:649
A base class that is used to convert H.26x byte streams to NAL unit streams.
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition: nalu_reader.h:96
int type() const
Definition: nalu_reader.h:112
uint64_t header_size() const
The size of the header, e.g. 1 for H.264.
Definition: nalu_reader.h:99
uint64_t payload_size() const
Size of this Nalu minus header_size().
Definition: nalu_reader.h:101
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66