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