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;
31 EsParserH26x::EsParserH26x(
33 scoped_ptr<H26xByteToUnitStreamConverter> stream_converter,
35 const EmitSampleCB& emit_sample_cb)
37 emit_sample_cb_(emit_sample_cb),
39 es_queue_(new media::OffsetByteQueue()),
40 current_search_position_(0),
41 stream_converter_(stream_converter.Pass()),
42 pending_sample_duration_(0),
43 waiting_for_key_frame_(true) {}
45 EsParserH26x::~EsParserH26x() {}
47 bool EsParserH26x::Parse(
const uint8_t* buf,
60 DVLOG_IF(1, pts == kNoTimestamp) <<
"Each video PES should have a PTS";
61 if (pts != kNoTimestamp) {
62 TimingDesc timing_desc;
63 timing_desc.pts = pts;
64 timing_desc.dts = (dts != kNoTimestamp) ? dts : pts;
67 timing_desc_list_.push_back(
68 std::pair<int64_t, TimingDesc>(es_queue_->tail(), timing_desc));
72 es_queue_->Push(buf, size);
77 if (access_unit_nalus_.empty()) {
78 if (!SkipToFirstAccessUnit())
81 DCHECK(!access_unit_nalus_.empty());
82 DCHECK(access_unit_nalus_.front().nalu.can_start_access_unit());
84 return ParseInternal();
87 void EsParserH26x::Flush() {
88 DVLOG(1) <<
"EsParserH26x::Flush";
92 if (type_ == Nalu::kH264) {
93 const uint8_t aud[] = {0x00, 0x00, 0x01, 0x09};
94 es_queue_->Push(aud,
sizeof(aud));
96 DCHECK_EQ(Nalu::kH265, type_);
97 const uint8_t aud[] = {0x00, 0x00, 0x01, 0x46, 0x01};
98 es_queue_->Push(aud,
sizeof(aud));
101 CHECK(ParseInternal());
105 if (access_unit_nalus_.size() > 1 &&
106 !ProcessAccessUnit(access_unit_nalus_.end() - 1)) {
107 LOG(WARNING) <<
"Error processing last access unit.";
110 if (pending_sample_) {
112 DCHECK(pending_sample_duration_);
113 pending_sample_->set_duration(pending_sample_duration_);
114 emit_sample_cb_.Run(pid(), pending_sample_);
115 pending_sample_ = scoped_refptr<MediaSample>();
119 void EsParserH26x::Reset() {
120 es_queue_.reset(
new media::OffsetByteQueue());
121 current_search_position_ = 0;
122 access_unit_nalus_.clear();
123 timing_desc_list_.clear();
124 pending_sample_ = scoped_refptr<MediaSample>();
125 pending_sample_duration_ = 0;
126 waiting_for_key_frame_ =
true;
129 bool EsParserH26x::SkipToFirstAccessUnit() {
130 DCHECK(access_unit_nalus_.empty());
131 while (access_unit_nalus_.empty()) {
132 if (!SearchForNextNalu())
136 DCHECK_EQ(1u, access_unit_nalus_.size());
137 if (!access_unit_nalus_.back().nalu.can_start_access_unit())
138 access_unit_nalus_.clear();
143 bool EsParserH26x::SearchForNextNalu() {
146 es_queue_->PeekAt(current_search_position_, &es, &es_size);
149 uint64_t start_code_offset;
150 uint8_t start_code_size;
151 const bool start_code_found = NaluReader::FindStartCode(
152 es, es_size, &start_code_offset, &start_code_size);
154 if (!start_code_found) {
156 if (es_size > kStartCodeSize)
157 current_search_position_ += es_size - kStartCodeSize;
162 const uint8_t* nalu_ptr = es + start_code_offset + start_code_size;
164 const int64_t next_nalu_size = es_size - start_code_offset - start_code_size;
166 (type_ == Nalu::kH264 ? kH264NaluHeaderSize : kH265NaluHeaderSize)) {
172 if (!next_nalu.Initialize(type_, nalu_ptr, next_nalu_size)) {
174 current_search_position_ += start_code_offset + start_code_size;
175 return SearchForNextNalu();
178 current_search_position_ += start_code_offset + start_code_size;
181 info.position = current_search_position_ - start_code_size;
182 info.start_code_size = start_code_size;
183 info.nalu = next_nalu;
184 access_unit_nalus_.push_back(info);
189 bool EsParserH26x::ProcessAccessUnit(std::deque<NaluInfo>::iterator end) {
190 DCHECK(end < access_unit_nalus_.end());
191 auto begin = access_unit_nalus_.begin();
194 es_queue_->PeekAt(begin->position, &es, &es_size);
195 DCHECK_GE(static_cast<uint64_t>(es_size), (end->position - begin->position));
198 bool is_key_frame =
false;
200 for (
auto it = begin; it != end; ++it) {
201 if (it->nalu.nuh_layer_id() == 0) {
203 CHECK(it->nalu.Initialize(
204 type_, es + (it->position - begin->position) + it->start_code_size,
205 ((it+1)->position - it->position) - it->start_code_size));
206 if (!ProcessNalu(it->nalu, &is_key_frame, &pps_id))
212 waiting_for_key_frame_ =
false;
213 if (!waiting_for_key_frame_) {
214 const uint64_t access_unit_size = end->position - begin->position;
215 RCHECK(EmitFrame(begin->position, access_unit_size, is_key_frame, pps_id));
221 bool EsParserH26x::ParseInternal() {
223 if (!SearchForNextNalu())
236 DCHECK(!access_unit_nalus_.empty());
237 if (!access_unit_nalus_.back().nalu.is_video_slice() ||
238 access_unit_nalus_.back().nalu.nuh_layer_id() != 0) {
244 auto access_unit_end_rit = access_unit_nalus_.rbegin();
245 bool found_vcl =
false;
246 for (
auto rit = access_unit_nalus_.rbegin() + 1;
247 rit != access_unit_nalus_.rend(); ++rit) {
248 if (rit->nalu.is_video_slice()) {
251 }
else if (rit->nalu.can_start_access_unit()) {
254 access_unit_end_rit = rit;
263 auto end = (access_unit_end_rit + 1).base();
264 if (!ProcessAccessUnit(end))
268 es_queue_->Trim(end->position);
269 access_unit_nalus_.erase(access_unit_nalus_.begin(), end);
273 bool EsParserH26x::EmitFrame(int64_t access_unit_pos,
274 int access_unit_size,
278 TimingDesc current_timing_desc = {kNoTimestamp, kNoTimestamp};
279 while (!timing_desc_list_.empty() &&
280 timing_desc_list_.front().first <= access_unit_pos) {
281 current_timing_desc = timing_desc_list_.front().second;
282 timing_desc_list_.pop_front();
284 if (current_timing_desc.pts == kNoTimestamp)
288 DVLOG(LOG_LEVEL_ES) <<
"Emit frame: stream_pos=" << access_unit_pos
289 <<
" size=" << access_unit_size;
292 es_queue_->PeekAt(access_unit_pos, &es, &es_size);
295 std::vector<uint8_t> converted_frame;
296 if (!stream_converter_->ConvertByteStreamToNalUnitStream(
297 es, access_unit_size, &converted_frame)) {
298 DLOG(ERROR) <<
"Failure to convert video frame to unit stream format.";
303 RCHECK(UpdateVideoDecoderConfig(pps_id));
308 converted_frame.data(), converted_frame.size(), is_key_frame);
309 media_sample->set_dts(current_timing_desc.dts);
310 media_sample->set_pts(current_timing_desc.pts);
311 if (pending_sample_) {
312 DCHECK_GT(media_sample->dts(), pending_sample_->dts());
313 pending_sample_duration_ = media_sample->dts() - pending_sample_->dts();
314 pending_sample_->set_duration(pending_sample_duration_);
315 emit_sample_cb_.Run(pid(), pending_sample_);
317 pending_sample_ = media_sample;