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), &timestamp_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