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