1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/formats/mp2t/mp2t_stream_parser.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/optional.h"
13 #include "media/base/media_tracks.h"
14 #include "media/base/stream_parser_buffer.h"
15 #include "media/base/text_track_config.h"
16 #include "media/base/timestamp_constants.h"
17 #include "media/formats/mp2t/descriptors.h"
18 #include "media/formats/mp2t/es_parser.h"
19 #include "media/formats/mp2t/es_parser_adts.h"
20 #include "media/formats/mp2t/es_parser_h264.h"
21 #include "media/formats/mp2t/es_parser_mpeg1audio.h"
22 #include "media/formats/mp2t/mp2t_common.h"
23 #include "media/formats/mp2t/ts_packet.h"
24 #include "media/formats/mp2t/ts_section.h"
25 #include "media/formats/mp2t/ts_section_pat.h"
26 #include "media/formats/mp2t/ts_section_pes.h"
27 #include "media/formats/mp2t/ts_section_pmt.h"
28
29 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
30 #include "media/formats/mp2t/ts_section_cat.h"
31 #include "media/formats/mp2t/ts_section_cets_ecm.h"
32 #include "media/formats/mp2t/ts_section_cets_pssh.h"
33 #endif
34
35 namespace media {
36 namespace mp2t {
37
38 namespace {
39
40 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
41 const int64_t kSampleAESPrivateDataIndicatorAVC = 0x7a617663;
42 const int64_t kSampleAESPrivateDataIndicatorAAC = 0x61616364;
43 // TODO(dougsteed). Consider adding support for the following:
44 // const int64_t kSampleAESPrivateDataIndicatorAC3 = 0x61633364;
45 // const int64_t kSampleAESPrivateDataIndicatorEAC3 = 0x65633364;
46 #endif
47
48 } // namespace
49
50 enum StreamType {
51 // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments"
52 kStreamTypeMpeg1Audio = 0x3,
53 // ISO/IEC 13818-3 Audio (MPEG-2)
54 kStreamTypeMpeg2Audio = 0x4,
55 kStreamTypeAAC = 0xf,
56 kStreamTypeAVC = 0x1b,
57 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
58 kStreamTypeAACWithSampleAES = 0xcf,
59 kStreamTypeAVCWithSampleAES = 0xdb,
60 // TODO(dougsteed). Consider adding support for the following:
61 // kStreamTypeAC3WithSampleAES = 0xc1,
62 // kStreamTypeEAC3WithSampleAES = 0xc2,
63 #endif
64 };
65
66 class PidState {
67 public:
68 enum PidType {
69 kPidPat,
70 kPidPmt,
71 kPidAudioPes,
72 kPidVideoPes,
73 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
74 kPidCat,
75 kPidCetsEcm,
76 kPidCetsPssh,
77 #endif
78 };
79
80 PidState(int pid,
81 PidType pid_type,
82 std::unique_ptr<TsSection> section_parser);
83
84 // Extract the content of the TS packet and parse it.
85 // Return true if successful.
86 bool PushTsPacket(const TsPacket& ts_packet);
87
88 // Flush the PID state (possibly emitting some pending frames)
89 // and reset its state.
90 void Flush();
91
92 // Enable/disable the PID.
93 // Disabling a PID will reset its state and ignore any further incoming TS
94 // packets.
95 void Enable();
96 void Disable();
97 bool IsEnabled() const;
98
pid_type() const99 PidType pid_type() const { return pid_type_; }
100
101 private:
102 void ResetState();
103
104 int pid_;
105 PidType pid_type_;
106 std::unique_ptr<TsSection> section_parser_;
107
108 bool enable_;
109
110 int continuity_counter_;
111 };
112
PidState(int pid,PidType pid_type,std::unique_ptr<TsSection> section_parser)113 PidState::PidState(int pid,
114 PidType pid_type,
115 std::unique_ptr<TsSection> section_parser)
116 : pid_(pid),
117 pid_type_(pid_type),
118 section_parser_(std::move(section_parser)),
119 enable_(false),
120 continuity_counter_(-1) {
121 DCHECK(section_parser_);
122 }
123
PushTsPacket(const TsPacket & ts_packet)124 bool PidState::PushTsPacket(const TsPacket& ts_packet) {
125 DCHECK_EQ(ts_packet.pid(), pid_);
126
127 // The current PID is not part of the PID filter,
128 // just discard the incoming TS packet.
129 if (!enable_)
130 return true;
131
132 int expected_continuity_counter = (continuity_counter_ + 1) % 16;
133 if (continuity_counter_ >= 0 &&
134 ts_packet.continuity_counter() != expected_continuity_counter) {
135 DVLOG(1) << "TS discontinuity detected for pid: " << pid_;
136 return false;
137 }
138
139 bool status = section_parser_->Parse(
140 ts_packet.payload_unit_start_indicator(),
141 ts_packet.payload(),
142 ts_packet.payload_size());
143
144 // At the minimum, when parsing failed, auto reset the section parser.
145 // Components that use the StreamParser can take further action if needed.
146 if (!status) {
147 DVLOG(1) << "Parsing failed for pid = " << pid_;
148 ResetState();
149 }
150
151 return status;
152 }
153
Flush()154 void PidState::Flush() {
155 section_parser_->Flush();
156 ResetState();
157 }
158
Enable()159 void PidState::Enable() {
160 enable_ = true;
161 }
162
Disable()163 void PidState::Disable() {
164 if (!enable_)
165 return;
166
167 ResetState();
168 enable_ = false;
169 }
170
IsEnabled() const171 bool PidState::IsEnabled() const {
172 return enable_;
173 }
174
ResetState()175 void PidState::ResetState() {
176 section_parser_->Reset();
177 continuity_counter_ = -1;
178 }
179
BufferQueueWithConfig(bool is_cfg_sent,const AudioDecoderConfig & audio_cfg,const VideoDecoderConfig & video_cfg)180 Mp2tStreamParser::BufferQueueWithConfig::BufferQueueWithConfig(
181 bool is_cfg_sent,
182 const AudioDecoderConfig& audio_cfg,
183 const VideoDecoderConfig& video_cfg)
184 : is_config_sent(is_cfg_sent),
185 audio_config(audio_cfg),
186 video_config(video_cfg) {
187 }
188
189 Mp2tStreamParser::BufferQueueWithConfig::BufferQueueWithConfig(
190 const BufferQueueWithConfig& other) = default;
191
~BufferQueueWithConfig()192 Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() {
193 }
194
Mp2tStreamParser(bool sbr_in_mimetype)195 Mp2tStreamParser::Mp2tStreamParser(bool sbr_in_mimetype)
196 : sbr_in_mimetype_(sbr_in_mimetype),
197 selected_audio_pid_(-1),
198 selected_video_pid_(-1),
199 is_initialized_(false),
200 segment_started_(false) {
201 }
202
~Mp2tStreamParser()203 Mp2tStreamParser::~Mp2tStreamParser() {
204 }
205
Init(InitCB init_cb,const NewConfigCB & config_cb,const NewBuffersCB & new_buffers_cb,bool,const EncryptedMediaInitDataCB & encrypted_media_init_data_cb,const NewMediaSegmentCB & new_segment_cb,const EndMediaSegmentCB & end_of_segment_cb,MediaLog * media_log)206 void Mp2tStreamParser::Init(
207 InitCB init_cb,
208 const NewConfigCB& config_cb,
209 const NewBuffersCB& new_buffers_cb,
210 bool /* ignore_text_tracks */,
211 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
212 const NewMediaSegmentCB& new_segment_cb,
213 const EndMediaSegmentCB& end_of_segment_cb,
214 MediaLog* media_log) {
215 DCHECK(!is_initialized_);
216 DCHECK(!init_cb_);
217 DCHECK(init_cb);
218 DCHECK(config_cb);
219 DCHECK(new_buffers_cb);
220 DCHECK(encrypted_media_init_data_cb);
221 DCHECK(new_segment_cb);
222 DCHECK(end_of_segment_cb);
223
224 init_cb_ = std::move(init_cb);
225 config_cb_ = config_cb;
226 new_buffers_cb_ = new_buffers_cb;
227 encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
228 new_segment_cb_ = new_segment_cb;
229 end_of_segment_cb_ = end_of_segment_cb;
230 media_log_ = media_log;
231 }
232
Flush()233 void Mp2tStreamParser::Flush() {
234 DVLOG(1) << "Mp2tStreamParser::Flush";
235
236 // Flush the buffers and reset the pids.
237 for (const auto& pid_pair : pids_) {
238 DVLOG(1) << "Flushing PID: " << pid_pair.first;
239 pid_pair.second->Flush();
240 }
241 pids_.clear();
242
243 // Flush is invoked from SourceBuffer.abort/SourceState::ResetParserState, and
244 // MSE spec prohibits emitting new configs in ResetParserState algorithm (see
245 // https://w3c.github.io/media-source/#sourcebuffer-reset-parser-state,
246 // 3.5.2 Reset Parser State states that new frames might be processed only in
247 // PARSING_MEDIA_SEGMENT and therefore doesn't allow emitting new configs,
248 // since that might need to run "init segment received" algorithm).
249 // So before we emit remaining buffers here, we need to trim our buffer queue
250 // so that we leave only buffers with configs that were already sent.
251 for (auto buffer_queue_iter = buffer_queue_chain_.begin();
252 buffer_queue_iter != buffer_queue_chain_.end(); ++buffer_queue_iter) {
253 const BufferQueueWithConfig& queue_with_config = *buffer_queue_iter;
254 if (!queue_with_config.is_config_sent) {
255 DVLOG(LOG_LEVEL_ES) << "Flush: dropping buffers with unsent new configs.";
256 buffer_queue_chain_.erase(buffer_queue_iter, buffer_queue_chain_.end());
257 break;
258 }
259 }
260
261 EmitRemainingBuffers();
262 buffer_queue_chain_.clear();
263
264 // End of the segment.
265 // Note: does not need to invoke |end_of_segment_cb_| since flushing the
266 // stream parser already involves the end of the current segment.
267 segment_started_ = false;
268
269 // Remove any bytes left in the TS buffer.
270 // (i.e. any partial TS packet => less than 188 bytes).
271 ts_byte_queue_.Reset();
272
273 // Reset the selected PIDs.
274 selected_audio_pid_ = -1;
275 selected_video_pid_ = -1;
276
277 // Reset the timestamp unroller.
278 timestamp_unroller_.Reset();
279 }
280
GetGenerateTimestampsFlag() const281 bool Mp2tStreamParser::GetGenerateTimestampsFlag() const {
282 return false;
283 }
284
Parse(const uint8_t * buf,int size)285 bool Mp2tStreamParser::Parse(const uint8_t* buf, int size) {
286 DVLOG(1) << "Mp2tStreamParser::Parse size=" << size;
287
288 // Add the data to the parser state.
289 ts_byte_queue_.Push(buf, size);
290
291 while (true) {
292 const uint8_t* ts_buffer;
293 int ts_buffer_size;
294 ts_byte_queue_.Peek(&ts_buffer, &ts_buffer_size);
295 if (ts_buffer_size < TsPacket::kPacketSize)
296 break;
297
298 // Synchronization.
299 int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size);
300 if (skipped_bytes > 0) {
301 DVLOG(1) << "Packet not aligned on a TS syncword:"
302 << " skipped_bytes=" << skipped_bytes;
303 ts_byte_queue_.Pop(skipped_bytes);
304 continue;
305 }
306
307 // Parse the TS header, skipping 1 byte if the header is invalid.
308 std::unique_ptr<TsPacket> ts_packet(
309 TsPacket::Parse(ts_buffer, ts_buffer_size));
310 if (!ts_packet) {
311 DVLOG(1) << "Error: invalid TS packet";
312 ts_byte_queue_.Pop(1);
313 continue;
314 }
315 DVLOG(LOG_LEVEL_TS)
316 << "Processing PID=" << ts_packet->pid()
317 << " start_unit=" << ts_packet->payload_unit_start_indicator();
318
319 // Parse the section.
320 auto it = pids_.find(ts_packet->pid());
321 if (it == pids_.end() &&
322 ts_packet->pid() == TsSection::kPidPat) {
323 // Create the PAT state here if needed.
324 auto pat_section_parser =
325 std::make_unique<TsSectionPat>(base::BindRepeating(
326 &Mp2tStreamParser::RegisterPmt, base::Unretained(this)));
327 auto pat_pid_state = std::make_unique<PidState>(
328 ts_packet->pid(), PidState::kPidPat, std::move(pat_section_parser));
329 pat_pid_state->Enable();
330 it = pids_
331 .insert(
332 std::make_pair(ts_packet->pid(), std::move(pat_pid_state)))
333 .first;
334 }
335 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
336 // We allow a CAT to appear as the first packet in the TS. This allows us to
337 // specify encryption metadata for HLS by injecting it as an extra TS packet
338 // at the front of the stream.
339 else if (it == pids_.end() && ts_packet->pid() == TsSection::kPidCat) {
340 it = pids_.insert(std::make_pair(TsSection::kPidCat, MakeCatPidState()))
341 .first;
342 }
343 #endif
344
345 if (it != pids_.end()) {
346 if (!it->second->PushTsPacket(*ts_packet))
347 return false;
348 } else {
349 DVLOG(LOG_LEVEL_TS) << "Ignoring TS packet for pid: " << ts_packet->pid();
350 }
351
352 // Go to the next packet.
353 ts_byte_queue_.Pop(TsPacket::kPacketSize);
354 }
355
356 RCHECK(FinishInitializationIfNeeded());
357
358 // Emit the A/V buffers that kept accumulating during TS parsing.
359 return EmitRemainingBuffers();
360 }
361
RegisterPmt(int program_number,int pmt_pid)362 void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) {
363 DVLOG(1) << "RegisterPmt:"
364 << " program_number=" << program_number
365 << " pmt_pid=" << pmt_pid;
366
367 // Only one TS program is allowed. Ignore the incoming program map table,
368 // if there is already one registered.
369 for (const auto& pid_pair : pids_) {
370 PidState* pid_state = pid_pair.second.get();
371 if (pid_state->pid_type() == PidState::kPidPmt) {
372 DVLOG_IF(1, pmt_pid != pid_pair.first)
373 << "More than one program is defined";
374 return;
375 }
376 }
377
378 // Create the PMT state here if needed.
379 DVLOG(1) << "Create a new PMT parser";
380 auto pmt_section_parser = std::make_unique<TsSectionPmt>(base::BindRepeating(
381 &Mp2tStreamParser::RegisterPes, base::Unretained(this)));
382 auto pmt_pid_state = std::make_unique<PidState>(
383 pmt_pid, PidState::kPidPmt, std::move(pmt_section_parser));
384 pmt_pid_state->Enable();
385 pids_.insert(std::make_pair(pmt_pid, std::move(pmt_pid_state)));
386
387 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
388 // Take the opportunity to clean up any PIDs that were involved in importing
389 // encryption metadata for HLS with SampleAES. This prevents the possibility
390 // of interference with actual PIDs that might be declared in the PMT.
391 // TODO(dougsteed): if in the future the appropriate PIDs are embedded in the
392 // source stream, this will not be necessary.
393 UnregisterCat();
394 UnregisterCencPids();
395 #endif
396 }
397
CreateH264Parser(int pes_pid)398 std::unique_ptr<EsParser> Mp2tStreamParser::CreateH264Parser(int pes_pid) {
399 auto on_video_config_changed = base::BindRepeating(
400 &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
401 auto on_emit_video_buffer = base::BindRepeating(
402 &Mp2tStreamParser::OnEmitVideoBuffer, base::Unretained(this), pes_pid);
403
404 return std::make_unique<EsParserH264>(std::move(on_video_config_changed),
405 std::move(on_emit_video_buffer));
406 }
407
CreateAacParser(int pes_pid)408 std::unique_ptr<EsParser> Mp2tStreamParser::CreateAacParser(int pes_pid) {
409 auto on_audio_config_changed = base::BindRepeating(
410 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
411 auto on_emit_audio_buffer = base::BindRepeating(
412 &Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), pes_pid);
413 return std::make_unique<EsParserAdts>(on_audio_config_changed,
414 std::move(on_emit_audio_buffer),
415 sbr_in_mimetype_);
416 }
417
CreateMpeg1AudioParser(int pes_pid)418 std::unique_ptr<EsParser> Mp2tStreamParser::CreateMpeg1AudioParser(
419 int pes_pid) {
420 auto on_audio_config_changed = base::BindRepeating(
421 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
422 auto on_emit_audio_buffer = base::BindRepeating(
423 &Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), pes_pid);
424 return std::make_unique<EsParserMpeg1Audio>(
425 on_audio_config_changed, std::move(on_emit_audio_buffer), media_log_);
426 }
427
428 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
ShouldForceEncryptedParser()429 bool Mp2tStreamParser::ShouldForceEncryptedParser() {
430 // If we expect to handle encrypted data later in the stream, then force the
431 // use of the encrypted parser variant so that the initial configuration
432 // reflects the intended encryption mode (even if the initial segment itself
433 // is not encrypted).
434 return initial_encryption_scheme_ != EncryptionScheme::kUnencrypted;
435 }
436
CreateEncryptedH264Parser(int pes_pid,bool emit_clear_buffers)437 std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedH264Parser(
438 int pes_pid,
439 bool emit_clear_buffers) {
440 auto on_video_config_changed = base::BindRepeating(
441 &Mp2tStreamParser::OnVideoConfigChanged, base::Unretained(this), pes_pid);
442 auto on_emit_video_buffer = base::BindRepeating(
443 &Mp2tStreamParser::OnEmitVideoBuffer, base::Unretained(this), pes_pid);
444 EsParserAdts::GetDecryptConfigCB get_decrypt_config;
445 if (!emit_clear_buffers) {
446 get_decrypt_config = base::BindRepeating(
447 &Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
448 }
449 return std::make_unique<EsParserH264>(
450 std::move(on_video_config_changed), on_emit_video_buffer,
451 initial_encryption_scheme_, std::move(get_decrypt_config));
452 }
453
CreateEncryptedAacParser(int pes_pid,bool emit_clear_buffers)454 std::unique_ptr<EsParser> Mp2tStreamParser::CreateEncryptedAacParser(
455 int pes_pid,
456 bool emit_clear_buffers) {
457 auto on_audio_config_changed = base::BindRepeating(
458 &Mp2tStreamParser::OnAudioConfigChanged, base::Unretained(this), pes_pid);
459 auto on_emit_audio_buffer = base::BindRepeating(
460 &Mp2tStreamParser::OnEmitAudioBuffer, base::Unretained(this), pes_pid);
461 EsParserAdts::GetDecryptConfigCB get_decrypt_config;
462 if (!emit_clear_buffers) {
463 get_decrypt_config = base::BindRepeating(
464 &Mp2tStreamParser::GetDecryptConfig, base::Unretained(this));
465 }
466 return std::make_unique<EsParserAdts>(
467 on_audio_config_changed, std::move(on_emit_audio_buffer),
468 std::move(get_decrypt_config), initial_encryption_scheme_,
469 sbr_in_mimetype_);
470 }
471 #endif
472
RegisterPes(int pes_pid,int stream_type,const Descriptors & descriptors)473 void Mp2tStreamParser::RegisterPes(int pes_pid,
474 int stream_type,
475 const Descriptors& descriptors) {
476 // TODO(damienv): check there is no mismatch if the entry already exists.
477 DVLOG(1) << "RegisterPes:"
478 << " pes_pid=" << pes_pid
479 << " stream_type=" << std::hex << stream_type << std::dec;
480 auto it = pids_.find(pes_pid);
481 if (it != pids_.end())
482 return;
483
484 // Create a stream parser corresponding to the stream type.
485 bool is_audio = true;
486 std::unique_ptr<EsParser> es_parser;
487
488 switch (stream_type) {
489 case kStreamTypeAVC:
490 is_audio = false;
491 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
492 if (ShouldForceEncryptedParser()) {
493 es_parser =
494 CreateEncryptedH264Parser(pes_pid, true /* emit_clear_buffers */);
495 break;
496 }
497 #endif
498 es_parser = CreateH264Parser(pes_pid);
499 break;
500
501 case kStreamTypeAAC:
502 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
503 if (ShouldForceEncryptedParser()) {
504 es_parser =
505 CreateEncryptedAacParser(pes_pid, true /* emit_clear_buffers */);
506 break;
507 }
508 #endif
509 es_parser = CreateAacParser(pes_pid);
510 break;
511
512 case kStreamTypeMpeg1Audio:
513 case kStreamTypeMpeg2Audio:
514 es_parser = CreateMpeg1AudioParser(pes_pid);
515 break;
516
517 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
518 case kStreamTypeAVCWithSampleAES:
519 if (descriptors.HasPrivateDataIndicator(
520 kSampleAESPrivateDataIndicatorAVC)) {
521 is_audio = false;
522 es_parser =
523 CreateEncryptedH264Parser(pes_pid, false /* emit_clear_buffers */);
524 } else {
525 VLOG(2) << "HLS: stream_type in PMT indicates AVC with Sample-AES, but "
526 << "corresponding private data indicator is not present.";
527 }
528 break;
529
530 case kStreamTypeAACWithSampleAES:
531 if (descriptors.HasPrivateDataIndicator(
532 kSampleAESPrivateDataIndicatorAAC)) {
533 es_parser =
534 CreateEncryptedAacParser(pes_pid, false /* emit_clear_buffers */);
535 } else {
536 VLOG(2) << "HLS: stream_type in PMT indicates AAC with Sample-AES, but "
537 << "corresponding private data indicator is not present.";
538 }
539 break;
540 #endif
541
542 default:
543 // Unknown stream_type, so can't create a parser. Logged below.
544 break;
545 }
546
547 if (!es_parser) {
548 VLOG(1) << "Parser could not be created for stream_type: " << stream_type;
549 return;
550 }
551
552 // Create the PES state here.
553 DVLOG(1) << "Create a new PES state";
554 auto pes_section_parser = std::make_unique<TsSectionPes>(
555 std::move(es_parser), ×tamp_unroller_);
556 PidState::PidType pid_type =
557 is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
558 auto pes_pid_state = std::make_unique<PidState>(
559 pes_pid, pid_type, std::move(pes_section_parser));
560 pids_.insert(std::make_pair(pes_pid, std::move(pes_pid_state)));
561
562 // A new PES pid has been added, the PID filter might change.
563 UpdatePidFilter();
564 }
565
UpdatePidFilter()566 void Mp2tStreamParser::UpdatePidFilter() {
567 // Applies the HLS rule to select the default audio/video PIDs:
568 // select the audio/video streams with the lowest PID.
569 // TODO(damienv): this can be changed when the StreamParser interface
570 // supports multiple audio/video streams.
571 auto lowest_audio_pid = pids_.end();
572 auto lowest_video_pid = pids_.end();
573 for (auto it = pids_.begin(); it != pids_.end(); ++it) {
574 int pid = it->first;
575 PidState* pid_state = it->second.get();
576 if (pid_state->pid_type() == PidState::kPidAudioPes &&
577 (lowest_audio_pid == pids_.end() || pid < lowest_audio_pid->first))
578 lowest_audio_pid = it;
579 if (pid_state->pid_type() == PidState::kPidVideoPes &&
580 (lowest_video_pid == pids_.end() || pid < lowest_video_pid->first))
581 lowest_video_pid = it;
582 }
583
584 // Enable both the lowest audio and video PIDs.
585 if (lowest_audio_pid != pids_.end()) {
586 DVLOG(1) << "Enable audio pid: " << lowest_audio_pid->first;
587 lowest_audio_pid->second->Enable();
588 selected_audio_pid_ = lowest_audio_pid->first;
589 }
590 if (lowest_video_pid != pids_.end()) {
591 DVLOG(1) << "Enable video pid: " << lowest_video_pid->first;
592 lowest_video_pid->second->Enable();
593 selected_video_pid_ = lowest_video_pid->first;
594 }
595
596 // Disable all the other audio and video PIDs.
597 for (auto it = pids_.begin(); it != pids_.end(); ++it) {
598 PidState* pid_state = it->second.get();
599 if (it != lowest_audio_pid && it != lowest_video_pid &&
600 (pid_state->pid_type() == PidState::kPidAudioPes ||
601 pid_state->pid_type() == PidState::kPidVideoPes))
602 pid_state->Disable();
603 }
604 }
605
OnVideoConfigChanged(int pes_pid,const VideoDecoderConfig & video_decoder_config)606 void Mp2tStreamParser::OnVideoConfigChanged(
607 int pes_pid,
608 const VideoDecoderConfig& video_decoder_config) {
609 DVLOG(1) << "OnVideoConfigChanged for pid=" << pes_pid;
610 DCHECK_EQ(pes_pid, selected_video_pid_);
611 DCHECK(video_decoder_config.IsValidConfig());
612
613 if (!buffer_queue_chain_.empty() &&
614 !buffer_queue_chain_.back().video_config.IsValidConfig()) {
615 // No video has been received so far, can reuse the existing video queue.
616 DCHECK(buffer_queue_chain_.back().video_queue.empty());
617 buffer_queue_chain_.back().video_config = video_decoder_config;
618 } else {
619 // Create a new entry in |buffer_queue_chain_| with the updated configs.
620 BufferQueueWithConfig buffer_queue_with_config(
621 false,
622 buffer_queue_chain_.empty()
623 ? AudioDecoderConfig() : buffer_queue_chain_.back().audio_config,
624 video_decoder_config);
625 buffer_queue_chain_.push_back(buffer_queue_with_config);
626 }
627
628 // Replace any non valid config with the 1st valid entry.
629 // This might happen if there was no available config before.
630 for (std::list<BufferQueueWithConfig>::iterator it =
631 buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) {
632 if (it->video_config.IsValidConfig())
633 break;
634 it->video_config = video_decoder_config;
635 }
636 }
637
OnAudioConfigChanged(int pes_pid,const AudioDecoderConfig & audio_decoder_config)638 void Mp2tStreamParser::OnAudioConfigChanged(
639 int pes_pid,
640 const AudioDecoderConfig& audio_decoder_config) {
641 DVLOG(1) << "OnAudioConfigChanged for pid=" << pes_pid;
642 DCHECK_EQ(pes_pid, selected_audio_pid_);
643 DCHECK(audio_decoder_config.IsValidConfig());
644
645 if (!buffer_queue_chain_.empty() &&
646 !buffer_queue_chain_.back().audio_config.IsValidConfig()) {
647 // No audio has been received so far, can reuse the existing audio queue.
648 DCHECK(buffer_queue_chain_.back().audio_queue.empty());
649 buffer_queue_chain_.back().audio_config = audio_decoder_config;
650 } else {
651 // Create a new entry in |buffer_queue_chain_| with the updated configs.
652 BufferQueueWithConfig buffer_queue_with_config(
653 false,
654 audio_decoder_config,
655 buffer_queue_chain_.empty()
656 ? VideoDecoderConfig() : buffer_queue_chain_.back().video_config);
657 buffer_queue_chain_.push_back(buffer_queue_with_config);
658 }
659
660 // Replace any non valid config with the 1st valid entry.
661 // This might happen if there was no available config before.
662 for (std::list<BufferQueueWithConfig>::iterator it =
663 buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) {
664 if (it->audio_config.IsValidConfig())
665 break;
666 it->audio_config = audio_decoder_config;
667 }
668 }
669
GenerateMediaTrackInfo(const AudioDecoderConfig & audio_config,const VideoDecoderConfig & video_config)670 std::unique_ptr<MediaTracks> GenerateMediaTrackInfo(
671 const AudioDecoderConfig& audio_config,
672 const VideoDecoderConfig& video_config) {
673 auto media_tracks = std::make_unique<MediaTracks>();
674 // TODO(servolk): Implement proper sourcing of media track info as described
675 // in crbug.com/590085
676 if (audio_config.IsValidConfig()) {
677 media_tracks->AddAudioTrack(audio_config, kMp2tAudioTrackId,
678 MediaTrack::Kind("main"), MediaTrack::Label(""),
679 MediaTrack::Language(""));
680 }
681 if (video_config.IsValidConfig()) {
682 media_tracks->AddVideoTrack(video_config, kMp2tVideoTrackId,
683 MediaTrack::Kind("main"), MediaTrack::Label(""),
684 MediaTrack::Language(""));
685 }
686 return media_tracks;
687 }
688
FinishInitializationIfNeeded()689 bool Mp2tStreamParser::FinishInitializationIfNeeded() {
690 // Nothing to be done if already initialized.
691 if (is_initialized_)
692 return true;
693
694 // Wait for more data to come to finish initialization.
695 if (buffer_queue_chain_.empty())
696 return true;
697
698 // Wait for more data to come if one of the config is not available.
699 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
700 if (selected_audio_pid_ > 0 &&
701 !queue_with_config.audio_config.IsValidConfig())
702 return true;
703 if (selected_video_pid_ > 0 &&
704 !queue_with_config.video_config.IsValidConfig())
705 return true;
706
707 // Pass the config before invoking the initialization callback.
708 std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
709 queue_with_config.audio_config, queue_with_config.video_config);
710 RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
711 queue_with_config.is_config_sent = true;
712
713 // For Mpeg2 TS, the duration is not known.
714 DVLOG(1) << "Mpeg2TS stream parser initialization done";
715
716 // TODO(wolenetz): If possible, detect and report track counts by type more
717 // accurately here. Currently, capped at max 1 each for audio and video, with
718 // assumption of 0 text tracks.
719 InitParameters params(kInfiniteDuration);
720 params.detected_audio_track_count =
721 queue_with_config.audio_config.IsValidConfig() ? 1 : 0;
722 params.detected_video_track_count =
723 queue_with_config.video_config.IsValidConfig() ? 1 : 0;
724 std::move(init_cb_).Run(params);
725 is_initialized_ = true;
726
727 return true;
728 }
729
OnEmitAudioBuffer(int pes_pid,scoped_refptr<StreamParserBuffer> stream_parser_buffer)730 void Mp2tStreamParser::OnEmitAudioBuffer(
731 int pes_pid,
732 scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
733 DCHECK_EQ(pes_pid, selected_audio_pid_);
734
735 DVLOG(LOG_LEVEL_ES)
736 << "OnEmitAudioBuffer: "
737 << " size="
738 << stream_parser_buffer->data_size()
739 << " dts="
740 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
741 << " pts="
742 << stream_parser_buffer->timestamp().InMilliseconds()
743 << " dur="
744 << stream_parser_buffer->duration().InMilliseconds();
745
746 // Ignore the incoming buffer if it is not associated with any config.
747 if (buffer_queue_chain_.empty()) {
748 LOG(ERROR) << "Cannot provide buffers before configs";
749 return;
750 }
751
752 buffer_queue_chain_.back().audio_queue.push_back(stream_parser_buffer);
753 }
754
OnEmitVideoBuffer(int pes_pid,scoped_refptr<StreamParserBuffer> stream_parser_buffer)755 void Mp2tStreamParser::OnEmitVideoBuffer(
756 int pes_pid,
757 scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
758 DCHECK_EQ(pes_pid, selected_video_pid_);
759
760 DVLOG(LOG_LEVEL_ES)
761 << "OnEmitVideoBuffer"
762 << " size="
763 << stream_parser_buffer->data_size()
764 << " dts="
765 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
766 << " pts="
767 << stream_parser_buffer->timestamp().InMilliseconds()
768 << " dur="
769 << stream_parser_buffer->duration().InMilliseconds()
770 << " is_key_frame="
771 << stream_parser_buffer->is_key_frame();
772
773 // Ignore the incoming buffer if it is not associated with any config.
774 if (buffer_queue_chain_.empty()) {
775 NOTREACHED() << "Cannot provide buffers before configs";
776 return;
777 }
778
779 buffer_queue_chain_.back().video_queue.push_back(stream_parser_buffer);
780 }
781
EmitRemainingBuffers()782 bool Mp2tStreamParser::EmitRemainingBuffers() {
783 DVLOG(LOG_LEVEL_ES) << "Mp2tStreamParser::EmitRemainingBuffers";
784
785 // No buffer should be sent until fully initialized.
786 if (!is_initialized_)
787 return true;
788
789 if (buffer_queue_chain_.empty())
790 return true;
791
792 // Keep track of the last audio and video config sent.
793 AudioDecoderConfig last_audio_config =
794 buffer_queue_chain_.back().audio_config;
795 VideoDecoderConfig last_video_config =
796 buffer_queue_chain_.back().video_config;
797
798 // Do not have all the configs, need more data.
799 if (selected_audio_pid_ >= 0 && !last_audio_config.IsValidConfig())
800 return true;
801 if (selected_video_pid_ >= 0 && !last_video_config.IsValidConfig())
802 return true;
803
804 // Buffer emission.
805 while (!buffer_queue_chain_.empty()) {
806 // Start a segment if needed.
807 if (!segment_started_) {
808 DVLOG(1) << "Starting a new segment";
809 segment_started_ = true;
810 new_segment_cb_.Run();
811 }
812
813 // Update the audio and video config if needed.
814 BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
815 if (!queue_with_config.is_config_sent) {
816 std::unique_ptr<MediaTracks> media_tracks = GenerateMediaTrackInfo(
817 queue_with_config.audio_config, queue_with_config.video_config);
818 if (!config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()))
819 return false;
820 queue_with_config.is_config_sent = true;
821 }
822
823 // Add buffers.
824 BufferQueueMap buffer_queue_map;
825 if (!queue_with_config.audio_queue.empty())
826 buffer_queue_map.insert(
827 std::make_pair(kMp2tAudioTrackId, queue_with_config.audio_queue));
828 if (!queue_with_config.video_queue.empty())
829 buffer_queue_map.insert(
830 std::make_pair(kMp2tVideoTrackId, queue_with_config.video_queue));
831
832 if (!buffer_queue_map.empty() && !new_buffers_cb_.Run(buffer_queue_map))
833 return false;
834
835 buffer_queue_chain_.pop_front();
836 }
837
838 // Push an empty queue with the last audio/video config
839 // so that buffers with the same config can be added later on.
840 BufferQueueWithConfig queue_with_config(
841 true, last_audio_config, last_video_config);
842 buffer_queue_chain_.push_back(queue_with_config);
843
844 return true;
845 }
846
847 #if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
MakeCatPidState()848 std::unique_ptr<PidState> Mp2tStreamParser::MakeCatPidState() {
849 auto cat_section_parser = std::make_unique<TsSectionCat>(
850 base::BindRepeating(&Mp2tStreamParser::RegisterCencPids,
851 base::Unretained(this)),
852 base::BindRepeating(&Mp2tStreamParser::RegisterEncryptionScheme,
853 base::Unretained(this)));
854 auto cat_pid_state = std::make_unique<PidState>(
855 TsSection::kPidCat, PidState::kPidCat, std::move(cat_section_parser));
856 cat_pid_state->Enable();
857 return cat_pid_state;
858 }
859
UnregisterCat()860 void Mp2tStreamParser::UnregisterCat() {
861 for (auto& pid : pids_) {
862 if (pid.second->pid_type() == PidState::kPidCat) {
863 pids_.erase(pid.first);
864 break;
865 }
866 }
867 }
868
RegisterCencPids(int ca_pid,int pssh_pid)869 void Mp2tStreamParser::RegisterCencPids(int ca_pid, int pssh_pid) {
870 auto ecm_parser = std::make_unique<TsSectionCetsEcm>(base::BindRepeating(
871 &Mp2tStreamParser::RegisterNewKeyIdAndIv, base::Unretained(this)));
872 auto ecm_pid_state = std::make_unique<PidState>(ca_pid, PidState::kPidCetsEcm,
873 std::move(ecm_parser));
874 ecm_pid_state->Enable();
875 pids_.insert(std::make_pair(ca_pid, std::move(ecm_pid_state)));
876
877 auto pssh_parser = std::make_unique<TsSectionCetsPssh>(base::BindRepeating(
878 &Mp2tStreamParser::RegisterPsshBoxes, base::Unretained(this)));
879 auto pssh_pid_state = std::make_unique<PidState>(
880 pssh_pid, PidState::kPidCetsPssh, std::move(pssh_parser));
881 pssh_pid_state->Enable();
882 pids_.insert(std::make_pair(pssh_pid, std::move(pssh_pid_state)));
883 }
884
UnregisterCencPids()885 void Mp2tStreamParser::UnregisterCencPids() {
886 for (auto& pid : pids_) {
887 if (pid.second->pid_type() == PidState::kPidCetsEcm) {
888 pids_.erase(pid.first);
889 break;
890 }
891 }
892 for (auto& pid : pids_) {
893 if (pid.second->pid_type() == PidState::kPidCetsPssh) {
894 pids_.erase(pid.first);
895 break;
896 }
897 }
898 }
899
RegisterEncryptionScheme(EncryptionScheme scheme)900 void Mp2tStreamParser::RegisterEncryptionScheme(EncryptionScheme scheme) {
901 // We only need to record this for the initial decoder config.
902 if (!is_initialized_) {
903 initial_encryption_scheme_ = scheme;
904 }
905 // Reset the DecryptConfig, so that unless and until a CENC-ECM (containing
906 // key id and IV) is seen, media data will be considered unencrypted. This is
907 // similar to the way clear leaders can occur in MP4 containers.
908 decrypt_config_.reset();
909 }
910
RegisterNewKeyIdAndIv(const std::string & key_id,const std::string & iv)911 void Mp2tStreamParser::RegisterNewKeyIdAndIv(const std::string& key_id,
912 const std::string& iv) {
913 if (!iv.empty()) {
914 switch (initial_encryption_scheme_) {
915 case EncryptionScheme::kUnencrypted:
916 decrypt_config_.reset();
917 break;
918 case EncryptionScheme::kCenc:
919 decrypt_config_ = DecryptConfig::CreateCencConfig(key_id, iv, {});
920 break;
921 case EncryptionScheme::kCbcs:
922 decrypt_config_ =
923 DecryptConfig::CreateCbcsConfig(key_id, iv, {}, base::nullopt);
924 break;
925 }
926 }
927 }
928
RegisterPsshBoxes(const std::vector<uint8_t> & init_data)929 void Mp2tStreamParser::RegisterPsshBoxes(
930 const std::vector<uint8_t>& init_data) {
931 encrypted_media_init_data_cb_.Run(EmeInitDataType::CENC, init_data);
932 }
933
934 #endif
935
936 } // namespace mp2t
937 } // namespace media
938