Shaka Packager SDK
es_parser_dvb.cc
1 // Copyright 2020 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/formats/mp2t/es_parser_dvb.h>
8 
9 #include <packager/media/base/bit_reader.h>
10 #include <packager/media/base/text_stream_info.h>
11 #include <packager/media/base/timestamp.h>
12 #include <packager/media/formats/mp2t/mp2t_common.h>
13 
14 namespace shaka {
15 namespace media {
16 namespace mp2t {
17 
18 namespace {
19 
20 bool ParseSubtitlingDescriptor(
21  const uint8_t* descriptor,
22  size_t size,
23  std::unordered_map<uint16_t, std::string>* langs) {
24  // See ETSI EN 300 468 Section 6.2.41.
25  BitReader reader(descriptor, size);
26  size_t data_size;
27  RCHECK(reader.SkipBits(8)); // descriptor_tag
28  RCHECK(reader.ReadBits(8, &data_size));
29  RCHECK(data_size + 2 <= size);
30  for (size_t i = 0; i < data_size; i += 8) {
31  uint32_t lang_code;
32  uint16_t page;
33  RCHECK(reader.ReadBits(24, &lang_code));
34  RCHECK(reader.SkipBits(8)); // subtitling_type
35  RCHECK(reader.ReadBits(16, &page));
36  RCHECK(reader.SkipBits(16)); // ancillary_page_id
37 
38  // The lang code is a ISO 639-2 code coded in Latin-1.
39  std::string lang(3, '\0');
40  lang[0] = (lang_code >> 16) & 0xff;
41  lang[1] = (lang_code >> 8) & 0xff;
42  lang[2] = (lang_code >> 0) & 0xff;
43  langs->emplace(page, std::move(lang));
44  }
45  return true;
46 }
47 
48 } // namespace
49 
50 EsParserDvb::EsParserDvb(uint32_t pid,
51  const NewStreamInfoCB& new_stream_info_cb,
52  const EmitTextSampleCB& emit_sample_cb,
53  const uint8_t* descriptor,
54  size_t descriptor_length)
55  : EsParser(pid),
56  new_stream_info_cb_(new_stream_info_cb),
57  emit_sample_cb_(emit_sample_cb) {
58  if (!ParseSubtitlingDescriptor(descriptor, descriptor_length, &languages_)) {
59  LOG(WARNING) << "Error parsing subtitling descriptor";
60  }
61 }
62 
63 EsParserDvb::~EsParserDvb() {}
64 
65 bool EsParserDvb::Parse(const uint8_t* buf,
66  int size,
67  int64_t pts,
68  int64_t dts) {
69  if (!sent_info_) {
70  sent_info_ = true;
71  std::shared_ptr<TextStreamInfo> info = std::make_shared<TextStreamInfo>(
72  pid(), kMpeg2Timescale, kInfiniteDuration, kCodecText,
73  /* codec_string= */ "", /* codec_config= */ "", /* width= */ 0,
74  /* height= */ 0, /* language= */ "");
75  for (const auto& pair : languages_) {
76  info->AddSubStream(pair.first, {pair.second});
77  }
78 
79  new_stream_info_cb_(info);
80  }
81 
82  // TODO: Handle buffering and multiple reads? All content so far has been
83  // a whole segment, so it may not be needed.
84  return ParseInternal(buf, size, pts);
85 }
86 
87 bool EsParserDvb::Flush() {
88  for (auto& pair : parsers_) {
89  std::vector<std::shared_ptr<TextSample>> samples;
90  RCHECK(pair.second.Flush(&samples));
91 
92  for (auto sample : samples) {
93  sample->set_sub_stream_index(pair.first);
94  emit_sample_cb_(sample);
95  }
96  }
97  return true;
98 }
99 
100 void EsParserDvb::Reset() {
101  parsers_.clear();
102 }
103 
104 bool EsParserDvb::ParseInternal(const uint8_t* data, size_t size, int64_t pts) {
105  // See EN 300 743 Table 3.
106  BitReader reader(data, size);
107  int data_identifier;
108  int subtitle_stream_id;
109  RCHECK(reader.ReadBits(8, &data_identifier));
110  RCHECK(reader.ReadBits(8, &subtitle_stream_id));
111  RCHECK(data_identifier == 0x20);
112  RCHECK(subtitle_stream_id == 0);
113 
114  int temp;
115  while (reader.ReadBits(8, &temp) && temp == 0xf) {
116  DvbSubSegmentType segment_type;
117  uint16_t page_id;
118  size_t segment_length;
119  RCHECK(reader.ReadBits(8, &segment_type));
120  RCHECK(reader.ReadBits(16, &page_id));
121  RCHECK(reader.ReadBits(16, &segment_length));
122  RCHECK(reader.bits_available() > segment_length * 8);
123 
124  const uint8_t* payload = data + (size - reader.bits_available() / 8);
125  std::vector<std::shared_ptr<TextSample>> samples;
126  RCHECK(parsers_[page_id].Parse(segment_type, pts, payload, segment_length,
127  &samples));
128  for (auto sample : samples) {
129  sample->set_sub_stream_index(page_id);
130  emit_sample_cb_(sample);
131  }
132 
133  RCHECK(reader.SkipBytes(segment_length));
134  }
135  return temp == 0xff;
136 }
137 
138 } // namespace mp2t
139 } // namespace media
140 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66