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;
28 is_video_slice_(false) {}
30 bool Nalu::InitializeFromH264(
const uint8_t* data, uint64_t size) {
33 uint8_t header = data[0];
34 if ((header & 0x80) != 0)
39 payload_size_ = size - 1;
40 ref_idc_ = (header >> 5) & 0x3;
41 type_ = header & 0x1F;
42 is_video_slice_ = (type_ >= Nalu::H264_NonIDRSlice &&
43 type_ <= Nalu::H264_IDRSlice);
48 const uint8_t* stream,
51 stream_size_(stream_size),
52 nalu_length_size_(nal_length_size),
53 format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
54 : kNalUnitStreamFormat) {
57 NaluReader::~NaluReader() {}
60 if (stream_size_ <= 0)
61 return NaluReader::kEOStream;
63 uint8_t nalu_length_size_or_start_code_size;
65 if (format_ == kAnnexbByteStreamFormat) {
67 uint64_t nalu_length_with_header;
68 if (!LocateNaluByStartCode(&nalu_length_with_header,
69 &nalu_length_size_or_start_code_size)) {
70 LOG(ERROR) <<
"Could not find next NALU, bytes left in stream: "
75 return NaluReader::kInvalidStream;
77 nalu_length = nalu_length_with_header - nalu_length_size_or_start_code_size;
81 return NaluReader::kInvalidStream;
82 nalu_length_size_or_start_code_size = nalu_length_size_;
84 if (nalu_length + nalu_length_size_ > stream_size_) {
85 LOG(ERROR) <<
"NALU length exceeds stream size: "
86 << stream_size_ <<
" < " << nalu_length;
87 return NaluReader::kInvalidStream;
89 if (nalu_length == 0) {
90 LOG(ERROR) <<
"NALU size 0";
91 return NaluReader::kInvalidStream;
95 const uint8_t* nalu_data = stream_ + nalu_length_size_or_start_code_size;
96 if (!nalu->InitializeFromH264(nalu_data, nalu_length))
97 return NaluReader::kInvalidStream;
101 stream_ += nalu_length_size_or_start_code_size + nalu_length;
102 stream_size_ -= nalu_length_size_or_start_code_size + nalu_length;
104 DVLOG(4) <<
"NALU type: " <<
static_cast<int>(nalu->type())
105 <<
" at: " << reinterpret_cast<const void*>(nalu->data())
106 <<
" data size: " << nalu->payload_size()
107 <<
" ref: " <<
static_cast<int>(nalu->ref_idc());
109 return NaluReader::kOk;
113 if (stream_size_ >= 3) {
114 if (IsStartCode(stream_))
117 if (stream_size_ >= 4) {
118 if (stream_[0] == 0x00 && IsStartCode(stream_ + 1))
125 bool NaluReader::FindStartCode(
const uint8_t* data,
128 uint8_t* start_code_size) {
129 uint64_t bytes_left = data_size;
131 while (bytes_left >= 3) {
132 if (IsStartCode(data)) {
134 *offset = data_size - bytes_left;
135 *start_code_size = 3;
139 if (*offset > 0 && *(data - 1) == 0x00) {
141 ++(*start_code_size);
153 *offset = data_size - bytes_left;
154 *start_code_size = 0;
158 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
159 uint8_t* start_code_size) {
161 uint64_t nalu_start_off = 0;
162 uint8_t annexb_start_code_size = 0;
163 if (!FindStartCode(stream_, stream_size_,
164 &nalu_start_off, &annexb_start_code_size)) {
165 DVLOG(4) <<
"Could not find start code, end of stream?";
170 stream_ += nalu_start_off;
171 stream_size_ -= nalu_start_off;
173 const uint8_t* nalu_data = stream_ + annexb_start_code_size;
174 uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
175 if (max_nalu_data_size <= 0) {
176 DVLOG(3) <<
"End of stream";
186 uint64_t nalu_size_without_start_code = 0;
187 uint8_t next_start_code_size = 0;
188 if (!FindStartCode(nalu_data, max_nalu_data_size,
189 &nalu_size_without_start_code, &next_start_code_size)) {
190 nalu_size_without_start_code = max_nalu_data_size;
192 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
193 *start_code_size = annexb_start_code_size;