diff --git a/DEPS b/DEPS
index dc917af8b4..685ea75291 100644
--- a/DEPS
+++ b/DEPS
@@ -50,7 +50,7 @@ deps = {
Var("chromium_git") + "/chromium/deps/icu@ef5c735307d0f86c7622f69620994c9468beba99",
"src/packager/third_party/libwebm/src":
- Var("chromium_git") + "/webm/libwebm@1ad314e297a43966605c4ef23a6442bb58e1d9be",
+ Var("chromium_git") + "/webm/libwebm@d6af52a1e688fade2e2d22b6d9b0c82f10d38e0b",
"src/packager/third_party/modp_b64":
Var("chromium_git") + "/chromium/src/third_party/modp_b64@aae60754fa997799e8037f5e8ca1f56d58df763d", #405651
diff --git a/packager/app/test/testdata/bear-320x240-opus-golden.webm b/packager/app/test/testdata/bear-320x240-opus-golden.webm
index 3dc7e7e532..ed155bc28b 100644
Binary files a/packager/app/test/testdata/bear-320x240-opus-golden.webm and b/packager/app/test/testdata/bear-320x240-opus-golden.webm differ
diff --git a/packager/app/test/testdata/bear-320x240-vorbis-golden.webm b/packager/app/test/testdata/bear-320x240-vorbis-golden.webm
index 57b0b1e605..b764a53aa8 100644
Binary files a/packager/app/test/testdata/bear-320x240-vorbis-golden.webm and b/packager/app/test/testdata/bear-320x240-vorbis-golden.webm differ
diff --git a/packager/app/test/testdata/bear-320x240-vorbis-webm-golden.mpd b/packager/app/test/testdata/bear-320x240-vorbis-webm-golden.mpd
index d2d2096478..69dfdd1dc1 100644
--- a/packager/app/test/testdata/bear-320x240-vorbis-webm-golden.mpd
+++ b/packager/app/test/testdata/bear-320x240-vorbis-webm-golden.mpd
@@ -6,7 +6,7 @@
output_audio.webm
-
+
diff --git a/packager/app/test/testdata/bear-320x240-vp9-golden.webm b/packager/app/test/testdata/bear-320x240-vp9-golden.webm
index 3b18d7666f..0618a8009c 100644
Binary files a/packager/app/test/testdata/bear-320x240-vp9-golden.webm and b/packager/app/test/testdata/bear-320x240-vp9-golden.webm differ
diff --git a/packager/app/test/testdata/bear-320x240-vp9-opus-webm-golden.mpd b/packager/app/test/testdata/bear-320x240-vp9-opus-webm-golden.mpd
index 3efd0d4cfd..39376b4a83 100644
--- a/packager/app/test/testdata/bear-320x240-vp9-opus-webm-golden.mpd
+++ b/packager/app/test/testdata/bear-320x240-vp9-opus-webm-golden.mpd
@@ -6,15 +6,15 @@
output_audio.webm
-
+
-
+
output_video.webm
-
+
diff --git a/packager/app/test/testdata/bear-640x360-vp8-cenc-golden.webm b/packager/app/test/testdata/bear-640x360-vp8-cenc-golden.webm
index 6a90df191b..91d57aa5fd 100644
Binary files a/packager/app/test/testdata/bear-640x360-vp8-cenc-golden.webm and b/packager/app/test/testdata/bear-640x360-vp8-cenc-golden.webm differ
diff --git a/packager/app/test/testdata/bear-640x360-vp8-cenc-webm-golden.mpd b/packager/app/test/testdata/bear-640x360-vp8-cenc-webm-golden.mpd
index cca18189b7..d2f0a15b71 100644
--- a/packager/app/test/testdata/bear-640x360-vp8-cenc-webm-golden.mpd
+++ b/packager/app/test/testdata/bear-640x360-vp8-cenc-webm-golden.mpd
@@ -8,7 +8,7 @@
AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==
output_video.webm
-
+
diff --git a/packager/app/test/testdata/bear-640x360-vp8-golden.webm b/packager/app/test/testdata/bear-640x360-vp8-golden.webm
index d9f9436ac9..5fa81b7d88 100644
Binary files a/packager/app/test/testdata/bear-640x360-vp8-golden.webm and b/packager/app/test/testdata/bear-640x360-vp8-golden.webm differ
diff --git a/packager/app/test/testdata/bear-640x360-vp8-webm-golden.mpd b/packager/app/test/testdata/bear-640x360-vp8-webm-golden.mpd
index c108e7f2b2..68a6b1d3ec 100644
--- a/packager/app/test/testdata/bear-640x360-vp8-webm-golden.mpd
+++ b/packager/app/test/testdata/bear-640x360-vp8-webm-golden.mpd
@@ -3,9 +3,9 @@
-
+
output_video.webm
-
+
diff --git a/packager/app/test/testdata/bear-640x360-vp9-altref-dec-golden.webm b/packager/app/test/testdata/bear-640x360-vp9-altref-dec-golden.webm
index d5df056ea4..ae1c97b480 100644
Binary files a/packager/app/test/testdata/bear-640x360-vp9-altref-dec-golden.webm and b/packager/app/test/testdata/bear-640x360-vp9-altref-dec-golden.webm differ
diff --git a/packager/app/test/testdata/bear-640x360-vp9-altref-enc-golden.webm b/packager/app/test/testdata/bear-640x360-vp9-altref-enc-golden.webm
index 06b7a34567..6493afa80c 100644
Binary files a/packager/app/test/testdata/bear-640x360-vp9-altref-enc-golden.webm and b/packager/app/test/testdata/bear-640x360-vp9-altref-enc-golden.webm differ
diff --git a/packager/app/test/testdata/bear-vp9-blockgroup-golden.webm b/packager/app/test/testdata/bear-vp9-blockgroup-golden.webm
index 9ab11de170..aeda2e9b36 100644
Binary files a/packager/app/test/testdata/bear-vp9-blockgroup-golden.webm and b/packager/app/test/testdata/bear-vp9-blockgroup-golden.webm differ
diff --git a/packager/media/formats/webm/encrypted_segmenter_unittest.cc b/packager/media/formats/webm/encrypted_segmenter_unittest.cc
index 8af360d76f..b263f94d00 100644
--- a/packager/media/formats/webm/encrypted_segmenter_unittest.cc
+++ b/packager/media/formats/webm/encrypted_segmenter_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "packager/media/formats/webm/single_segment_segmenter.h"
#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
#include
@@ -39,16 +38,16 @@ const uint8_t kBasicSupportData[] = {
0x53, 0xac, 0x81, 0xb6,
// ID: Seek, Payload Size: 12
0x4d, 0xbb, 0x8c,
- // SeekID: binary(4) (Cluster)
- 0x53, 0xab, 0x84, 0x1f, 0x43, 0xb6, 0x75,
+ // SeekID: binary(4) (Cues)
+ 0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
// SeekPosition: 279
0x53, 0xac, 0x82, 0x01, 0x17,
// ID: Seek, Payload Size: 12
0x4d, 0xbb, 0x8c,
- // SeekID: binary(4) (Cues)
- 0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
- // SeekPosition: 398
- 0x53, 0xac, 0x82, 0x01, 0x8e,
+ // SeekID: binary(4) (Cluster)
+ 0x53, 0xab, 0x84, 0x1f, 0x43, 0xb6, 0x75,
+ // SeekPosition: 313
+ 0x53, 0xac, 0x82, 0x01, 0x39,
// ID: Void, Payload Size: 24
0xec, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -115,6 +114,28 @@ const uint8_t kBasicSupportData[] = {
0x54, 0xb0, 0x81, 0x64,
// DisplayHeight: 100
0x54, 0xba, 0x81, 0x64,
+ // ID: Cues, Payload Size: 29
+ 0x1c, 0x53, 0xbb, 0x6b, 0x9d,
+ // ID: CuePoint, Payload Size: 12
+ 0xbb, 0x8c,
+ // CueTime: 0
+ 0xb3, 0x81, 0x00,
+ // ID: CueTrackPositions, Payload Size: 7
+ 0xb7, 0x87,
+ // CueTrack: 1
+ 0xf7, 0x81, 0x01,
+ // CueClusterPosition: 313
+ 0xf1, 0x82, 0x01, 0x39,
+ // ID: CuePoint, Payload Size: 13
+ 0xbb, 0x8d,
+ // CueTime: 3000
+ 0xb3, 0x82, 0x0b, 0xb8,
+ // ID: CueTrackPositions, Payload Size: 7
+ 0xb7, 0x87,
+ // CueTrack: 1
+ 0xf7, 0x81, 0x01,
+ // CueClusterPosition: 370
+ 0xf1, 0x82, 0x01, 0x72,
// ID: Cluster, Payload Size: 45
0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
// Timecode: 0
@@ -165,28 +186,6 @@ const uint8_t kBasicSupportData[] = {
0xbf, 0x38, 0x72, 0x20, 0xac,
// BlockDuration: 1000
0x9b, 0x82, 0x03, 0xe8,
- // ID: Cues, Payload Size: 29
- 0x1c, 0x53, 0xbb, 0x6b, 0x9d,
- // ID: CuePoint, Payload Size: 12
- 0xbb, 0x8c,
- // CueTime: 0
- 0xb3, 0x81, 0x00,
- // ID: CueTrackPositions, Payload Size: 7
- 0xb7, 0x87,
- // CueTrack: 1
- 0xf7, 0x81, 0x01,
- // CueClusterPosition: 279
- 0xf1, 0x82, 0x01, 0x17,
- // ID: CuePoint, Payload Size: 13
- 0xbb, 0x8d,
- // CueTime: 3000
- 0xb3, 0x82, 0x0b, 0xb8,
- // ID: CueTrackPositions, Payload Size: 7
- 0xb7, 0x87,
- // CueTrack: 1
- 0xf7, 0x81, 0x01,
- // CueClusterPosition: 336
- 0xf1, 0x82, 0x01, 0x50,
};
} // namespace
@@ -200,7 +199,7 @@ class EncrypedSegmenterTest : public SegmentTestBase {
key_source_ =
FixedKeySource::CreateFromHexStrings(kKeyId, kKey, kPsshData, kIv);
ASSERT_NO_FATAL_FAILURE(
- CreateAndInitializeSegmenter(
+ CreateAndInitializeSegmenter(
options, info_.get(), key_source_.get(), &segmenter_));
}
diff --git a/packager/media/formats/webm/seek_head.cc b/packager/media/formats/webm/seek_head.cc
index 15f21ea1b5..7579bd9513 100644
--- a/packager/media/formats/webm/seek_head.cc
+++ b/packager/media/formats/webm/seek_head.cc
@@ -6,19 +6,23 @@
#include "packager/media/formats/webm/seek_head.h"
+#include
#include
+#include "packager/base/logging.h"
#include "packager/third_party/libwebm/src/mkvmuxerutil.hpp"
#include "packager/third_party/libwebm/src/webmids.hpp"
namespace shaka {
namespace media {
namespace {
-const mkvmuxer::uint64 kElementIds[] = {
- mkvmuxer::kMkvInfo, mkvmuxer::kMkvTracks, mkvmuxer::kMkvCluster,
- mkvmuxer::kMkvCues,
-};
-const int kElementIdCount = arraysize(kElementIds);
+
+// Cluster, Cues, Info, Tracks.
+const size_t kElementIdCount = 4u;
+
+uint64_t EbmlMasterElementWithPayloadSize(mkvmuxer::MkvId id, uint64_t payload_size) {
+ return EbmlMasterElementSize(id, payload_size) + payload_size;
+}
uint64_t MaxSeekEntrySize() {
const uint64_t max_entry_payload_size =
@@ -27,57 +31,46 @@ uint64_t MaxSeekEntrySize() {
static_cast(std::numeric_limits::max())) +
EbmlElementSize(mkvmuxer::kMkvSeekPosition,
std::numeric_limits::max());
- const uint64_t max_entry_size =
- EbmlMasterElementSize(mkvmuxer::kMkvSeek, max_entry_payload_size) +
- max_entry_payload_size;
-
- return max_entry_size;
+ return EbmlMasterElementWithPayloadSize(mkvmuxer::kMkvSeek,
+ max_entry_payload_size);
}
+
} // namespace
SeekHead::SeekHead()
- : cluster_pos_(-1),
- cues_pos_(-1),
- info_pos_(-1),
- tracks_pos_(-1),
- wrote_void_(false) {}
+ : total_void_size_(EbmlMasterElementWithPayloadSize(
+ mkvmuxer::kMkvSeekHead,
+ kElementIdCount * MaxSeekEntrySize())) {}
SeekHead::~SeekHead() {}
bool SeekHead::Write(mkvmuxer::IMkvWriter* writer) {
- std::vector element_sizes;
- const uint64_t payload_size = GetPayloadSize(&element_sizes);
-
- if (payload_size == 0) {
+ std::vector seek_elements = CreateSeekElements();
+ if (seek_elements.empty())
return true;
+
+ uint64_t payload_size = 0;
+ for (const SeekHead::SeekElement& seek_element : seek_elements) {
+ payload_size +=
+ seek_element.size +
+ EbmlMasterElementSize(mkvmuxer::kMkvSeek, seek_element.size);
}
const int64_t start_pos = writer->Position();
if (!WriteEbmlMasterElement(writer, mkvmuxer::kMkvSeekHead, payload_size))
return false;
- const int64_t positions[] = {info_pos_, tracks_pos_, cluster_pos_, cues_pos_};
- for (int i = 0; i < kElementIdCount; ++i) {
- if (element_sizes[i] == 0)
- continue;
-
- const mkvmuxer::uint64 position =
- static_cast(positions[i]);
- if (!WriteEbmlMasterElement(writer, mkvmuxer::kMkvSeek, element_sizes[i]) ||
- !WriteEbmlElement(writer, mkvmuxer::kMkvSeekID, kElementIds[i]) ||
- !WriteEbmlElement(writer, mkvmuxer::kMkvSeekPosition, position))
+ for (const SeekHead::SeekElement& element : seek_elements) {
+ if (!WriteEbmlMasterElement(writer, mkvmuxer::kMkvSeek, element.size) ||
+ !WriteEbmlElement(writer, mkvmuxer::kMkvSeekID, element.id) ||
+ !WriteEbmlElement(writer, mkvmuxer::kMkvSeekPosition, element.position))
return false;
}
// If we wrote void before, then fill in the extra with void.
if (wrote_void_) {
- const uint64_t max_payload_size = kElementIdCount * MaxSeekEntrySize();
- const uint64_t total_void_size =
- EbmlMasterElementSize(mkvmuxer::kMkvSeekHead, max_payload_size) +
- max_payload_size;
-
const uint64_t extra_void =
- total_void_size - (writer->Position() - start_pos);
+ total_void_size_ - (writer->Position() - start_pos);
if (!WriteVoidElement(writer, extra_void))
return false;
}
@@ -86,38 +79,36 @@ bool SeekHead::Write(mkvmuxer::IMkvWriter* writer) {
}
bool SeekHead::WriteVoid(mkvmuxer::IMkvWriter* writer) {
- const uint64_t payload_size = kElementIdCount * MaxSeekEntrySize();
- const uint64_t total_size =
- EbmlMasterElementSize(mkvmuxer::kMkvSeekHead, payload_size) +
- payload_size;
-
- wrote_void_ = true;
- const uint64_t written = WriteVoidElement(writer, total_size);
+ const uint64_t written = WriteVoidElement(writer, total_void_size_);
if (!written)
return false;
-
+ wrote_void_ = true;
return true;
}
-uint64_t SeekHead::GetPayloadSize(std::vector* data) {
- const int64_t positions[] = {info_pos_, tracks_pos_, cluster_pos_, cues_pos_};
- uint64_t total_payload_size = 0;
- data->resize(kElementIdCount);
- for (int i = 0; i < kElementIdCount; ++i) {
- if (positions[i] < 0) {
- (*data)[i] = 0;
- continue;
- }
+std::vector SeekHead::CreateSeekElements() {
+ std::vector seek_elements;
+ if (info_pos_ != 0)
+ seek_elements.emplace_back(mkvmuxer::kMkvInfo, info_pos_);
+ if (tracks_pos_ != 0)
+ seek_elements.emplace_back(mkvmuxer::kMkvTracks, tracks_pos_);
+ if (cues_pos_ != 0)
+ seek_elements.emplace_back(mkvmuxer::kMkvCues, cues_pos_);
+ if (cluster_pos_ != 0)
+ seek_elements.emplace_back(mkvmuxer::kMkvCluster, cluster_pos_);
+ DCHECK_LE(seek_elements.size(), kElementIdCount);
- const mkvmuxer::uint64 position =
- static_cast(positions[i]);
- (*data)[i] = EbmlElementSize(mkvmuxer::kMkvSeekID, kElementIds[i]) +
- EbmlElementSize(mkvmuxer::kMkvSeekPosition, position);
- total_payload_size +=
- data->at(i) + EbmlMasterElementSize(mkvmuxer::kMkvSeek, data->at(i));
+ std::sort(seek_elements.begin(), seek_elements.end(),
+ [](const SeekHead::SeekElement& left,
+ const SeekHead::SeekElement& right) {
+ return left.position < right.position;
+ });
+ for (SeekHead::SeekElement& element : seek_elements) {
+ element.size =
+ EbmlElementSize(mkvmuxer::kMkvSeekID, element.id) +
+ EbmlElementSize(mkvmuxer::kMkvSeekPosition, element.position);
}
-
- return total_payload_size;
+ return seek_elements;
}
} // namespace media
diff --git a/packager/media/formats/webm/seek_head.h b/packager/media/formats/webm/seek_head.h
index ccd5188d85..a4c3c019d6 100644
--- a/packager/media/formats/webm/seek_head.h
+++ b/packager/media/formats/webm/seek_head.h
@@ -10,7 +10,6 @@
#include
#include
-#include "base/macros.h"
#include "packager/third_party/libwebm/src/mkvmuxer.hpp"
namespace shaka {
@@ -35,15 +34,29 @@ class SeekHead {
void set_tracks_pos(uint64_t pos) { tracks_pos_ = pos; }
private:
- uint64_t GetPayloadSize(std::vector* data);
+ SeekHead(const SeekHead&) = delete;
+ SeekHead& operator=(const SeekHead&) = delete;
- int64_t cluster_pos_;
- int64_t cues_pos_;
- int64_t info_pos_;
- int64_t tracks_pos_;
- bool wrote_void_;
+ struct SeekElement {
+ mkvmuxer::uint64 id;
+ mkvmuxer::uint64 position;
+ mkvmuxer::uint64 size;
- DISALLOW_COPY_AND_ASSIGN(SeekHead);
+ SeekElement(uint64_t seek_id, uint64_t seek_position)
+ : id(seek_id), position(seek_position), size(0) {}
+ };
+
+ // Create seek element vector from positions.
+ std::vector CreateSeekElements();
+
+ // In practice, these positions, if set, will never be 0, so we use a zero
+ // value to denote that they are not set.
+ uint64_t cluster_pos_ = 0;
+ uint64_t cues_pos_ = 0;
+ uint64_t info_pos_ = 0;
+ uint64_t tracks_pos_ = 0;
+ bool wrote_void_ = false;
+ const uint64_t total_void_size_ = 0;
};
} // namespace media
diff --git a/packager/media/formats/webm/single_segment_segmenter.h b/packager/media/formats/webm/single_segment_segmenter.h
index 1044a810d5..ff8efd54f2 100644
--- a/packager/media/formats/webm/single_segment_segmenter.h
+++ b/packager/media/formats/webm/single_segment_segmenter.h
@@ -36,6 +36,7 @@ class SingleSegmentSegmenter : public Segmenter {
protected:
MkvWriter* writer() { return writer_.get(); }
+ uint64_t init_end() { return init_end_; }
void set_init_end(uint64_t end) { init_end_ = end; }
void set_index_start(uint64_t start) { index_start_ = start; }
void set_index_end(uint64_t end) { index_end_ = end; }
diff --git a/packager/media/formats/webm/single_segment_segmenter_unittest.cc b/packager/media/formats/webm/single_segment_segmenter_unittest.cc
index f24bda7630..7f6d01a219 100644
--- a/packager/media/formats/webm/single_segment_segmenter_unittest.cc
+++ b/packager/media/formats/webm/single_segment_segmenter_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "packager/media/formats/webm/single_segment_segmenter.h"
#include "packager/media/formats/webm/two_pass_single_segment_segmenter.h"
#include
@@ -20,7 +19,7 @@ const uint8_t kBasicSupportData[] = {
// ID: Segment, Payload Size: 343
0x18, 0x53, 0x80, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x57,
// ID: SeekHead, Payload Size: 57
- 0x11, 0x4d, 0x9b, 0x74, 0xb9,
+ 0x11, 0x4d, 0x9b, 0x74, 0xb8,
// ID: Seek, Payload Size: 11
0x4d, 0xbb, 0x8b,
// SeekID: binary(4) (Info)
@@ -33,22 +32,22 @@ const uint8_t kBasicSupportData[] = {
0x53, 0xab, 0x84, 0x16, 0x54, 0xae, 0x6b,
// SeekPosition: 182
0x53, 0xac, 0x81, 0xb6,
+ // ID: Seek, Payload Size: 12
+ 0x4d, 0xbb, 0x8b,
+ // SeekID: binary(4) (Cues)
+ 0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
+ // SeekPosition: 228
+ 0x53, 0xac, 0x81, 0xe4,
// ID: Seek, Payload Size: 11
0x4d, 0xbb, 0x8b,
// SeekID: binary(4) (Cluster)
0x53, 0xab, 0x84, 0x1f, 0x43, 0xb6, 0x75,
- // SeekPosition: 228
- 0x53, 0xac, 0x81, 0xe4,
- // ID: Seek, Payload Size: 12
- 0x4d, 0xbb, 0x8c,
- // SeekID: binary(4) (Cues)
- 0x53, 0xab, 0x84, 0x1c, 0x53, 0xbb, 0x6b,
- // SeekPosition: 325
- 0x53, 0xac, 0x82, 0x01, 0x45,
- // ID: Void, Payload Size: 25
- 0xec, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // SeekPosition: 246
+ 0x53, 0xac, 0x81, 0xf6,
+ // ID: Void, Payload Size: 26
+ 0xec, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
// ID: Info, Payload Size: 88
0x15, 0x49, 0xa9, 0x66, 0xd8,
// TimecodeScale: 1000000
@@ -89,6 +88,18 @@ const uint8_t kBasicSupportData[] = {
0x54, 0xb0, 0x81, 0x64,
// DisplayHeight: 100
0x54, 0xba, 0x81, 0x64,
+ // ID: Cues, Payload Size: 13
+ 0x1c, 0x53, 0xbb, 0x6b, 0x8d,
+ // ID: CuePoint, Payload Size: 11
+ 0xbb, 0x8b,
+ // CueTime: 0
+ 0xb3, 0x81, 0x00,
+ // ID: CueTrackPositions, Payload Size: 6
+ 0xb7, 0x86,
+ // CueTrack: 1
+ 0xf7, 0x81, 0x01,
+ // CueClusterPosition: 246
+ 0xf1, 0x81, 0xf6,
// ID: Cluster, Payload Size: 85
0x1f, 0x43, 0xb6, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
// Timecode: 0
@@ -117,48 +128,26 @@ const uint8_t kBasicSupportData[] = {
0xa1, 0x89, 0x81, 0x0f, 0xa0, 0x00, 0xde, 0xad, 0xbe, 0xef, 0x00,
// BlockDuration: 1000
0x9b, 0x82, 0x03, 0xe8,
- // ID: Cues, Payload Size: 13
- 0x1c, 0x53, 0xbb, 0x6b, 0x8d,
- // ID: CuePoint, Payload Size: 11
- 0xbb, 0x8b,
- // CueTime: 0
- 0xb3, 0x81, 0x00,
- // ID: CueTrackPositions, Payload Size: 6
- 0xb7, 0x86,
- // CueTrack: 1
- 0xf7, 0x81, 0x01,
- // CueClusterPosition: 228
- 0xf1, 0x81, 0xe4
};
} // namespace
-// This is a parameterized test that tests both SingleSegmentSegmenter and
-// TwoPassSingleSegmentSegmenter, since they should provide the exact same
-// output.
-class SingleSegmentSegmenterTest : public SegmentTestBase,
- public ::testing::WithParamInterface {
+class SingleSegmentSegmenterTest : public SegmentTestBase {
public:
SingleSegmentSegmenterTest() : info_(CreateVideoStreamInfo()) {}
protected:
void InitializeSegmenter(const MuxerOptions& options) {
- if (!GetParam()) {
- ASSERT_NO_FATAL_FAILURE(
- CreateAndInitializeSegmenter(
- options, info_.get(), NULL, &segmenter_));
- } else {
- ASSERT_NO_FATAL_FAILURE(
- CreateAndInitializeSegmenter(
- options, info_.get(), NULL, &segmenter_));
- }
+ ASSERT_NO_FATAL_FAILURE(
+ CreateAndInitializeSegmenter(
+ options, info_.get(), NULL, &segmenter_));
}
scoped_refptr info_;
std::unique_ptr segmenter_;
};
-TEST_P(SingleSegmentSegmenterTest, BasicSupport) {
+TEST_F(SingleSegmentSegmenterTest, BasicSupport) {
MuxerOptions options = CreateMuxerOptions();
ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options));
@@ -175,7 +164,7 @@ TEST_P(SingleSegmentSegmenterTest, BasicSupport) {
ASSERT_FILE_ENDS_WITH(OutputFileName().c_str(), kBasicSupportData);
}
-TEST_P(SingleSegmentSegmenterTest, SplitsClustersOnSegmentDuration) {
+TEST_F(SingleSegmentSegmenterTest, SplitsClustersOnSegmentDuration) {
MuxerOptions options = CreateMuxerOptions();
options.segment_duration = 4.5; // seconds
ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options));
@@ -196,7 +185,7 @@ TEST_P(SingleSegmentSegmenterTest, SplitsClustersOnSegmentDuration) {
EXPECT_EQ(3, parser.GetFrameCountForCluster(1));
}
-TEST_P(SingleSegmentSegmenterTest, IgnoresFragmentDuration) {
+TEST_F(SingleSegmentSegmenterTest, IgnoresFragmentDuration) {
MuxerOptions options = CreateMuxerOptions();
options.fragment_duration = 5; // seconds
ASSERT_NO_FATAL_FAILURE(InitializeSegmenter(options));
@@ -216,7 +205,7 @@ TEST_P(SingleSegmentSegmenterTest, IgnoresFragmentDuration) {
EXPECT_EQ(8, parser.GetFrameCountForCluster(0));
}
-TEST_P(SingleSegmentSegmenterTest, RespectsSAPAlign) {
+TEST_F(SingleSegmentSegmenterTest, RespectsSAPAlign) {
MuxerOptions options = CreateMuxerOptions();
options.segment_duration = 3; // seconds
options.segment_sap_aligned = true;
@@ -242,9 +231,5 @@ TEST_P(SingleSegmentSegmenterTest, RespectsSAPAlign) {
EXPECT_EQ(4, parser.GetFrameCountForCluster(1));
}
-INSTANTIATE_TEST_CASE_P(TrueIsTwoPass,
- SingleSegmentSegmenterTest,
- ::testing::Bool());
-
} // namespace media
} // namespace shaka
diff --git a/packager/media/formats/webm/two_pass_single_segment_segmenter.cc b/packager/media/formats/webm/two_pass_single_segment_segmenter.cc
index a8166c4248..52a7c63758 100644
--- a/packager/media/formats/webm/two_pass_single_segment_segmenter.cc
+++ b/packager/media/formats/webm/two_pass_single_segment_segmenter.cc
@@ -28,6 +28,26 @@ namespace shaka {
namespace media {
namespace webm {
namespace {
+// Cues will be inserted before clusters. All clusters will be shifted down by
+// the size of cues. However, cluster positions affect the size of cues. This
+// function adjusts cues size iteratively until it is stable.
+// Returns the size of updated Cues.
+uint64_t UpdateCues(mkvmuxer::Cues* cues) {
+ uint64_t cues_size = cues->Size();
+ uint64_t adjustment = cues_size;
+ while (adjustment != 0) {
+ for (int i = 0; i < cues->cue_entries_size(); ++i) {
+ mkvmuxer::CuePoint* cue = cues->GetCueByIndex(i);
+ cue->set_cluster_pos(cue->cluster_pos() + adjustment);
+ }
+ uint64_t new_cues_size = cues->Size();
+ DCHECK_LE(cues_size, new_cues_size);
+ adjustment = new_cues_size - cues_size;
+ cues_size = new_cues_size;
+ }
+ return cues_size;
+}
+
/// Create the temp file name using process/thread id and current time.
std::string TempFileName(const MuxerOptions& options) {
// TODO: Move to a common util function and remove other uses.
@@ -93,17 +113,26 @@ Status TwoPassSingleSegmentSegmenter::DoFinalize() {
if (!cluster()->Finalize())
return Status(error::FILE_FAILURE, "Error finalizing cluster.");
- // Write the Cues to the end of the temp file.
- uint64_t cues_pos = writer()->Position();
- set_index_start(cues_pos);
- seek_head()->set_cues_pos(cues_pos - segment_payload_pos());
- if (!cues()->Write(writer()))
- return Status(error::FILE_FAILURE, "Error writing Cues data.");
+ const uint64_t header_size = init_end() + 1;
+ const uint64_t cues_pos = header_size - segment_payload_pos();
+ const uint64_t cues_size = UpdateCues(cues());
+ seek_head()->set_cues_pos(cues_pos);
+ seek_head()->set_cluster_pos(cues_pos + cues_size);
// Write the header to the real output file.
- Status temp = WriteSegmentHeader(writer()->Position(), real_writer_.get());
+ const uint64_t file_size = writer()->Position() + cues_size;
+ Status temp = WriteSegmentHeader(file_size, real_writer_.get());
if (!temp.ok())
return temp;
+ DCHECK_EQ(real_writer_->Position(), static_cast(header_size));
+
+ // Write the cues to the real output file.
+ set_index_start(real_writer_->Position());
+ if (!cues()->Write(real_writer_.get()))
+ return Status(error::FILE_FAILURE, "Error writing Cues data.");
+ set_index_end(real_writer_->Position() - 1);
+ DCHECK_EQ(real_writer_->Position(),
+ static_cast(segment_payload_pos() + cues_pos + cues_size));
// Close the temp file and open it for reading.
set_writer(std::unique_ptr());
@@ -113,14 +142,14 @@ Status TwoPassSingleSegmentSegmenter::DoFinalize() {
return Status(error::FILE_FAILURE, "Error opening temp file.");
// Skip the header that has already been written.
- uint64_t header_size = real_writer_->Position();
if (!ReadSkip(temp_reader.get(), header_size))
return Status(error::FILE_FAILURE, "Error reading temp file.");
// Copy the rest of the data over.
if (!CopyFileWithClusterRewrite(temp_reader.get(), real_writer_.get(),
- cluster()->Size()))
+ cluster()->Size())) {
return Status(error::FILE_FAILURE, "Error copying temp file.");
+ }
// Close and delete the temp file.
temp_reader.reset();
@@ -128,8 +157,6 @@ Status TwoPassSingleSegmentSegmenter::DoFinalize() {
LOG(WARNING) << "Unable to delete temporary file " << temp_file_name_;
}
- // The WebM index is at the end of the file.
- set_index_end(real_writer_->file()->Size() - 1);
return real_writer_->Close();
}
@@ -175,9 +202,9 @@ bool TwoPassSingleSegmentSegmenter::CopyFileWithClusterRewrite(
if (!ReadSkip(source, cluster_size_size))
return false;
- // Copy the remaining data (i.e. Cues data).
+ // Copy the last cluster.
return dest->WriteFromFile(source) ==
- static_cast(last_cluster_payload_size + cues()->Size());
+ static_cast(last_cluster_payload_size);
}
} // namespace webm
diff --git a/packager/media/formats/webm/webm.gyp b/packager/media/formats/webm/webm.gyp
index 7557405d27..1aeb63c9ec 100644
--- a/packager/media/formats/webm/webm.gyp
+++ b/packager/media/formats/webm/webm.gyp
@@ -84,6 +84,7 @@
'dependencies': [
'../../../testing/gtest.gyp:gtest',
'../../../testing/gmock.gyp:gmock',
+ '../../../third_party/libwebm/libwebm.gyp:mkvmuxer',
'../../file/file.gyp:file',
'../../test/media_test.gyp:media_test_support',
'webm',
diff --git a/packager/media/formats/webm/webm_muxer.cc b/packager/media/formats/webm/webm_muxer.cc
index d4ac37db70..3f3d55e552 100644
--- a/packager/media/formats/webm/webm_muxer.cc
+++ b/packager/media/formats/webm/webm_muxer.cc
@@ -45,8 +45,6 @@ Status WebMMuxer::Initialize() {
if (!options().single_segment) {
segmenter_.reset(new MultiSegmentSegmenter(options()));
- } else if (writer->Seekable()) {
- segmenter_.reset(new SingleSegmentSegmenter(options()));
} else {
segmenter_.reset(new TwoPassSingleSegmentSegmenter(options()));
}
diff --git a/packager/third_party/libwebm/libwebm.gyp b/packager/third_party/libwebm/libwebm.gyp
index 882a43023f..0d4bcabb48 100644
--- a/packager/third_party/libwebm/libwebm.gyp
+++ b/packager/third_party/libwebm/libwebm.gyp
@@ -12,13 +12,26 @@
'target_name': 'mkvmuxer',
'type': 'static_library',
'sources': [
- 'src/mkvmuxer.cpp',
- 'src/mkvmuxer.hpp',
- 'src/mkvmuxerutil.cpp',
- 'src/mkvmuxerutil.hpp',
- 'src/mkvwriter.cpp',
- 'src/mkvwriter.hpp',
+ 'src/common/webmids.h',
+ 'src/mkvmuxer/mkvmuxer.cc',
+ 'src/mkvmuxer/mkvmuxer.h',
+ 'src/mkvmuxer/mkvmuxertypes.h',
+ 'src/mkvmuxer/mkvmuxerutil.cc',
+ 'src/mkvmuxer/mkvmuxerutil.h',
+ 'src/mkvmuxer/mkvwriter.cc',
+ 'src/mkvmuxer/mkvwriter.h',
+ 'src/mkvmuxer.hpp'
+ 'src/mkvmuxerutil.hpp'
+ 'src/webmids.hpp'
],
+ 'include_dirs': [
+ 'src',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ 'src',
+ ],
+ },
},
],
}