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 <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
17using namespace mkvmuxer;
18
19namespace shaka {
20namespace media {
21namespace {
22
23// Cluster, Cues, Info, Tracks.
24const size_t kElementIdCount = 4u;
25
26uint64_t EbmlMasterElementWithPayloadSize(libwebm::MkvId id,
27 uint64_t payload_size) {
28 return EbmlMasterElementSize(id, payload_size) + payload_size;
29}
30
31uint64_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
44SeekHead::SeekHead()
45 : total_void_size_(EbmlMasterElementWithPayloadSize(
46 libwebm::kMkvSeekHead,
47 kElementIdCount * MaxSeekEntrySize())) {}
48
49SeekHead::~SeekHead() {}
50
51bool 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
84bool 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
92std::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.