5 #include "packager/media/formats/mp2t/es_parser_h26x.h"
9 #include "packager/base/logging.h"
10 #include "packager/base/numerics/safe_conversions.h"
11 #include "packager/media/base/media_sample.h"
12 #include "packager/media/base/offset_byte_queue.h"
13 #include "packager/media/base/timestamp.h"
14 #include "packager/media/base/video_stream_info.h"
15 #include "packager/media/codecs/h26x_byte_to_unit_stream_converter.h"
16 #include "packager/media/formats/mp2t/mp2t_common.h"
24 const int kStartCodeSize = 3;
25 const int kH264NaluHeaderSize = 1;
26 const int kH265NaluHeaderSize = 2;
30 EsParserH26x::EsParserH26x(
32 std::unique_ptr<H26xByteToUnitStreamConverter> stream_converter,
34 const EmitSampleCB& emit_sample_cb)
36 emit_sample_cb_(emit_sample_cb),
38 es_queue_(new media::OffsetByteQueue()),
39 current_search_position_(0),
40 stream_converter_(std::move(stream_converter)),
41 pending_sample_duration_(0),
42 waiting_for_key_frame_(true) {}
44 EsParserH26x::~EsParserH26x() {}
46 bool EsParserH26x::Parse(
const uint8_t* buf,
59 DVLOG_IF(1, pts == kNoTimestamp) <<
"Each video PES should have a PTS";
60 if (pts != kNoTimestamp) {
61 TimingDesc timing_desc;
62 timing_desc.pts = pts;
63 timing_desc.dts = (dts != kNoTimestamp) ? dts : pts;
66 timing_desc_list_.push_back(
67 std::pair<int64_t, TimingDesc>(es_queue_->tail(), timing_desc));
71 es_queue_->Push(buf, size);
76 if (access_unit_nalus_.empty()) {
77 if (!SkipToFirstAccessUnit())
80 DCHECK(!access_unit_nalus_.empty());
81 DCHECK(access_unit_nalus_.front().nalu.can_start_access_unit());
83 return ParseInternal();
86 void EsParserH26x::Flush() {
87 DVLOG(1) <<
"EsParserH26x::Flush";
91 if (type_ == Nalu::kH264) {
92 const uint8_t aud[] = {0x00, 0x00, 0x01, 0x09};
93 es_queue_->Push(aud,
sizeof(aud));
95 DCHECK_EQ(Nalu::kH265, type_);
96 const uint8_t aud[] = {0x00, 0x00, 0x01, 0x46, 0x01};
97 es_queue_->Push(aud,
sizeof(aud));
100 CHECK(ParseInternal());
104 if (access_unit_nalus_.size() > 1 &&
105 !ProcessAccessUnit(access_unit_nalus_.end() - 1)) {
106 LOG(WARNING) <<
"Error processing last access unit.";
109 if (pending_sample_) {
111 DCHECK(pending_sample_duration_);
112 pending_sample_->set_duration(pending_sample_duration_);
113 emit_sample_cb_.Run(pid(), pending_sample_);
114 pending_sample_ = scoped_refptr<MediaSample>();
118 void EsParserH26x::Reset() {
119 es_queue_.reset(
new media::OffsetByteQueue());
120 current_search_position_ = 0;
121 access_unit_nalus_.clear();
122 timing_desc_list_.clear();
123 pending_sample_ = scoped_refptr<MediaSample>();
124 pending_sample_duration_ = 0;
125 waiting_for_key_frame_ =
true;
128 bool EsParserH26x::SkipToFirstAccessUnit() {
129 DCHECK(access_unit_nalus_.empty());
130 while (access_unit_nalus_.empty()) {
131 if (!SearchForNextNalu())
135 DCHECK_EQ(1u, access_unit_nalus_.size());
136 if (!access_unit_nalus_.back().nalu.can_start_access_unit())
137 access_unit_nalus_.clear();
142 bool EsParserH26x::SearchForNextNalu() {
145 es_queue_->PeekAt(current_search_position_, &es, &es_size);
148 uint64_t start_code_offset;
149 uint8_t start_code_size;
150 const bool start_code_found = NaluReader::FindStartCode(
151 es, es_size, &start_code_offset, &start_code_size);
153 if (!start_code_found) {
155 if (es_size > kStartCodeSize)
156 current_search_position_ += es_size - kStartCodeSize;
161 const uint8_t* nalu_ptr = es + start_code_offset + start_code_size;
163 const int64_t next_nalu_size = es_size - start_code_offset - start_code_size;
165 (type_ == Nalu::kH264 ? kH264NaluHeaderSize : kH265NaluHeaderSize)) {
171 if (!next_nalu.Initialize(type_, nalu_ptr, next_nalu_size)) {
173 current_search_position_ += start_code_offset + start_code_size;
174 return SearchForNextNalu();
177 current_search_position_ += start_code_offset + start_code_size;
180 info.position = current_search_position_ - start_code_size;
181 info.start_code_size = start_code_size;
182 info.nalu = next_nalu;
183 access_unit_nalus_.push_back(info);
188 bool EsParserH26x::ProcessAccessUnit(std::deque<NaluInfo>::iterator end) {
189 DCHECK(end < access_unit_nalus_.end());
190 auto begin = access_unit_nalus_.begin();
193 es_queue_->PeekAt(begin->position, &es, &es_size);
194 DCHECK_GE(static_cast<uint64_t>(es_size), (end->position - begin->position));
197 bool is_key_frame =
false;
199 for (
auto it = begin; it != end; ++it) {
200 if (it->nalu.nuh_layer_id() == 0) {
202 CHECK(it->nalu.Initialize(
203 type_, es + (it->position - begin->position) + it->start_code_size,
204 ((it+1)->position - it->position) - it->start_code_size));
205 if (!ProcessNalu(it->nalu, &is_key_frame, &pps_id))
211 waiting_for_key_frame_ =
false;
212 if (!waiting_for_key_frame_) {
213 const uint64_t access_unit_size = end->position - begin->position;
214 RCHECK(EmitFrame(begin->position, access_unit_size, is_key_frame, pps_id));
220 bool EsParserH26x::ParseInternal() {
222 if (!SearchForNextNalu())
235 DCHECK(!access_unit_nalus_.empty());
236 if (!access_unit_nalus_.back().nalu.is_video_slice() ||
237 access_unit_nalus_.back().nalu.nuh_layer_id() != 0) {
243 auto access_unit_end_rit = access_unit_nalus_.rbegin();
244 bool found_vcl =
false;
245 for (
auto rit = access_unit_nalus_.rbegin() + 1;
246 rit != access_unit_nalus_.rend(); ++rit) {
247 if (rit->nalu.is_video_slice()) {
250 }
else if (rit->nalu.can_start_access_unit()) {
253 access_unit_end_rit = rit;
262 auto end = (access_unit_end_rit + 1).base();
263 if (!ProcessAccessUnit(end))
267 es_queue_->Trim(end->position);
268 access_unit_nalus_.erase(access_unit_nalus_.begin(), end);
272 bool EsParserH26x::EmitFrame(int64_t access_unit_pos,
273 int access_unit_size,
277 TimingDesc current_timing_desc = {kNoTimestamp, kNoTimestamp};
278 while (!timing_desc_list_.empty() &&
279 timing_desc_list_.front().first <= access_unit_pos) {
280 current_timing_desc = timing_desc_list_.front().second;
281 timing_desc_list_.pop_front();
283 if (current_timing_desc.pts == kNoTimestamp)
287 DVLOG(LOG_LEVEL_ES) <<
"Emit frame: stream_pos=" << access_unit_pos
288 <<
" size=" << access_unit_size;
291 es_queue_->PeekAt(access_unit_pos, &es, &es_size);
294 std::vector<uint8_t> converted_frame;
295 if (!stream_converter_->ConvertByteStreamToNalUnitStream(
296 es, access_unit_size, &converted_frame)) {
297 DLOG(ERROR) <<
"Failure to convert video frame to unit stream format.";
302 RCHECK(UpdateVideoDecoderConfig(pps_id));
307 converted_frame.data(), converted_frame.size(), is_key_frame);
308 media_sample->set_dts(current_timing_desc.dts);
309 media_sample->set_pts(current_timing_desc.pts);
310 if (pending_sample_) {
311 DCHECK_GT(media_sample->dts(), pending_sample_->dts());
312 pending_sample_duration_ = media_sample->dts() - pending_sample_->dts();
313 pending_sample_->set_duration(pending_sample_duration_);
314 emit_sample_cb_.Run(pid(), pending_sample_);
316 pending_sample_ = media_sample;