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,
32 uint8_t start_code_size) {
34 DCHECK_GT(size, start_code_size);
35 uint8_t header = data[start_code_size];
36 if ((header & 0x80) != 0)
40 header_size_ = start_code_size + 1;
41 data_size_ = size - start_code_size - 1;
42 ref_idc_ = (header >> 5) & 0x3;
43 type_ = header & 0x1F;
44 is_video_slice_ = (type_ >= Nalu::H264_NonIDRSlice &&
45 type_ <= Nalu::H264_IDRSlice);
50 const uint8_t* stream,
53 stream_size_(stream_size),
54 nalu_length_size_(nal_length_size),
55 format_(nal_length_size == 0 ? kAnnexbByteStreamFormat
56 : kNalUnitStreamFormat) {
59 NaluReader::~NaluReader() {}
62 if (stream_size_ <= 0)
63 return NaluReader::kEOStream;
65 uint8_t nalu_length_size_or_start_code_size;
66 uint64_t nalu_length_with_header;
67 if (format_ == kAnnexbByteStreamFormat) {
69 if (!LocateNaluByStartCode(&nalu_length_with_header,
70 &nalu_length_size_or_start_code_size)) {
71 LOG(ERROR) <<
"Could not find next NALU, bytes left in stream: "
76 return NaluReader::kInvalidStream;
82 return NaluReader::kInvalidStream;
83 nalu_length_size_or_start_code_size = nalu_length_size_;
85 if (nalu_length + nalu_length_size_ > stream_size_) {
86 LOG(ERROR) <<
"NALU length exceeds stream size: "
87 << stream_size_ <<
" < " << nalu_length;
88 return NaluReader::kInvalidStream;
90 if (nalu_length == 0) {
91 LOG(ERROR) <<
"NALU size 0";
92 return NaluReader::kInvalidStream;
94 nalu_length_with_header = nalu_length + nalu_length_size_;
97 if (!nalu->InitializeFromH264(stream_, nalu_length_with_header,
98 nalu_length_size_or_start_code_size))
99 return NaluReader::kInvalidStream;
103 stream_ += nalu_length_with_header;
104 stream_size_ -= nalu_length_with_header;
106 DVLOG(4) <<
"NALU type: " <<
static_cast<int>(nalu->type())
107 <<
" at: " << reinterpret_cast<const void*>(nalu->data())
108 <<
" data size: " << nalu->data_size()
109 <<
" ref: " <<
static_cast<int>(nalu->ref_idc());
111 return NaluReader::kOk;
115 bool NaluReader::FindStartCode(
const uint8_t* data,
118 uint8_t* start_code_size) {
119 uint64_t bytes_left = data_size;
121 while (bytes_left >= 3) {
122 if (IsStartCode(data)) {
124 *offset = data_size - bytes_left;
125 *start_code_size = 3;
129 if (*offset > 0 && *(data - 1) == 0x00) {
131 ++(*start_code_size);
143 *offset = data_size - bytes_left;
144 *start_code_size = 0;
148 bool NaluReader::LocateNaluByStartCode(uint64_t* nalu_size,
149 uint8_t* start_code_size) {
151 uint64_t nalu_start_off = 0;
152 uint8_t annexb_start_code_size = 0;
153 if (!FindStartCode(stream_, stream_size_,
154 &nalu_start_off, &annexb_start_code_size)) {
155 DVLOG(4) <<
"Could not find start code, end of stream?";
160 stream_ += nalu_start_off;
161 stream_size_ -= nalu_start_off;
163 const uint8_t* nalu_data = stream_ + annexb_start_code_size;
164 uint64_t max_nalu_data_size = stream_size_ - annexb_start_code_size;
165 if (max_nalu_data_size <= 0) {
166 DVLOG(3) <<
"End of stream";
176 uint64_t nalu_size_without_start_code = 0;
177 uint8_t next_start_code_size = 0;
178 if (!FindStartCode(nalu_data, max_nalu_data_size,
179 &nalu_size_without_start_code, &next_start_code_size)) {
180 nalu_size_without_start_code = max_nalu_data_size;
182 *nalu_size = nalu_size_without_start_code + annexb_start_code_size;
183 *start_code_size = annexb_start_code_size;