Shaka Packager SDK
Loading...
Searching...
No Matches
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
17namespace shaka {
18namespace media {
19
20namespace {
21// utility helper function to get an sps
22const 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
42H264ByteToUnitStreamConverter::~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
101bool 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.
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.