5 #include "packager/media/formats/mp2t/mp2t_media_parser.h"
8 #include "packager/base/bind.h"
9 #include "packager/media/base/media_sample.h"
10 #include "packager/media/base/stream_info.h"
11 #include "packager/media/formats/mp2t/es_parser.h"
12 #include "packager/media/formats/mp2t/es_parser_adts.h"
13 #include "packager/media/formats/mp2t/es_parser_h264.h"
14 #include "packager/media/formats/mp2t/es_parser_h265.h"
15 #include "packager/media/formats/mp2t/mp2t_common.h"
16 #include "packager/media/formats/mp2t/ts_packet.h"
17 #include "packager/media/formats/mp2t/ts_section.h"
18 #include "packager/media/formats/mp2t/ts_section_pat.h"
19 #include "packager/media/formats/mp2t/ts_section_pes.h"
20 #include "packager/media/formats/mp2t/ts_section_pmt.h"
28 kStreamTypeMpeg1Audio = 0x3,
30 kStreamTypeAVC = 0x1b,
31 kStreamTypeHEVC = 0x24,
45 std::unique_ptr<TsSection> section_parser);
49 bool PushTsPacket(
const TsPacket& ts_packet);
60 bool IsEnabled()
const;
62 PidType pid_type()
const {
return pid_type_; }
64 scoped_refptr<StreamInfo>& config() {
return config_; }
65 void set_config(
const scoped_refptr<StreamInfo>& config) { config_ = config; }
67 SampleQueue& sample_queue() {
return sample_queue_; }
74 std::unique_ptr<TsSection> section_parser_;
77 int continuity_counter_;
78 scoped_refptr<StreamInfo> config_;
79 SampleQueue sample_queue_;
82 PidState::PidState(
int pid,
84 std::unique_ptr<TsSection> section_parser)
87 section_parser_(std::move(section_parser)),
89 continuity_counter_(-1) {
90 DCHECK(section_parser_);
93 bool PidState::PushTsPacket(
const TsPacket& ts_packet) {
94 DCHECK_EQ(ts_packet.pid(), pid_);
101 int expected_continuity_counter = (continuity_counter_ + 1) % 16;
102 if (continuity_counter_ >= 0 &&
103 ts_packet.continuity_counter() != expected_continuity_counter) {
104 DVLOG(1) <<
"TS discontinuity detected for pid: " << pid_;
109 bool status = section_parser_->Parse(
110 ts_packet.payload_unit_start_indicator(),
112 ts_packet.payload_size());
117 DVLOG(1) <<
"Parsing failed for pid = " << pid_;
124 void PidState::Flush() {
125 section_parser_->Flush();
129 void PidState::Enable() {
133 void PidState::Disable() {
141 bool PidState::IsEnabled()
const {
145 void PidState::ResetState() {
146 section_parser_->Reset();
147 continuity_counter_ = -1;
150 Mp2tMediaParser::Mp2tMediaParser()
151 : sbr_in_mimetype_(false),
152 is_initialized_(false) {
155 Mp2tMediaParser::~Mp2tMediaParser() {}
158 const InitCB& init_cb,
159 const NewSampleCB& new_sample_cb,
161 DCHECK(!is_initialized_);
162 DCHECK(init_cb_.is_null());
163 DCHECK(!init_cb.is_null());
164 DCHECK(!new_sample_cb.is_null());
167 new_sample_cb_ = new_sample_cb;
171 DVLOG(1) <<
"Mp2tMediaParser::Flush";
174 for (
const auto& pair : pids_) {
175 DVLOG(1) <<
"Flushing PID: " << pair.first;
176 PidState* pid_state = pair.second.get();
179 bool result = EmitRemainingSamples();
184 ts_byte_queue_.Reset();
189 DVLOG(1) <<
"Mp2tMediaParser::Parse size=" << size;
192 ts_byte_queue_.Push(buf, size);
195 const uint8_t* ts_buffer;
197 ts_byte_queue_.Peek(&ts_buffer, &ts_buffer_size);
198 if (ts_buffer_size < TsPacket::kPacketSize)
202 int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size);
203 if (skipped_bytes > 0) {
204 DVLOG(1) <<
"Packet not aligned on a TS syncword:"
205 <<
" skipped_bytes=" << skipped_bytes;
206 ts_byte_queue_.Pop(skipped_bytes);
211 std::unique_ptr<TsPacket> ts_packet(
212 TsPacket::Parse(ts_buffer, ts_buffer_size));
214 DVLOG(1) <<
"Error: invalid TS packet";
215 ts_byte_queue_.Pop(1);
219 <<
"Processing PID=" << ts_packet->pid()
220 <<
" start_unit=" << ts_packet->payload_unit_start_indicator();
223 std::map<int, std::unique_ptr<PidState>>::iterator it =
224 pids_.find(ts_packet->pid());
225 if (it == pids_.end() &&
226 ts_packet->pid() == TsSection::kPidPat) {
228 std::unique_ptr<TsSection> pat_section_parser(
new TsSectionPat(
229 base::Bind(&Mp2tMediaParser::RegisterPmt, base::Unretained(
this))));
230 std::unique_ptr<PidState> pat_pid_state(
new PidState(
231 ts_packet->pid(), PidState::kPidPat, std::move(pat_section_parser)));
232 pat_pid_state->Enable();
234 .insert(std::pair<
int, std::unique_ptr<PidState>>(
235 ts_packet->pid(), std::move(pat_pid_state)))
239 if (it != pids_.end()) {
240 if (!it->second->PushTsPacket(*ts_packet))
243 DVLOG(LOG_LEVEL_TS) <<
"Ignoring TS packet for pid: " << ts_packet->pid();
247 ts_byte_queue_.Pop(TsPacket::kPacketSize);
251 return EmitRemainingSamples();
254 void Mp2tMediaParser::RegisterPmt(
int program_number,
int pmt_pid) {
255 DVLOG(1) <<
"RegisterPmt:"
256 <<
" program_number=" << program_number
257 <<
" pmt_pid=" << pmt_pid;
261 for (
const auto& pair : pids_) {
262 if (pair.second->pid_type() == PidState::kPidPmt) {
263 DVLOG_IF(1, pmt_pid != pair.first) <<
"More than one program is defined";
269 DVLOG(1) <<
"Create a new PMT parser";
270 std::unique_ptr<TsSection> pmt_section_parser(
new TsSectionPmt(base::Bind(
271 &Mp2tMediaParser::RegisterPes, base::Unretained(
this), pmt_pid)));
272 std::unique_ptr<PidState> pmt_pid_state(
273 new PidState(pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser)));
274 pmt_pid_state->Enable();
275 pids_.insert(std::pair<
int, std::unique_ptr<PidState>>(
276 pmt_pid, std::move(pmt_pid_state)));
279 void Mp2tMediaParser::RegisterPes(
int pmt_pid,
282 DVLOG(1) <<
"RegisterPes:"
283 <<
" pes_pid=" << pes_pid
284 <<
" stream_type=" << std::hex << stream_type << std::dec;
285 std::map<int, std::unique_ptr<PidState>>::iterator it = pids_.find(pes_pid);
286 if (it != pids_.end())
290 bool is_audio =
false;
291 std::unique_ptr<EsParser> es_parser;
292 if (stream_type == kStreamTypeAVC) {
296 base::Bind(&Mp2tMediaParser::OnNewStreamInfo,
297 base::Unretained(
this)),
298 base::Bind(&Mp2tMediaParser::OnEmitSample,
299 base::Unretained(
this))));
300 }
else if (stream_type == kStreamTypeHEVC) {
304 base::Bind(&Mp2tMediaParser::OnNewStreamInfo,
305 base::Unretained(
this)),
306 base::Bind(&Mp2tMediaParser::OnEmitSample,
307 base::Unretained(
this))));
308 }
else if (stream_type == kStreamTypeAAC) {
312 base::Bind(&Mp2tMediaParser::OnNewStreamInfo,
313 base::Unretained(
this)),
314 base::Bind(&Mp2tMediaParser::OnEmitSample,
315 base::Unretained(
this)),
323 DVLOG(1) <<
"Create a new PES state";
324 std::unique_ptr<TsSection> pes_section_parser(
325 new TsSectionPes(std::move(es_parser)));
326 PidState::PidType pid_type =
327 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
328 std::unique_ptr<PidState> pes_pid_state(
329 new PidState(pes_pid, pid_type, std::move(pes_section_parser)));
330 pes_pid_state->Enable();
331 pids_.insert(std::pair<
int, std::unique_ptr<PidState>>(
332 pes_pid, std::move(pes_pid_state)));
335 void Mp2tMediaParser::OnNewStreamInfo(
336 const scoped_refptr<StreamInfo>& new_stream_info) {
337 DCHECK(new_stream_info);
338 DVLOG(1) <<
"OnVideoConfigChanged for pid=" << new_stream_info->track_id();
340 PidMap::iterator pid_state = pids_.find(new_stream_info->track_id());
341 if (pid_state == pids_.end()) {
342 LOG(ERROR) <<
"PID State for new stream not found (pid = "
343 << new_stream_info->track_id() <<
").";
348 pid_state->second->set_config(new_stream_info);
351 FinishInitializationIfNeeded();
354 bool Mp2tMediaParser::FinishInitializationIfNeeded() {
363 std::vector<scoped_refptr<StreamInfo> > all_stream_info;
365 for (PidMap::const_iterator iter = pids_.begin(); iter != pids_.end();
367 if (((iter->second->pid_type() == PidState::kPidAudioPes) ||
368 (iter->second->pid_type() == PidState::kPidVideoPes))) {
370 if (iter->second->config())
371 all_stream_info.push_back(iter->second->config());
374 if (num_es && (all_stream_info.size() == num_es)) {
377 init_cb_.Run(all_stream_info);
378 DVLOG(1) <<
"Mpeg2TS stream parser initialization done";
379 is_initialized_ =
true;
384 void Mp2tMediaParser::OnEmitSample(
386 const scoped_refptr<MediaSample>& new_sample) {
393 << new_sample->data_size()
397 << new_sample->pts();
400 PidMap::iterator pid_state = pids_.find(pes_pid);
401 if (pid_state == pids_.end()) {
402 LOG(ERROR) <<
"PID State for new sample not found (pid = "
406 pid_state->second->sample_queue().push_back(new_sample);
409 bool Mp2tMediaParser::EmitRemainingSamples() {
410 DVLOG(LOG_LEVEL_ES) <<
"Mp2tMediaParser::EmitRemainingBuffers";
413 if (!is_initialized_)
417 for (PidMap::const_iterator pid_iter = pids_.begin(); pid_iter != pids_.end();
419 SampleQueue& sample_queue = pid_iter->second->sample_queue();
420 for (SampleQueue::iterator sample_iter = sample_queue.begin();
421 sample_iter != sample_queue.end();
423 if (!new_sample_cb_.Run(pid_iter->first, *sample_iter)) {
428 sample_queue.clear();