7 #include "packager/media/filters/nalu_reader.h"
9 #include "packager/base/logging.h"
10 #include "packager/media/base/buffer_reader.h"
11 #include "packager/media/filters/h264_parser.h"
13 namespace edash_packager {
17 inline bool IsStartCode(
const uint8_t* data) {
18 return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01;
30 is_video_slice_(false) {}
32 bool Nalu::InitializeFromH264(
const uint8_t* data, uint64_t size) {
36 uint8_t header = data[0];
37 if ((header & 0x80) != 0)
42 payload_size_ = size - header_size_;
43 ref_idc_ = (header >> 5) & 0x3;
44 type_ = header & 0x1F;
45 is_video_slice_ = (type_ >= Nalu::H264_NonIDRSlice &&
46 type_ <= Nalu::H264_IDRSlice);
50 bool Nalu::InitializeFromH265(
const uint8_t* data, uint64_t size) {
54 uint16_t header = (data[0] << 8) | data[1];
55 if ((header & 0x8000) != 0)
60 payload_size_ = size - header_size_;
62 type_ = (header >> 9) & 0x3F;
63 nuh_layer_id_ = (header >> 3) & 0x3F;
64 nuh_temporal_id_ = (header & 0x7) - 1;
68 (type_ >= Nalu::H265_TRAIL_N && type_ <= Nalu::H265_RASL_R) ||
69 (type_ >= Nalu::H265_BLA_W_LP && type_ <= Nalu::H265_CRA_NUT);
74 uint8_t nal_length_size,
75 const uint8_t* stream,
78 stream_size_(stream_size),
80 nalu_length_size_(nal_length_size),
81 format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
82 : kNalUnitStreamFormat) {
85 NaluReader::~NaluReader() {}
88 if (stream_size_ <= 0)
89 return NaluReader::kEOStream;
91 uint8_t nalu_length_size_or_start_code_size;
93 if (format_ == kAnnexbByteStreamFormat) {
95 uint64_t nalu_length_with_header;
96 if (!LocateNaluByStartCode(&nalu_length_with_header,
97 &nalu_length_size_or_start_code_size)) {
98 LOG(ERROR) <<
"Could not find next NALU, bytes left in stream: "
103 return NaluReader::kInvalidStream;
105 nalu_length = nalu_length_with_header - nalu_length_size_or_start_code_size;
109 return NaluReader::kInvalidStream;
110 nalu_length_size_or_start_code_size = nalu_length_size_;
112 if (nalu_length + nalu_length_size_ > stream_size_) {
113 LOG(ERROR) <<
"NALU length exceeds stream size: "
114 << stream_size_ <<
" < " << nalu_length;
115 return NaluReader::kInvalidStream;
117 if (nalu_length == 0) {
118 LOG(ERROR) <<
"NALU size 0";
119 return NaluReader::kInvalidStream;
123 const uint8_t* nalu_data = stream_ + nalu_length_size_or_start_code_size;
124 if (nalu_type_ == kH264) {
125 if (!nalu->InitializeFromH264(nalu_data, nalu_length))
126 return NaluReader::kInvalidStream;
128 DCHECK_EQ(kH265, nalu_type_);
129 if (!nalu->InitializeFromH265(nalu_data, nalu_length))
130 return NaluReader::kInvalidStream;
135 stream_ += nalu_length_size_or_start_code_size + nalu_length;
136 stream_size_ -= nalu_length_size_or_start_code_size + nalu_length;
138 DVLOG(4) <<
"NALU type: " <<
static_cast<int>(nalu->type())
139 <<
" at: " << reinterpret_cast<const void*>(nalu->data())
140 <<
" data size: " << nalu->payload_size();
142 return NaluReader::kOk;
146 if (stream_size_ >= 3) {
147 if (IsStartCode(stream_))
150 if (stream_size_ >= 4) {
151 if (stream_[0] == 0x00 && IsStartCode(stream_ + 1))
158 bool NaluReader::FindStartCode(
const uint8_t* data,
161 uint8_t* start_code_size) {
162 uint64_t bytes_left = data_size;
164 while (bytes_left >= 3) {
165 if (IsStartCode(data)) {
167 *offset = data_size - bytes_left;
168 *start_code_size = 3;
172 if (*offset > 0 && *(data - 1) == 0x00) {
174 ++(*start_code_size);
186 *offset = data_size - bytes_left;
187 *start_code_size = 0;
191 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
192 uint8_t* start_code_size) {
194 uint64_t nalu_start_off = 0;
195 uint8_t annexb_start_code_size = 0;
196 if (!FindStartCode(stream_, stream_size_,
197 &nalu_start_off, &annexb_start_code_size)) {
198 DVLOG(4) <<
"Could not find start code, end of stream?";
203 stream_ += nalu_start_off;
204 stream_size_ -= nalu_start_off;
206 const uint8_t* nalu_data = stream_ + annexb_start_code_size;
207 uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
208 if (max_nalu_data_size <= 0) {
209 DVLOG(3) <<
"End of stream";
219 uint64_t nalu_size_without_start_code = 0;
220 uint8_t next_start_code_size = 0;
221 if (!FindStartCode(nalu_data, max_nalu_data_size,
222 &nalu_size_without_start_code, &next_start_code_size)) {
223 nalu_size_without_start_code = max_nalu_data_size;
225 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
226 *start_code_size = annexb_start_code_size;