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 <limits>
10 
11 #include "packager/third_party/libwebm/src/mkvmuxerutil.hpp"
12 #include "packager/third_party/libwebm/src/webmids.hpp"
13 
14 namespace shaka {
15 namespace media {
16 namespace {
17 const mkvmuxer::uint64 kElementIds[] = {
18  mkvmuxer::kMkvInfo, mkvmuxer::kMkvTracks, mkvmuxer::kMkvCluster,
19  mkvmuxer::kMkvCues,
20 };
21 const int kElementIdCount = arraysize(kElementIds);
22 
23 uint64_t MaxSeekEntrySize() {
24  const uint64_t max_entry_payload_size =
25  EbmlElementSize(
26  mkvmuxer::kMkvSeekID,
27  static_cast<mkvmuxer::uint64>(std::numeric_limits<uint32_t>::max())) +
28  EbmlElementSize(mkvmuxer::kMkvSeekPosition,
29  std::numeric_limits<mkvmuxer::uint64>::max());
30  const uint64_t max_entry_size =
31  EbmlMasterElementSize(mkvmuxer::kMkvSeek, max_entry_payload_size) +
32  max_entry_payload_size;
33 
34  return max_entry_size;
35 }
36 } // namespace
37 
38 SeekHead::SeekHead()
39  : cluster_pos_(-1),
40  cues_pos_(-1),
41  info_pos_(-1),
42  tracks_pos_(-1),
43  wrote_void_(false) {}
44 
45 SeekHead::~SeekHead() {}
46 
47 bool SeekHead::Write(mkvmuxer::IMkvWriter* writer) {
48  std::vector<uint64_t> element_sizes;
49  const uint64_t payload_size = GetPayloadSize(&element_sizes);
50 
51  if (payload_size == 0) {
52  return true;
53  }
54 
55  const int64_t start_pos = writer->Position();
56  if (!WriteEbmlMasterElement(writer, mkvmuxer::kMkvSeekHead, payload_size))
57  return false;
58 
59  const int64_t positions[] = {info_pos_, tracks_pos_, cluster_pos_, cues_pos_};
60  for (int i = 0; i < kElementIdCount; ++i) {
61  if (element_sizes[i] == 0)
62  continue;
63 
64  const mkvmuxer::uint64 position =
65  static_cast<mkvmuxer::uint64>(positions[i]);
66  if (!WriteEbmlMasterElement(writer, mkvmuxer::kMkvSeek, element_sizes[i]) ||
67  !WriteEbmlElement(writer, mkvmuxer::kMkvSeekID, kElementIds[i]) ||
68  !WriteEbmlElement(writer, mkvmuxer::kMkvSeekPosition, position))
69  return false;
70  }
71 
72  // If we wrote void before, then fill in the extra with void.
73  if (wrote_void_) {
74  const uint64_t max_payload_size = kElementIdCount * MaxSeekEntrySize();
75  const uint64_t total_void_size =
76  EbmlMasterElementSize(mkvmuxer::kMkvSeekHead, max_payload_size) +
77  max_payload_size;
78 
79  const uint64_t extra_void =
80  total_void_size - (writer->Position() - start_pos);
81  if (!WriteVoidElement(writer, extra_void))
82  return false;
83  }
84 
85  return true;
86 }
87 
88 bool SeekHead::WriteVoid(mkvmuxer::IMkvWriter* writer) {
89  const uint64_t payload_size = kElementIdCount * MaxSeekEntrySize();
90  const uint64_t total_size =
91  EbmlMasterElementSize(mkvmuxer::kMkvSeekHead, payload_size) +
92  payload_size;
93 
94  wrote_void_ = true;
95  const uint64_t written = WriteVoidElement(writer, total_size);
96  if (!written)
97  return false;
98 
99  return true;
100 }
101 
102 uint64_t SeekHead::GetPayloadSize(std::vector<uint64_t>* data) {
103  const int64_t positions[] = {info_pos_, tracks_pos_, cluster_pos_, cues_pos_};
104  uint64_t total_payload_size = 0;
105  data->resize(kElementIdCount);
106  for (int i = 0; i < kElementIdCount; ++i) {
107  if (positions[i] < 0) {
108  (*data)[i] = 0;
109  continue;
110  }
111 
112  const mkvmuxer::uint64 position =
113  static_cast<mkvmuxer::uint64>(positions[i]);
114  (*data)[i] = EbmlElementSize(mkvmuxer::kMkvSeekID, kElementIds[i]) +
115  EbmlElementSize(mkvmuxer::kMkvSeekPosition, position);
116  total_payload_size +=
117  data->at(i) + EbmlMasterElementSize(mkvmuxer::kMkvSeek, data->at(i));
118  }
119 
120  return total_payload_size;
121 }
122 
123 } // namespace media
124 } // namespace shaka
bool WriteVoid(mkvmuxer::IMkvWriter *writer)
Writes a void element large enough to fit the SeekHead.
Definition: seek_head.cc:88
bool Write(mkvmuxer::IMkvWriter *writer)
Definition: seek_head.cc:47