Shaka Packager SDK
Loading...
Searching...
No Matches
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
18namespace shaka {
19namespace media {
20
23
25 H26xStreamFormat stream_format)
26 : H26xByteToUnitStreamConverter(Nalu::kH265, stream_format) {}
27
28H265ByteToUnitStreamConverter::~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
103bool 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)
const H265Sps * GetSps(int sps_id)
A base class that is used to convert H.26x byte streams to NAL unit streams.
uint64_t header_size() const
The size of the header, e.g. 1 for H.264.
Definition nalu_reader.h:99
const uint8_t * data() const
This is the pointer to the Nalu data, pointing to the header.
Definition nalu_reader.h:96
uint64_t payload_size() const
Size of this Nalu minus header_size().
All the methods that are virtual are virtual for mocking.