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