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