Shaka Packager SDK
seek_head.cc
1 // Copyright 2015 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/webm/seek_head.h>
8 
9 #include <algorithm>
10 #include <limits>
11 
12 #include <absl/log/check.h>
13 #include <absl/log/log.h>
14 #include <common/webmids.h>
15 #include <mkvmuxer/mkvmuxerutil.h>
16 
17 using namespace mkvmuxer;
18 
19 namespace shaka {
20 namespace media {
21 namespace {
22 
23 // Cluster, Cues, Info, Tracks.
24 const size_t kElementIdCount = 4u;
25 
26 uint64_t EbmlMasterElementWithPayloadSize(libwebm::MkvId id,
27  uint64_t payload_size) {
28  return EbmlMasterElementSize(id, payload_size) + payload_size;
29 }
30 
31 uint64_t MaxSeekEntrySize() {
32  const uint64_t max_entry_payload_size =
33  EbmlElementSize(
34  libwebm::kMkvSeekID,
35  static_cast<mkvmuxer::uint64>(std::numeric_limits<uint32_t>::max())) +
36  EbmlElementSize(libwebm::kMkvSeekPosition,
37  std::numeric_limits<mkvmuxer::uint64>::max());
38  return EbmlMasterElementWithPayloadSize(libwebm::kMkvSeek,
39  max_entry_payload_size);
40 }
41 
42 } // namespace
43 
44 SeekHead::SeekHead()
45  : total_void_size_(EbmlMasterElementWithPayloadSize(
46  libwebm::kMkvSeekHead,
47  kElementIdCount * MaxSeekEntrySize())) {}
48 
49 SeekHead::~SeekHead() {}
50 
51 bool SeekHead::Write(mkvmuxer::IMkvWriter* writer) {
52  std::vector<SeekElement> seek_elements = CreateSeekElements();
53  if (seek_elements.empty())
54  return true;
55 
56  uint64_t payload_size = 0;
57  for (const SeekHead::SeekElement& seek_element : seek_elements) {
58  payload_size +=
59  EbmlMasterElementWithPayloadSize(libwebm::kMkvSeek, seek_element.size);
60  }
61 
62  const int64_t start_pos = writer->Position();
63  if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeekHead, payload_size))
64  return false;
65 
66  for (const SeekHead::SeekElement& element : seek_elements) {
67  if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeek, element.size) ||
68  !WriteEbmlElement(writer, libwebm::kMkvSeekID, element.id) ||
69  !WriteEbmlElement(writer, libwebm::kMkvSeekPosition, element.position))
70  return false;
71  }
72 
73  // If we wrote void before, then fill in the extra with void.
74  if (wrote_void_) {
75  const uint64_t extra_void =
76  total_void_size_ - (writer->Position() - start_pos);
77  if (!WriteVoidElement(writer, extra_void))
78  return false;
79  }
80 
81  return true;
82 }
83 
84 bool SeekHead::WriteVoid(mkvmuxer::IMkvWriter* writer) {
85  const uint64_t written = WriteVoidElement(writer, total_void_size_);
86  if (!written)
87  return false;
88  wrote_void_ = true;
89  return true;
90 }
91 
92 std::vector<SeekHead::SeekElement> SeekHead::CreateSeekElements() {
93  std::vector<SeekHead::SeekElement> seek_elements;
94  if (info_pos_ != 0)
95  seek_elements.emplace_back(libwebm::kMkvInfo, info_pos_);
96  if (tracks_pos_ != 0)
97  seek_elements.emplace_back(libwebm::kMkvTracks, tracks_pos_);
98  if (cues_pos_ != 0)
99  seek_elements.emplace_back(libwebm::kMkvCues, cues_pos_);
100  if (cluster_pos_ != 0)
101  seek_elements.emplace_back(libwebm::kMkvCluster, cluster_pos_);
102  DCHECK_LE(seek_elements.size(), kElementIdCount);
103 
104  std::sort(seek_elements.begin(), seek_elements.end(),
105  [](const SeekHead::SeekElement& left,
106  const SeekHead::SeekElement& right) {
107  return left.position < right.position;
108  });
109  for (SeekHead::SeekElement& element : seek_elements) {
110  element.size = EbmlElementSize(libwebm::kMkvSeekID, element.id) +
111  EbmlElementSize(libwebm::kMkvSeekPosition, element.position);
112  }
113  return seek_elements;
114 }
115 
116 } // namespace media
117 } // namespace shaka
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66