RDK Documentation (Open Sourced RDK Components)
WebvttSubtecDevParser.cpp
1 /*
2  * If not stated otherwise in this file or this component's license file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2020 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 #include "WebvttSubtecDevParser.hpp"
21 
22 std::string getTtmlHeader()
23 {
24  return R"str(
25  <head>
26  <metadata xmlns:ttm="http://www.w3.org/ns/ttml#metadata">
27  <ttm:title>WebVTT to TTML template</ttm:title>
28  </metadata>
29  <styling xmlns:tts="http://www.w3.org/ns/ttml#styling">
30  <!-- s1 specifies default color, font, and text alignment -->
31  <style xml:id="s1"
32  tts:color="white"
33  tts:fontFamily="XFINITY Sans Med"
34  tts:fontSize="100%"
35  tts:textAlign="start"
36  />
37  </styling>
38  <layout xmlns:tts="http://www.w3.org/ns/ttml#styling">
39  <region xml:id="subtitleArea"
40  style="s1"
41  tts:origin="10% 70%"
42  tts:extent="80% 30%"
43  tts:backgroundColor="#000000FF"
44  tts:displayAlign="after"
45  />
46  </layout>
47  </head>)str";
48 }
49 
50 void stripHtmlTags(std::string& str)
51 {
52  size_t startpos = std::string::npos, endpos = std::string::npos;
53 
54  do
55  {
56  startpos = str.find_first_of('<');
57  if (startpos != std::string::npos)
58  {
59  endpos = str.find_first_of('>');
60  if (endpos != std::string::npos)
61  {
62  str.erase(startpos, endpos - startpos + 1);
63  continue;
64  }
65  }
66  break;
67  } while (true);
68 }
69 
70 std::string convertCueToTtmlString(int id, VTTCue *cue, double startTime)
71 {
72  std::ostringstream ss;
73  std::string text;
74 
75  if (NULL != cue)
76  {
77  std::istringstream is(cue->mText);
78  bool first = true; //CID:158977 - Reverse_inull
79  ss << "<p xml:id=\"subtitle" << id << "\" begin=\"" << startTime / 1000.0 << "s\" end=\"" << (startTime + cue->mDuration) / 1000.0 << "s\" style=\"s1\">";
80  while (std::getline(is, text))
81  {
82  if (!text.empty())
83  {
84  if (!first)
85  ss << "\n";
86  stripHtmlTags(text);
87  ss << text;
88  first = false;
89  }
90  }
91  ss << "</p>\n";
92  }
93 
94  AAMPLOG_TRACE(" %s\n", ss.str().c_str());
95 
96  return ss.str();
97 }
98 
99 
100 WebVTTSubtecDevParser::WebVTTSubtecDevParser(AampLogManager *logObj, PrivateInstanceAAMP *aamp, SubtitleMimeType type) : WebVTTParser(logObj, aamp, type), m_channel(nullptr)
101 {
102  m_channel = SubtecChannel::SubtecChannelFactory(SubtecChannel::ChannelType::TTML);
103  if (!m_channel->InitComms())
104  {
105  AAMPLOG_INFO("Init failed - subtitle parsing disabled");
106  throw std::runtime_error("PacketSender init failed");
107  }
108  m_channel->SendResetAllPacket();
109  int width = 1920, height = 1080;
110 
111  mAamp->GetPlayerVideoSize(width, height);
112  m_channel->SendSelectionPacket(width, height);
113  m_channel->SendMutePacket();
114 }
115 
116 bool WebVTTSubtecDevParser::processData(char *buffer, size_t bufferLen, double position, double duration)
117 {
118  bool ret;
119 
120  if (mReset) mReset = false;
121  ret = WebVTTParser::processData(buffer, bufferLen, position, duration);
122 
123  if (ret) sendCueData();
124 
125  return ret;
126 }
127 
128 void WebVTTSubtecDevParser::sendCueData()
129 {
130  std::string ttml = getVttAsTtml();
131  std::vector<uint8_t> data(ttml.begin(), ttml.end());
132 
133  m_channel->SendDataPacket(std::move(data), 0);
134 }
135 
136 void WebVTTSubtecDevParser::reset()
137 {
138  if (!mReset)
139  {
140  m_channel->SendResetChannelPacket();
141  }
142  WebVTTParser::reset();
143 }
144 
145 void WebVTTSubtecDevParser::updateTimestamp(unsigned long long positionMs)
146 {
147  AAMPLOG_TRACE("timestamp: %lldms", positionMs );
148  m_channel->SendTimestampPacket(positionMs);
149 }
150 
151 bool WebVTTSubtecDevParser::init(double startPosSeconds, unsigned long long basePTS)
152 {
153  bool ret = true;
154  mVttQueueIdleTaskId = -1;
155 
156  ret = WebVTTParser::init(startPosSeconds, 0);
158 
159  m_channel->SendTimestampPacket(static_cast<uint64_t>(basePTS));
160 
161 
162  return ret;
163 }
164 
165 void WebVTTSubtecDevParser::mute(bool mute)
166 {
167  if (mute)
168  m_channel->SendMutePacket();
169  else
170  m_channel->SendUnmutePacket();
171 }
172 
173 void WebVTTSubtecDevParser::pause(bool pause)
174 {
175  if (pause)
176  m_channel->SendPausePacket();
177  else
178  m_channel->SendResumePacket();
179 }
180 
181 /**
182  * @}
183  */
184 std::string WebVTTSubtecDevParser::getVttAsTtml()
185 {
186  pthread_mutex_lock(&mVttQueueMutex);
187  std::string ss;
188  int counter = 0;
189 
190  ss += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
191  ss += "<tt xmlns=\"http://www.w3.org/ns/ttml\">\n";
192  ss += getTtmlHeader();
193  ss += "<body region=\"subtitleArea\">\n";
194  ss += "<div>\n";
195 
196  if (!mVttQueue.empty())
197  {
198  while(mVttQueue.size() > 0)
199  {
200  VTTCue *cue = mVttQueue.front();
201  mVttQueue.pop();
202  AAMPLOG_TRACE("mStart %.3f mStartPos %.3f mPtsOffset %lld", cue->mStart, mStartPos, mPtsOffset);
203  int start = cue->mStart;
204  if (start > 0)
205  {
206  ss += convertCueToTtmlString(counter++, cue, start);
207  }
208  else
209  {
210  AAMPLOG_TRACE("queue size %zu cue start %.3f", mVttQueue.size(), cue->mStart);
211  }
212  SAFE_DELETE(cue);
213  }
214  }
215  else
216  {
217  AAMPLOG_TRACE("cue queue empty");
218  AAMPLOG_INFO("Outgoing WebVTT file with start pos %.3fs is EMPTY", mStartPos / 1000.0);
219  }
220 
221  ss += "</div>\n";
222  ss += "</body>\n";
223  ss += "</tt>\n";
224 
225 
226  pthread_mutex_unlock(&mVttQueueMutex);
227 
228  return ss;
229 }
AampLogManager
AampLogManager Class.
Definition: AampLogManager.h:150
WebVTTParser::mVttQueueMutex
pthread_mutex_t mVttQueueMutex
Definition: webvttParser.h:84
WebVTTParser::mReset
bool mReset
Definition: webvttParser.h:78
WebVTTParser::mPtsOffset
unsigned long long mPtsOffset
Definition: webvttParser.h:75
SubtitleMimeType
SubtitleMimeType
Subtitle data types.
Definition: subtitleParser.h:37
VTTCue
Data structure to hold a VTT cue.
Definition: vttCue.h:39
WebVTTParser::mStartPos
double mStartPos
Definition: webvttParser.h:76
PrivateInstanceAAMP::GetPlayerVideoSize
void GetPlayerVideoSize(int &w, int &h)
Get player video size.
Definition: priv_aamp.cpp:8198
AAMPLOG_TRACE
#define AAMPLOG_TRACE(FORMAT,...)
AAMP logging defines, this can be enabled through setLogLevel() as per the need.
Definition: AampLogManager.h:83
PrivateInstanceAAMP
Class representing the AAMP player's private instance, which is not exposed to outside world.
Definition: priv_aamp.h:640
WebVTTParser::mVttQueueIdleTaskId
guint mVttQueueIdleTaskId
Definition: webvttParser.h:83
WebVTTParser::mVttQueue
std::queue< VTTCue * > mVttQueue
Definition: webvttParser.h:82
WebVTTParser
WebVTT parser class.
Definition: webvttParser.h:56