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