Shaka Packager SDK
webvtt_file_buffer.cc
1 // Copyright 2018 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/webvtt/webvtt_file_buffer.h"
8 
9 #include "packager/base/strings/stringprintf.h"
10 #include "packager/media/base/text_sample.h"
11 #include "packager/media/formats/webvtt/webvtt_timestamp.h"
12 
13 namespace shaka {
14 namespace media {
15 namespace {
16 const char* kHeader = "WEBVTT\n";
17 const int kTsTimescale = 90000;
18 } // namespace
19 
20 WebVttFileBuffer::WebVttFileBuffer(
21  uint32_t transport_stream_timestamp_offset_ms,
22  const std::string& style_region_config)
23  : transport_stream_timestamp_offset_(transport_stream_timestamp_offset_ms *
24  kTsTimescale / 1000),
25  style_region_config_(style_region_config) {
26  // Make sure we start with the same state that we would end up with if
27  // the caller reset our state.
28  Reset();
29 }
30 
31 void WebVttFileBuffer::Reset() {
32  sample_count_ = 0;
33 
34  buffer_.clear();
35  buffer_.append(kHeader);
36  if (transport_stream_timestamp_offset_ > 0) {
37  // https://tools.ietf.org/html/rfc8216#section-3.5 WebVTT.
38  base::StringAppendF(&buffer_,
39  "X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:%d\n",
40  transport_stream_timestamp_offset_);
41  }
42  buffer_.append("\n"); // end of header.
43  if (!style_region_config_.empty()) {
44  buffer_.append(style_region_config_);
45  buffer_.append("\n\n");
46  }
47 }
48 
49 void WebVttFileBuffer::Append(const TextSample& sample) {
50  DCHECK_GT(buffer_.size(), 0u) << "The buffer should at least have a header";
51 
52  sample_count_++;
53 
54  // Ids are optional
55  if (sample.id().length()) {
56  buffer_.append(sample.id());
57  buffer_.append("\n"); // end of id
58  }
59 
60  // Write the times that the sample elapses.
61  buffer_.append(MsToWebVttTimestamp(sample.start_time()));
62  buffer_.append(" --> ");
63  buffer_.append(MsToWebVttTimestamp(sample.EndTime()));
64 
65  // Settings are optional
66  if (sample.settings().length()) {
67  buffer_.append(" ");
68  buffer_.append(sample.settings());
69  }
70  buffer_.append("\n"); // end of time & settings
71 
72  buffer_.append(sample.payload());
73  buffer_.append("\n"); // end of payload
74  buffer_.append("\n"); // end of sample
75 }
76 
77 bool WebVttFileBuffer::WriteTo(File* file) {
78  DCHECK(file);
79  DCHECK_GT(buffer_.size(), 0u) << "The buffer should at least have a header";
80 
81  const int written = file->Write(buffer_.c_str(), buffer_.size());
82  if (written < 0) {
83  return false;
84  }
85 
86  return static_cast<size_t>(written) == buffer_.size();
87 }
88 } // namespace media
89 } // namespace shaka
All the methods that are virtual are virtual for mocking.