Shaka Packager SDK
h264_byte_to_unit_stream_converter.cc
1 // Copyright 2014 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/h264_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/codecs/h264_parser.h>
16 
17 namespace shaka {
18 namespace media {
19 
20 namespace {
21 // utility helper function to get an sps
22 const H264Sps* ParseSpsFromBytes(const std::vector<uint8_t> sps,
23  H264Parser* parser) {
24  Nalu nalu;
25  if (!nalu.Initialize(Nalu::kH264, sps.data(), sps.size()))
26  return nullptr;
27 
28  int sps_id = 0;
29  if (parser->ParseSps(nalu, &sps_id) != H264Parser::kOk)
30  return nullptr;
31  return parser->GetSps(sps_id);
32 }
33 } // namespace
34 
37 
39  H26xStreamFormat stream_format)
40  : H26xByteToUnitStreamConverter(Nalu::kH264, stream_format) {}
41 
42 H264ByteToUnitStreamConverter::~H264ByteToUnitStreamConverter() {}
43 
45  std::vector<uint8_t>* decoder_config) const {
46  DCHECK(decoder_config);
47  if ((last_sps_.size() < 4) || last_pps_.empty()) {
48  // No data available to construct AVCDecoderConfigurationRecord.
49  return false;
50  }
51  // Construct an AVCDecoderConfigurationRecord containing a single SPS, a
52  // single PPS, and if available, a single SPS Extension NALU.
53  // Please refer to ISO/IEC 14496-15 for format specifics.
54  BufferWriter buffer;
55  uint8_t version(1);
56  buffer.AppendInt(version);
57  buffer.AppendInt(last_sps_[1]);
58  buffer.AppendInt(last_sps_[2]);
59  buffer.AppendInt(last_sps_[3]);
60  uint8_t reserved_and_length_size_minus_one(0xff);
61  buffer.AppendInt(reserved_and_length_size_minus_one);
62  uint8_t reserved_and_num_sps(0xe1);
63  buffer.AppendInt(reserved_and_num_sps);
64  buffer.AppendInt(static_cast<uint16_t>(last_sps_.size()));
65  buffer.AppendVector(last_sps_);
66  uint8_t num_pps(1);
67  buffer.AppendInt(num_pps);
68  buffer.AppendInt(static_cast<uint16_t>(last_pps_.size()));
69  buffer.AppendVector(last_pps_);
70  // handle profile special cases, refer to ISO/IEC 14496-15 Section 5.3.3.1.2
71  uint8_t profile_indication = last_sps_[1];
72  if (profile_indication == 100 || profile_indication == 110 ||
73  profile_indication == 122 || profile_indication == 144) {
74 
75  H264Parser parser;
76  const H264Sps* sps = ParseSpsFromBytes(last_sps_, &parser);
77  if (sps == nullptr)
78  return false;
79 
80  uint8_t reserved_chroma_format = 0xfc | (sps->chroma_format_idc);
81  buffer.AppendInt(reserved_chroma_format);
82  uint8_t reserved_bit_depth_luma_minus8 = 0xf8 | sps->bit_depth_luma_minus8;
83  buffer.AppendInt(reserved_bit_depth_luma_minus8);
84  uint8_t reserved_bit_depth_chroma_minus8 = 0xf8 | sps->bit_depth_chroma_minus8;
85  buffer.AppendInt(reserved_bit_depth_chroma_minus8);
86 
87  if (last_sps_ext_.empty()) {
88  uint8_t num_sps_ext(0);
89  buffer.AppendInt(num_sps_ext);
90  } else {
91  uint8_t num_sps_ext(1);
92  buffer.AppendInt(num_sps_ext);
93  buffer.AppendVector(last_sps_ext_);
94  }
95  }
96 
97  buffer.SwapBuffer(decoder_config);
98  return true;
99 }
100 
101 bool H264ByteToUnitStreamConverter::ProcessNalu(const Nalu& nalu) {
102  DCHECK(nalu.data());
103 
104  // Skip the start code, but keep the 1-byte NALU type.
105  const uint8_t* nalu_ptr = nalu.data();
106  const uint64_t nalu_size = nalu.payload_size() + nalu.header_size();
107 
108  switch (nalu.type()) {
109  case Nalu::H264_SPS:
110  if (strip_parameter_set_nalus())
111  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_sps_);
112  // Grab SPS NALU.
113  last_sps_.assign(nalu_ptr, nalu_ptr + nalu_size);
114  return strip_parameter_set_nalus();
115  case Nalu::H264_SPSExtension:
116  if (strip_parameter_set_nalus())
117  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_sps_ext_);
118  // Grab SPSExtension NALU.
119  last_sps_ext_.assign(nalu_ptr, nalu_ptr + nalu_size);
120  return strip_parameter_set_nalus();
121  case Nalu::H264_PPS:
122  if (strip_parameter_set_nalus())
123  WarnIfNotMatch(nalu.type(), nalu_ptr, nalu_size, last_pps_);
124  // Grab PPS NALU.
125  last_pps_.assign(nalu_ptr, nalu_ptr + nalu_size);
126  return strip_parameter_set_nalus();
127  case Nalu::H264_AUD:
128  // Ignore AUD NALU.
129  return true;
130  default:
131  // Have the base class handle other NALU types.
132  return false;
133  }
134 }
135 
136 } // namespace media
137 } // namespace shaka
bool GetDecoderConfigurationRecord(std::vector< uint8_t > *decoder_config) const override
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