2023-12-01 17:32:19 +00:00
|
|
|
// Copyright 2017 Google LLC. All rights reserved.
|
2017-05-22 16:35:49 +00:00
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/media/formats/webvtt/webvtt_muxer.h>
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2023-12-01 17:32:19 +00:00
|
|
|
#include <packager/file/file_test_util.h>
|
|
|
|
#include <packager/media/base/media_handler_test_base.h>
|
|
|
|
#include <packager/media/base/text_stream_info.h>
|
|
|
|
#include <packager/media/event/combined_muxer_listener.h>
|
|
|
|
#include <packager/media/event/mock_muxer_listener.h>
|
|
|
|
#include <packager/status/status_test_util.h>
|
2017-05-22 16:35:49 +00:00
|
|
|
|
|
|
|
namespace shaka {
|
|
|
|
namespace media {
|
2020-07-30 21:26:45 +00:00
|
|
|
namespace webvtt {
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
namespace {
|
2020-07-30 21:26:45 +00:00
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
using testing::_;
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
const size_t kInputCount = 1;
|
|
|
|
const size_t kOutputCount = 0;
|
|
|
|
const size_t kInputIndex = 0;
|
|
|
|
const size_t kStreamIndex = 0;
|
|
|
|
|
|
|
|
const bool kEncrypted = true;
|
|
|
|
const char* kNoId = "";
|
|
|
|
|
2021-08-04 18:56:44 +00:00
|
|
|
const int64_t kMsTimeScale = 1000;
|
2018-06-06 18:41:21 +00:00
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
const char* kSegmentedFileTemplate = "memory://output/template-$Number$.vtt";
|
|
|
|
const char* kSegmentedFileOutput1 = "memory://output/template-1.vtt";
|
|
|
|
const char* kSegmentedFileOutput2 = "memory://output/template-2.vtt";
|
2018-01-04 23:00:11 +00:00
|
|
|
|
2021-08-04 18:56:44 +00:00
|
|
|
const int64_t kSegmentDuration = 10000;
|
2018-01-04 23:00:11 +00:00
|
|
|
const float kMillisecondsPerSecond = 1000.0f;
|
2017-05-22 16:35:49 +00:00
|
|
|
} // namespace
|
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
class WebVttMuxerTest : public MediaHandlerTestBase {
|
2017-05-22 16:35:49 +00:00
|
|
|
protected:
|
|
|
|
void SetUp() {
|
|
|
|
MuxerOptions muxer_options;
|
|
|
|
muxer_options.segment_template = kSegmentedFileTemplate;
|
2018-01-04 23:00:11 +00:00
|
|
|
|
|
|
|
// Create a mock muxer listener but save a reference to the mock so that we
|
|
|
|
// can use it in the test.
|
|
|
|
std::unique_ptr<MockMuxerListener> muxer_listener(new MockMuxerListener);
|
|
|
|
muxer_listener_ = muxer_listener.get();
|
2017-05-22 16:35:49 +00:00
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
out_ = std::make_shared<WebVttMuxer>(muxer_options);
|
|
|
|
out_->SetMuxerListener(std::move(muxer_listener));
|
2017-05-22 16:35:49 +00:00
|
|
|
|
|
|
|
ASSERT_OK(SetUpAndInitializeGraph(out_, kInputCount, kOutputCount));
|
|
|
|
}
|
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
MockMuxerListener* muxer_listener_ = nullptr;
|
2020-07-30 21:26:45 +00:00
|
|
|
std::shared_ptr<WebVttMuxer> out_;
|
2017-05-22 16:35:49 +00:00
|
|
|
};
|
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
TEST_F(WebVttMuxerTest, WithNoSegmentAndWithNoSamples) {
|
2018-01-04 23:00:11 +00:00
|
|
|
EXPECT_CALL(*muxer_listener_, OnNewSegment(_, _, _, _)).Times(0);
|
|
|
|
|
|
|
|
{
|
|
|
|
// No segments should have be created as there were no samples.
|
|
|
|
|
|
|
|
testing::InSequence s;
|
|
|
|
EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
|
2020-07-30 21:26:45 +00:00
|
|
|
EXPECT_CALL(*muxer_listener_, OnMediaEndMock(_, _, _, _, _, _, _, _, _));
|
2018-01-04 23:00:11 +00:00
|
|
|
}
|
2017-05-22 16:35:49 +00:00
|
|
|
|
|
|
|
ASSERT_OK(Input(kInputIndex)
|
2018-06-06 18:41:21 +00:00
|
|
|
->Dispatch(StreamData::FromStreamInfo(
|
|
|
|
kStreamIndex, GetTextStreamInfo(kMsTimeScale))));
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
|
|
|
|
}
|
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
TEST_F(WebVttMuxerTest, WithOneSegmentAndWithOneSample) {
|
2017-05-22 16:35:49 +00:00
|
|
|
const char* kExpectedOutput =
|
|
|
|
"WEBVTT\n"
|
|
|
|
"\n"
|
2021-05-05 05:57:43 +00:00
|
|
|
"00:00:05.000 --> 00:00:06.000 align:center\n"
|
2017-05-22 16:35:49 +00:00
|
|
|
"payload\n"
|
|
|
|
"\n";
|
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
const uint64_t kSegmentStart = 0;
|
|
|
|
|
|
|
|
{
|
|
|
|
testing::InSequence s;
|
|
|
|
EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnNewSegment(kSegmentedFileOutput1, kSegmentStart,
|
|
|
|
kSegmentDuration, _));
|
|
|
|
|
|
|
|
const float kMediaDuration = 1 * kSegmentDuration / kMillisecondsPerSecond;
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnMediaEndMock(_, _, _, _, _, _, _, _, kMediaDuration));
|
|
|
|
}
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)
|
2018-06-06 18:41:21 +00:00
|
|
|
->Dispatch(StreamData::FromStreamInfo(
|
|
|
|
kStreamIndex, GetTextStreamInfo(kMsTimeScale))));
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromTextSample(
|
|
|
|
kStreamIndex, GetTextSample(kNoId, 5000, 6000, "payload"))));
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromSegmentInfo(
|
|
|
|
kStreamIndex,
|
|
|
|
GetSegmentInfo(kSegmentStart, kSegmentDuration, !kEncrypted))));
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
|
|
|
|
|
|
|
|
ASSERT_FILE_STREQ(kSegmentedFileOutput1, kExpectedOutput);
|
|
|
|
}
|
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
TEST_F(WebVttMuxerTest, WithTwoSegmentAndWithOneSample) {
|
2017-05-22 16:35:49 +00:00
|
|
|
const char* kExpectedOutput1 =
|
|
|
|
"WEBVTT\n"
|
|
|
|
"\n"
|
2021-05-05 05:57:43 +00:00
|
|
|
"00:00:05.000 --> 00:00:06.000 align:center\n"
|
2017-05-22 16:35:49 +00:00
|
|
|
"payload 1\n"
|
|
|
|
"\n";
|
|
|
|
|
|
|
|
const char* kExpectedOutput2 =
|
|
|
|
"WEBVTT\n"
|
|
|
|
"\n"
|
2021-05-05 05:57:43 +00:00
|
|
|
"00:00:15.000 --> 00:00:16.000 align:center\n"
|
2017-05-22 16:35:49 +00:00
|
|
|
"payload 2\n"
|
|
|
|
"\n";
|
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
const uint64_t kSegment1Start = 0;
|
|
|
|
const uint64_t kSegment2Start = kSegmentDuration;
|
|
|
|
|
|
|
|
{
|
|
|
|
testing::InSequence s;
|
|
|
|
EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnNewSegment(kSegmentedFileOutput1, kSegment1Start,
|
|
|
|
kSegmentDuration, _));
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnNewSegment(kSegmentedFileOutput2, kSegment2Start,
|
|
|
|
kSegmentDuration, _));
|
|
|
|
|
|
|
|
const float kMediaDuration = 2 * kSegmentDuration / kMillisecondsPerSecond;
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnMediaEndMock(_, _, _, _, _, _, _, _, kMediaDuration));
|
|
|
|
}
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)
|
2018-06-06 18:41:21 +00:00
|
|
|
->Dispatch(StreamData::FromStreamInfo(
|
|
|
|
0, GetTextStreamInfo(kMsTimeScale))));
|
2017-05-22 16:35:49 +00:00
|
|
|
|
|
|
|
// Segment One
|
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromTextSample(
|
|
|
|
kStreamIndex, GetTextSample(kNoId, 5000, 6000, "payload 1"))));
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromSegmentInfo(
|
|
|
|
kStreamIndex,
|
|
|
|
GetSegmentInfo(kSegment1Start, kSegmentDuration, !kEncrypted))));
|
2017-05-22 16:35:49 +00:00
|
|
|
// Segment Two
|
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromTextSample(
|
|
|
|
kStreamIndex, GetTextSample(kNoId, 15000, 16000, "payload 2"))));
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromSegmentInfo(
|
|
|
|
kStreamIndex,
|
|
|
|
GetSegmentInfo(kSegment2Start, kSegmentDuration, !kEncrypted))));
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
|
|
|
|
|
|
|
|
ASSERT_FILE_STREQ(kSegmentedFileOutput1, kExpectedOutput1);
|
|
|
|
ASSERT_FILE_STREQ(kSegmentedFileOutput2, kExpectedOutput2);
|
|
|
|
}
|
|
|
|
|
2020-07-30 21:26:45 +00:00
|
|
|
TEST_F(WebVttMuxerTest, WithAnEmptySegment) {
|
2018-01-04 23:00:11 +00:00
|
|
|
const char* kExpectedOutput1 =
|
|
|
|
"WEBVTT\n"
|
|
|
|
"\n";
|
|
|
|
|
|
|
|
const char* kExpectedOutput2 =
|
2017-05-22 16:35:49 +00:00
|
|
|
"WEBVTT\n"
|
|
|
|
"\n"
|
2021-05-05 05:57:43 +00:00
|
|
|
"00:00:15.000 --> 00:00:16.000 align:center\n"
|
2017-05-22 16:35:49 +00:00
|
|
|
"payload 2\n"
|
|
|
|
"\n";
|
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
const uint64_t kSegment1Start = 0;
|
|
|
|
const uint64_t kSegment2Start = kSegmentDuration;
|
|
|
|
|
|
|
|
{
|
|
|
|
testing::InSequence s;
|
|
|
|
EXPECT_CALL(*muxer_listener_, OnMediaStart(_, _, _, _));
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnNewSegment(kSegmentedFileOutput1, kSegment1Start,
|
|
|
|
kSegmentDuration, _));
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnNewSegment(kSegmentedFileOutput2, kSegment2Start,
|
|
|
|
kSegmentDuration, _));
|
|
|
|
|
|
|
|
const float kMediaDuration = 2 * kSegmentDuration / kMillisecondsPerSecond;
|
|
|
|
EXPECT_CALL(*muxer_listener_,
|
|
|
|
OnMediaEndMock(_, _, _, _, _, _, _, _, kMediaDuration));
|
|
|
|
}
|
|
|
|
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)
|
2018-06-06 18:41:21 +00:00
|
|
|
->Dispatch(StreamData::FromStreamInfo(
|
|
|
|
0, GetTextStreamInfo(kMsTimeScale))));
|
2017-05-22 16:35:49 +00:00
|
|
|
// Segment One
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromSegmentInfo(
|
|
|
|
kStreamIndex,
|
|
|
|
GetSegmentInfo(kSegment1Start, kSegmentDuration, !kEncrypted))));
|
2017-05-22 16:35:49 +00:00
|
|
|
// Segment Two
|
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromTextSample(
|
|
|
|
kStreamIndex, GetTextSample(kNoId, 15000, 16000, "payload 2"))));
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_OK(
|
|
|
|
Input(kInputIndex)
|
|
|
|
->Dispatch(StreamData::FromSegmentInfo(
|
|
|
|
kStreamIndex,
|
|
|
|
GetSegmentInfo(kSegment2Start, kSegmentDuration, !kEncrypted))));
|
2017-05-22 16:35:49 +00:00
|
|
|
ASSERT_OK(Input(kInputIndex)->FlushAllDownstreams());
|
|
|
|
|
2018-01-04 23:00:11 +00:00
|
|
|
ASSERT_FILE_STREQ(kSegmentedFileOutput1, kExpectedOutput1);
|
|
|
|
ASSERT_FILE_STREQ(kSegmentedFileOutput2, kExpectedOutput2);
|
2017-05-22 16:35:49 +00:00
|
|
|
}
|
2020-07-30 21:26:45 +00:00
|
|
|
|
|
|
|
} // namespace webvtt
|
2017-05-22 16:35:49 +00:00
|
|
|
} // namespace media
|
|
|
|
} // namespace shaka
|