parent
682ac3c990
commit
ab8485c5b7
6
AUTHORS
6
AUTHORS
|
@ -20,6 +20,7 @@ Anders Hasselqvist <anders.hasselqvist@gmail.com>
|
|||
Audible <*@audible.com>
|
||||
Chun-da Chen <capitalm.c@gmail.com>
|
||||
Daniel Cantarín <canta@canta.com.ar>
|
||||
Dennis E. Mungai (Brainiarc7) <dmngaie@gmail.com>
|
||||
Dolby Laboratories <*@dolby.com>
|
||||
Evgeny Zajcev <zevlg@yandex.ru>
|
||||
Eyevinn Technology AB <*@eyevinn.se>
|
||||
|
@ -27,13 +28,14 @@ Google LLC. <*@google.com>
|
|||
Ivi.ru LLC <*@ivi.ru>
|
||||
Leandro Moreira <leandro.ribeiro.moreira@gmail.com>
|
||||
Leo Law <leoltlaw.gh@gmail.com>
|
||||
Meta Platforms, Inc. <*@meta.com>
|
||||
More Screens Ltd. <*@morescreens.net>
|
||||
Ole Andre Birkedal <o.birkedal@sportradar.com>
|
||||
Philo Inc. <*@philo.com>
|
||||
Piotr Srebrny <srebrny.piotr@gmail.com>
|
||||
Prakash Duggaraju <duggaraju@gmail.com>
|
||||
Richard Eklycke <richard@eklycke.se>
|
||||
Sanil Raut <sr1990003@gmail.com>
|
||||
Sergio Ammirata <sergio@ammirata.net>
|
||||
The Chromium Authors <*@chromium.org>
|
||||
Prakash Duggaraju <duggaraju@gmail.com>
|
||||
Dennis E. Mungai (Brainiarc7) <dmngaie@gmail.com>
|
||||
|
||||
|
|
|
@ -27,8 +27,10 @@ Anders Hasselqvist <anders.hasselqvist@gmail.com>
|
|||
Andreas Motl <andreas.motl@elmyra.de>
|
||||
Bei Li <beil@google.com>
|
||||
Chun-da Chen <capitalm.c@gmail.com>
|
||||
Cosmin Stejerean <cstejerean@meta.com>
|
||||
Daniel Cantarín <canta@canta.com.ar>
|
||||
David Cavar <pal3thorn@gmail.com>
|
||||
Dennis E. Mungai (Brainiarc7) <dmngaie@gmail.com>
|
||||
Evgeny Zajcev <zevlg@yandex.ru>
|
||||
Gabe Kopley <gabe@philo.com>
|
||||
Geoff Jukes <geoff@jukes.org>
|
||||
|
@ -42,6 +44,7 @@ Leo Law <leoltlaw.gh@gmail.com>
|
|||
Marcus Spangenberg <marcus.spangenberg@eyevinn.se>
|
||||
Ole Andre Birkedal <o.birkedal@sportradar.com>
|
||||
Piotr Srebrny <srebrny.piotr@gmail.com>
|
||||
Prakash Duggaraju <duggaraju@gmail.com>
|
||||
Qingquan Wang <wangqq1103@gmail.com>
|
||||
Richard Eklycke <richard@eklycke.se>
|
||||
Rintaro Kuroiwa <rkuroiwa@google.com>
|
||||
|
@ -52,5 +55,4 @@ Thomas Inskip <tinskip@google.com>
|
|||
Tim Lansen <tim.lansen@gmail.com>
|
||||
Vincent Nguyen <nvincen@amazon.com>
|
||||
Weiguo Shao <weiguo.shao@dolby.com>
|
||||
Prakash Duggaraju <duggaraju@gmail.com>
|
||||
Dennis E. Mungai (Brainiarc7) <dmngaie@gmail.com>
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ include("protobuf.cmake")
|
|||
add_subdirectory(file)
|
||||
add_subdirectory(kv_pairs)
|
||||
add_subdirectory(media)
|
||||
add_subdirectory(hls)
|
||||
add_subdirectory(mpd)
|
||||
add_subdirectory(status)
|
||||
add_subdirectory(third_party)
|
||||
|
|
|
@ -48,4 +48,15 @@ bool TempFilePath(const std::string& temp_dir, std::string* temp_file_path) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string MakePathRelative(const std::filesystem::path& media_path,
|
||||
const std::filesystem::path& parent_path) {
|
||||
auto relative_path = std::filesystem::relative(media_path, parent_path);
|
||||
if (relative_path.empty() || *relative_path.begin() == "..") {
|
||||
// Not related.
|
||||
relative_path = media_path;
|
||||
}
|
||||
|
||||
return relative_path.lexically_normal().generic_string();
|
||||
}
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
namespace shaka {
|
||||
|
@ -15,4 +16,7 @@ namespace shaka {
|
|||
/// @returns true on success, false otherwise.
|
||||
bool TempFilePath(const std::string& temp_dir, std::string* temp_file_path);
|
||||
|
||||
std::string MakePathRelative(const std::filesystem::path& media_path,
|
||||
const std::filesystem::path& parent_path);
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
# Copyright 2016 Google LLC. All rights reserved.
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
add_library(hls_builder
|
||||
base/hls_notifier.h
|
||||
base/master_playlist.cc
|
||||
base/master_playlist.h
|
||||
base/media_playlist.cc
|
||||
base/media_playlist.h
|
||||
base/simple_hls_notifier.cc
|
||||
base/simple_hls_notifier.h
|
||||
base/tag.cc
|
||||
base/tag.h
|
||||
public/hls_params.h
|
||||
)
|
||||
|
||||
target_link_libraries(hls_builder
|
||||
file
|
||||
media_base
|
||||
widevine_protos
|
||||
manifest_base
|
||||
mpd_media_info_proto
|
||||
absl::flags
|
||||
absl::strings
|
||||
absl::str_format
|
||||
glog
|
||||
)
|
||||
|
||||
add_executable(hls_unittest
|
||||
base/master_playlist_unittest.cc
|
||||
base/media_playlist_unittest.cc
|
||||
base/mock_media_playlist.cc
|
||||
base/mock_media_playlist.h
|
||||
base/simple_hls_notifier_unittest.cc
|
||||
)
|
||||
|
||||
target_link_libraries(hls_unittest
|
||||
file
|
||||
file_test_util
|
||||
test_data_util
|
||||
absl::flags
|
||||
hls_builder
|
||||
gmock
|
||||
gtest
|
||||
gtest_main)
|
||||
|
||||
add_test(NAME hls_unittest COMMAND hls_unittest)
|
|
@ -10,10 +10,11 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "packager/base/files/file_path.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/string_util.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <absl/strings/str_join.h>
|
||||
#include <glog/logging.h>
|
||||
#include <filesystem>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/hls/base/media_playlist.h"
|
||||
#include "packager/hls/base/tag.h"
|
||||
|
@ -30,8 +31,8 @@ void AppendVersionString(std::string* content) {
|
|||
const std::string version = GetPackagerVersion();
|
||||
if (version.empty())
|
||||
return;
|
||||
base::StringAppendF(content, "## Generated with %s version %s\n",
|
||||
GetPackagerProjectUrl().c_str(), version.c_str());
|
||||
absl::StrAppendFormat(content, "## Generated with %s version %s\n",
|
||||
GetPackagerProjectUrl().c_str(), version.c_str());
|
||||
}
|
||||
|
||||
// This structure roughly maps to the Variant stream in HLS specification.
|
||||
|
@ -207,8 +208,8 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
|
|||
tag_name = "#EXT-X-I-FRAME-STREAM-INF";
|
||||
break;
|
||||
default:
|
||||
NOTREACHED() << "Cannot build STREAM-INFO tag for type "
|
||||
<< static_cast<int>(playlist.stream_type());
|
||||
NOTIMPLEMENTED() << "Cannot build STREAM-INFO tag for type "
|
||||
<< static_cast<int>(playlist.stream_type());
|
||||
break;
|
||||
}
|
||||
Tag tag(tag_name, out);
|
||||
|
@ -223,7 +224,7 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
|
|||
variant.audio_codecs.end());
|
||||
all_codecs.insert(all_codecs.end(), variant.text_codecs.begin(),
|
||||
variant.text_codecs.end());
|
||||
tag.AddQuotedString("CODECS", base::JoinString(all_codecs, ","));
|
||||
tag.AddQuotedString("CODECS", absl::StrJoin(all_codecs, ","));
|
||||
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
@ -266,8 +267,8 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
|
|||
tag.AddQuotedString("URI", base_url + playlist.file_name());
|
||||
out->append("\n");
|
||||
} else {
|
||||
base::StringAppendF(out, "\n%s%s\n", base_url.c_str(),
|
||||
playlist.file_name().c_str());
|
||||
absl::StrAppendFormat(out, "\n%s%s\n", base_url.c_str(),
|
||||
playlist.file_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,8 +296,8 @@ void BuildMediaTag(const MediaPlaylist& playlist,
|
|||
break;
|
||||
|
||||
default:
|
||||
NOTREACHED() << "Cannot build media tag for type "
|
||||
<< static_cast<int>(playlist.stream_type());
|
||||
NOTIMPLEMENTED() << "Cannot build media tag for type "
|
||||
<< static_cast<int>(playlist.stream_type());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -313,7 +314,7 @@ void BuildMediaTag(const MediaPlaylist& playlist,
|
|||
if (is_default) {
|
||||
tag.AddString("DEFAULT", "YES");
|
||||
} else {
|
||||
tag.AddString("DEFAULT", "NO");
|
||||
tag.AddString("DEFAULT", "NO");
|
||||
}
|
||||
|
||||
if (is_autoselect) {
|
||||
|
@ -322,8 +323,7 @@ void BuildMediaTag(const MediaPlaylist& playlist,
|
|||
|
||||
const std::vector<std::string>& characteristics = playlist.characteristics();
|
||||
if (!characteristics.empty()) {
|
||||
tag.AddQuotedString("CHARACTERISTICS",
|
||||
base::JoinString(characteristics, ","));
|
||||
tag.AddQuotedString("CHARACTERISTICS", absl::StrJoin(characteristics, ","));
|
||||
}
|
||||
|
||||
const MediaPlaylist::MediaPlaylistStreamType kAudio =
|
||||
|
@ -486,7 +486,7 @@ void AppendPlaylists(const std::string& default_audio_language,
|
|||
|
||||
} // namespace
|
||||
|
||||
MasterPlaylist::MasterPlaylist(const std::string& file_name,
|
||||
MasterPlaylist::MasterPlaylist(const std::filesystem::path& file_name,
|
||||
const std::string& default_audio_language,
|
||||
const std::string& default_text_language,
|
||||
bool is_independent_segments)
|
||||
|
@ -514,12 +514,9 @@ bool MasterPlaylist::WriteMasterPlaylist(
|
|||
if (content == written_playlist_)
|
||||
return true;
|
||||
|
||||
std::string file_path =
|
||||
base::FilePath::FromUTF8Unsafe(output_dir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe(file_name_))
|
||||
.AsUTF8Unsafe();
|
||||
if (!File::WriteFileAtomically(file_path.c_str(), content)) {
|
||||
LOG(ERROR) << "Failed to write master playlist to: " << file_path;
|
||||
auto file_path = std::filesystem::u8path(output_dir) / file_name_;
|
||||
if (!File::WriteFileAtomically(file_path.string().c_str(), content)) {
|
||||
LOG(ERROR) << "Failed to write master playlist to: " << file_path.string();
|
||||
return false;
|
||||
}
|
||||
written_playlist_ = content;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef PACKAGER_HLS_BASE_MASTER_PLAYLIST_H_
|
||||
#define PACKAGER_HLS_BASE_MASTER_PLAYLIST_H_
|
||||
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
|
@ -24,9 +25,9 @@ class MasterPlaylist {
|
|||
/// be tagged with 'DEFAULT'.
|
||||
/// @param default_text_language determines the text rendition that should be
|
||||
/// tagged with 'DEFAULT'.
|
||||
MasterPlaylist(const std::string& file_name,
|
||||
MasterPlaylist(const std::filesystem::path& file_name,
|
||||
const std::string& default_audio_language,
|
||||
const std::string& default_text_language,
|
||||
const std::string& default_text_language,
|
||||
const bool is_independent_segments);
|
||||
virtual ~MasterPlaylist();
|
||||
|
||||
|
@ -48,7 +49,7 @@ class MasterPlaylist {
|
|||
MasterPlaylist& operator=(const MasterPlaylist&) = delete;
|
||||
|
||||
std::string written_playlist_;
|
||||
const std::string file_name_;
|
||||
const std::filesystem::path file_name_;
|
||||
const std::string default_audio_language_;
|
||||
const std::string default_text_language_;
|
||||
bool is_independent_segments_;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packager/base/files/file_path.h"
|
||||
#include <filesystem>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/hls/base/master_playlist.h"
|
||||
#include "packager/hls/base/media_playlist.h"
|
||||
|
@ -17,9 +17,9 @@
|
|||
namespace shaka {
|
||||
namespace hls {
|
||||
|
||||
using base::FilePath;
|
||||
using ::testing::_;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnRef;
|
||||
|
@ -138,20 +138,18 @@ class MasterPlaylistTest : public ::testing::Test {
|
|||
protected:
|
||||
MasterPlaylistTest()
|
||||
: master_playlist_(new MasterPlaylist(kDefaultMasterPlaylistName,
|
||||
kDefaultAudioLanguage,
|
||||
kDefaultTextLanguage,
|
||||
!kIsIndependentSegments)),
|
||||
kDefaultAudioLanguage,
|
||||
kDefaultTextLanguage,
|
||||
!kIsIndependentSegments)),
|
||||
test_output_dir_("memory://test_dir"),
|
||||
master_playlist_path_(
|
||||
FilePath::FromUTF8Unsafe(test_output_dir_)
|
||||
.Append(FilePath::FromUTF8Unsafe(kDefaultMasterPlaylistName))
|
||||
.AsUTF8Unsafe()) {}
|
||||
master_playlist_path_(std::filesystem::u8path(test_output_dir_) /
|
||||
kDefaultMasterPlaylistName) {}
|
||||
|
||||
void SetUp() override { SetPackagerVersionForTesting("test"); }
|
||||
|
||||
std::unique_ptr<MasterPlaylist> master_playlist_;
|
||||
std::string test_output_dir_;
|
||||
std::string master_playlist_path_;
|
||||
std::filesystem::path master_playlist_path_;
|
||||
};
|
||||
|
||||
TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) {
|
||||
|
@ -166,7 +164,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideo) {
|
|||
{mock_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -200,7 +199,8 @@ TEST_F(MasterPlaylistTest,
|
|||
{mock_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -229,7 +229,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneVideoWithFrameRate) {
|
|||
{mock_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -257,7 +258,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistOneIframePlaylist) {
|
|||
{mock_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -312,7 +314,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudio) {
|
|||
spanish_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -372,7 +375,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMultipleAudioGroups) {
|
|||
{video_playlist.get(), eng_lo_playlist.get(), eng_hi_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -419,7 +423,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistSameAudioGroupSameLanguage) {
|
|||
{video_playlist.get(), eng_lo_playlist.get(), eng_hi_playlist.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -464,7 +469,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideosAndTexts) {
|
|||
{video1.get(), video2.get(), text_eng.get(), text_fr.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -506,7 +512,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextWithCharacteritics) {
|
|||
{video.get(), text.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -548,7 +555,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndDvsAudio) {
|
|||
kBaseUrl, test_output_dir_, {video.get(), dvs_audio.get(), audio.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -590,7 +598,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndTextGroups) {
|
|||
{video.get(), text_eng.get(), text_fr.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -636,7 +645,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistVideoAndAudioAndText) {
|
|||
kBaseUrl, test_output_dir_, {video.get(), audio.get(), text.get()}));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -709,7 +719,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistMixedPlaylistsDifferentGroups) {
|
|||
media_playlist_list));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -812,7 +823,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnly) {
|
|||
media_playlist_list));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -864,7 +876,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnlyJOC) {
|
|||
media_playlist_list));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -916,7 +929,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnlyAC4IMS) {
|
|||
media_playlist_list));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
@ -969,7 +983,8 @@ TEST_F(MasterPlaylistTest, WriteMasterPlaylistAudioOnlyAC4CBI) {
|
|||
media_playlist_list));
|
||||
|
||||
std::string actual;
|
||||
ASSERT_TRUE(File::ReadFileToString(master_playlist_path_.c_str(), &actual));
|
||||
ASSERT_TRUE(
|
||||
File::ReadFileToString(master_playlist_path_.string().c_str(), &actual));
|
||||
|
||||
const std::string expected =
|
||||
"#EXTM3U\n"
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <glog/logging.h>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/hls/base/tag.h"
|
||||
#include "packager/media/base/language_utils.h"
|
||||
|
@ -112,12 +112,12 @@ std::string CreatePlaylistHeader(
|
|||
std::string version_line;
|
||||
if (!version.empty()) {
|
||||
version_line =
|
||||
base::StringPrintf("## Generated with %s version %s\n",
|
||||
GetPackagerProjectUrl().c_str(), version.c_str());
|
||||
absl::StrFormat("## Generated with %s version %s\n",
|
||||
GetPackagerProjectUrl().c_str(), version.c_str());
|
||||
}
|
||||
|
||||
// 6 is required for EXT-X-MAP without EXT-X-I-FRAMES-ONLY.
|
||||
std::string header = base::StringPrintf(
|
||||
std::string header = absl::StrFormat(
|
||||
"#EXTM3U\n"
|
||||
"#EXT-X-VERSION:6\n"
|
||||
"%s"
|
||||
|
@ -133,20 +133,21 @@ std::string CreatePlaylistHeader(
|
|||
break;
|
||||
case HlsPlaylistType::kLive:
|
||||
if (media_sequence_number > 0) {
|
||||
base::StringAppendF(&header, "#EXT-X-MEDIA-SEQUENCE:%d\n",
|
||||
media_sequence_number);
|
||||
absl::StrAppendFormat(&header, "#EXT-X-MEDIA-SEQUENCE:%d\n",
|
||||
media_sequence_number);
|
||||
}
|
||||
if (discontinuity_sequence_number > 0) {
|
||||
base::StringAppendF(&header, "#EXT-X-DISCONTINUITY-SEQUENCE:%d\n",
|
||||
discontinuity_sequence_number);
|
||||
absl::StrAppendFormat(&header, "#EXT-X-DISCONTINUITY-SEQUENCE:%d\n",
|
||||
discontinuity_sequence_number);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NOTREACHED() << "Unexpected MediaPlaylistType " << static_cast<int>(type);
|
||||
NOTIMPLEMENTED() << "Unexpected MediaPlaylistType "
|
||||
<< static_cast<int>(type);
|
||||
}
|
||||
if (stream_type ==
|
||||
MediaPlaylist::MediaPlaylistStreamType::kVideoIFramesOnly) {
|
||||
base::StringAppendF(&header, "#EXT-X-I-FRAMES-ONLY\n");
|
||||
absl::StrAppendFormat(&header, "#EXT-X-I-FRAMES-ONLY\n");
|
||||
}
|
||||
|
||||
// Put EXT-X-MAP at the end since the rest of the playlist is about the
|
||||
|
@ -209,17 +210,17 @@ SegmentInfoEntry::SegmentInfoEntry(const std::string& file_name,
|
|||
previous_segment_end_offset_(previous_segment_end_offset) {}
|
||||
|
||||
std::string SegmentInfoEntry::ToString() {
|
||||
std::string result = base::StringPrintf("#EXTINF:%.3f,", duration_seconds_);
|
||||
std::string result = absl::StrFormat("#EXTINF:%.3f,", duration_seconds_);
|
||||
|
||||
if (use_byte_range_) {
|
||||
base::StringAppendF(&result, "\n#EXT-X-BYTERANGE:%" PRIu64,
|
||||
segment_file_size_);
|
||||
absl::StrAppendFormat(&result, "\n#EXT-X-BYTERANGE:%" PRIu64,
|
||||
segment_file_size_);
|
||||
if (previous_segment_end_offset_ + 1 != start_byte_offset_) {
|
||||
base::StringAppendF(&result, "@%" PRIu64, start_byte_offset_);
|
||||
absl::StrAppendFormat(&result, "@%" PRIu64, start_byte_offset_);
|
||||
}
|
||||
}
|
||||
|
||||
base::StringAppendF(&result, "\n%s", file_name_.c_str());
|
||||
absl::StrAppendFormat(&result, "\n%s", file_name_.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -445,7 +446,7 @@ void MediaPlaylist::AddKeyFrame(int64_t timestamp,
|
|||
stream_type_ = MediaPlaylistStreamType::kVideoIFramesOnly;
|
||||
use_byte_range_ = true;
|
||||
}
|
||||
key_frames_.push_back({timestamp, start_byte_offset, size});
|
||||
key_frames_.push_back({timestamp, start_byte_offset, size, std::string("")});
|
||||
}
|
||||
|
||||
void MediaPlaylist::AddEncryptionInfo(MediaPlaylist::EncryptionMethod method,
|
||||
|
@ -469,7 +470,7 @@ void MediaPlaylist::AddPlacementOpportunity() {
|
|||
entries_.emplace_back(new PlacementOpportunityEntry());
|
||||
}
|
||||
|
||||
bool MediaPlaylist::WriteToFile(const std::string& file_path) {
|
||||
bool MediaPlaylist::WriteToFile(const std::filesystem::path& file_path) {
|
||||
if (!target_duration_set_) {
|
||||
SetTargetDuration(ceil(GetLongestSegmentDuration()));
|
||||
}
|
||||
|
@ -479,14 +480,14 @@ bool MediaPlaylist::WriteToFile(const std::string& file_path) {
|
|||
media_sequence_number_, discontinuity_sequence_number_);
|
||||
|
||||
for (const auto& entry : entries_)
|
||||
base::StringAppendF(&content, "%s\n", entry->ToString().c_str());
|
||||
absl::StrAppendFormat(&content, "%s\n", entry->ToString().c_str());
|
||||
|
||||
if (hls_params_.playlist_type == HlsPlaylistType::kVod) {
|
||||
content += "#EXT-X-ENDLIST\n";
|
||||
}
|
||||
|
||||
if (!File::WriteFileAtomically(file_path.c_str(), content)) {
|
||||
LOG(ERROR) << "Failed to write playlist to: " << file_path;
|
||||
if (!File::WriteFileAtomically(file_path.string().c_str(), content)) {
|
||||
LOG(ERROR) << "Failed to write playlist to: " << file_path.string();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -691,7 +692,8 @@ void MediaPlaylist::SlideWindow() {
|
|||
} else if (entry_type == HlsEntry::EntryType::kExtDiscontinuity) {
|
||||
++discontinuity_sequence_number_;
|
||||
} else {
|
||||
DCHECK_EQ(entry_type, HlsEntry::EntryType::kExtInf);
|
||||
DCHECK_EQ(static_cast<int>(entry_type),
|
||||
static_cast<int>(HlsEntry::EntryType::kExtInf));
|
||||
|
||||
const SegmentInfoEntry& segment_info =
|
||||
*reinterpret_cast<SegmentInfoEntry*>(last->get());
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#ifndef PACKAGER_HLS_BASE_MEDIA_PLAYLIST_H_
|
||||
#define PACKAGER_HLS_BASE_MEDIA_PLAYLIST_H_
|
||||
|
||||
#include <filesystem>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/hls/public/hls_params.h"
|
||||
#include "packager/macros.h"
|
||||
#include "packager/mpd/base/bandwidth_estimator.h"
|
||||
#include "packager/mpd/base/media_info.pb.h"
|
||||
|
||||
|
@ -160,7 +161,7 @@ class MediaPlaylist {
|
|||
/// @param file_path is the output file path accepted by the File
|
||||
/// implementation.
|
||||
/// @return true on success, false otherwise.
|
||||
virtual bool WriteToFile(const std::string& file_path);
|
||||
virtual bool WriteToFile(const std::filesystem::path& file_path);
|
||||
|
||||
/// If bitrate is specified in MediaInfo then it will use that value.
|
||||
/// Otherwise, returns the max bitrate.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include <absl/strings/str_format.h>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/file/file_closer.h"
|
||||
#include "packager/file/file_test_util.h"
|
||||
|
@ -1032,8 +1032,8 @@ class MediaPlaylistDeleteSegmentsTest
|
|||
|
||||
std::string GetSegmentName(int index) {
|
||||
if (segment_template_.find("$Time$") != std::string::npos)
|
||||
return base::StringPrintf(kStringPrintTemplate, GetTime(index));
|
||||
return base::StringPrintf(kStringPrintTemplate, index + 1);
|
||||
return absl::StrFormat(kStringPrintTemplate, GetTime(index));
|
||||
return absl::StrFormat(kStringPrintTemplate, index + 1);
|
||||
}
|
||||
|
||||
bool SegmentDeleted(const std::string& segment_name) {
|
||||
|
|
|
@ -42,7 +42,7 @@ class MockMediaPlaylist : public MediaPlaylist {
|
|||
const std::string& key_format,
|
||||
const std::string& key_format_versions));
|
||||
MOCK_METHOD0(AddPlacementOpportunity, void());
|
||||
MOCK_METHOD1(WriteToFile, bool(const std::string& file_path));
|
||||
MOCK_METHOD1(WriteToFile, bool(const std::filesystem::path& file_path));
|
||||
MOCK_CONST_METHOD0(MaxBitrate, uint64_t());
|
||||
MOCK_CONST_METHOD0(AvgBitrate, uint64_t());
|
||||
MOCK_CONST_METHOD0(GetLongestSegmentDuration, double());
|
||||
|
|
|
@ -6,31 +6,29 @@
|
|||
|
||||
#include "packager/hls/base/simple_hls_notifier.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/flag.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "packager/base/base64.h"
|
||||
#include "packager/base/files/file_path.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/optional.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/hls/base/media_playlist.h"
|
||||
#include <absl/strings/escaping.h>
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <glog/logging.h>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include "packager/file/file_util.h"
|
||||
#include "packager/media/base/protection_system_ids.h"
|
||||
#include "packager/media/base/protection_system_specific_info.h"
|
||||
#include "packager/media/base/proto_json_util.h"
|
||||
#include "packager/media/base/widevine_pssh_data.pb.h"
|
||||
|
||||
DEFINE_bool(enable_legacy_widevine_hls_signaling,
|
||||
false,
|
||||
"Specifies whether Legacy Widevine HLS, i.e. v1 is signalled in "
|
||||
"the media playlist. Applies to Widevine protection system in HLS "
|
||||
"with SAMPLE-AES only.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_legacy_widevine_hls_signaling,
|
||||
false,
|
||||
"Specifies whether Legacy Widevine HLS, i.e. v1 is signalled in "
|
||||
"the media playlist. Applies to Widevine protection system in HLS "
|
||||
"with SAMPLE-AES only.");
|
||||
|
||||
namespace shaka {
|
||||
|
||||
using base::FilePath;
|
||||
|
||||
namespace hls {
|
||||
|
||||
namespace {
|
||||
|
@ -41,18 +39,18 @@ const char kWidevineDashIfIopUUID[] =
|
|||
"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed";
|
||||
|
||||
bool IsWidevineSystemId(const std::vector<uint8_t>& system_id) {
|
||||
return system_id.size() == arraysize(media::kWidevineSystemId) &&
|
||||
return system_id.size() == std::size(media::kWidevineSystemId) &&
|
||||
std::equal(system_id.begin(), system_id.end(),
|
||||
media::kWidevineSystemId);
|
||||
}
|
||||
|
||||
bool IsCommonSystemId(const std::vector<uint8_t>& system_id) {
|
||||
return system_id.size() == arraysize(media::kCommonSystemId) &&
|
||||
return system_id.size() == std::size(media::kCommonSystemId) &&
|
||||
std::equal(system_id.begin(), system_id.end(), media::kCommonSystemId);
|
||||
}
|
||||
|
||||
bool IsFairPlaySystemId(const std::vector<uint8_t>& system_id) {
|
||||
return system_id.size() == arraysize(media::kFairPlaySystemId) &&
|
||||
return system_id.size() == std::size(media::kFairPlaySystemId) &&
|
||||
std::equal(system_id.begin(), system_id.end(),
|
||||
media::kFairPlaySystemId);
|
||||
}
|
||||
|
@ -60,7 +58,7 @@ bool IsFairPlaySystemId(const std::vector<uint8_t>& system_id) {
|
|||
std::string Base64EncodeData(const std::string& prefix,
|
||||
const std::string& data) {
|
||||
std::string data_base64;
|
||||
base::Base64Encode(data, &data_base64);
|
||||
absl::Base64Escape(data, &data_base64);
|
||||
return prefix + data_base64;
|
||||
}
|
||||
|
||||
|
@ -68,33 +66,13 @@ std::string VectorToString(const std::vector<uint8_t>& v) {
|
|||
return std::string(v.begin(), v.end());
|
||||
}
|
||||
|
||||
// TODO(rkuroiwa): Dedup these with the functions in MpdBuilder.
|
||||
// If |media_path| is contained in |parent_path|, then
|
||||
// Strips the common path and keep only the relative part of |media_path|.
|
||||
// e.g. if |parent_path| is /some/parent/ and
|
||||
// |media_path| is /some/parent/abc/child/item.ext,
|
||||
// abc/child/item.ext is returned.
|
||||
// else
|
||||
// Returns |media_path|.
|
||||
// The path separator of the output is also changed to "/" if it is not.
|
||||
std::string MakePathRelative(const std::string& media_path,
|
||||
const FilePath& parent_path) {
|
||||
FilePath relative_path;
|
||||
const FilePath child_path = FilePath::FromUTF8Unsafe(media_path);
|
||||
const bool is_child =
|
||||
parent_path.AppendRelativePath(child_path, &relative_path);
|
||||
if (!is_child)
|
||||
relative_path = child_path;
|
||||
return relative_path.NormalizePathSeparatorsTo('/').AsUTF8Unsafe();
|
||||
}
|
||||
|
||||
// Segment URL is relative to either output directory or the directory
|
||||
// containing the media playlist depends on whether base_url is set.
|
||||
std::string GenerateSegmentUrl(const std::string& segment_name,
|
||||
const std::string& base_url,
|
||||
const std::string& output_dir,
|
||||
const std::string& playlist_file_name) {
|
||||
FilePath output_path = FilePath::FromUTF8Unsafe(output_dir);
|
||||
auto output_path = std::filesystem::u8path(output_dir);
|
||||
if (!base_url.empty()) {
|
||||
// Media segment URL is base_url + segment path relative to output
|
||||
// directory.
|
||||
|
@ -102,10 +80,8 @@ std::string GenerateSegmentUrl(const std::string& segment_name,
|
|||
}
|
||||
// Media segment URL is segment path relative to the directory containing the
|
||||
// playlist.
|
||||
const FilePath playlist_dir =
|
||||
output_path.Append(FilePath::FromUTF8Unsafe(playlist_file_name))
|
||||
.DirName()
|
||||
.AsEndingWithSeparator();
|
||||
const std::filesystem::path playlist_dir =
|
||||
(output_path / playlist_file_name).parent_path() / "";
|
||||
return MakePathRelative(segment_name, playlist_dir);
|
||||
}
|
||||
|
||||
|
@ -168,10 +144,12 @@ bool WidevinePsshToJson(const std::vector<uint8_t>& pssh_box,
|
|||
|
||||
// Place the current |key_id| to the front and converts all key_id to hex
|
||||
// format.
|
||||
widevine_header.add_key_ids(base::HexEncode(key_id.data(), key_id.size()));
|
||||
widevine_header.add_key_ids(absl::BytesToHexString(absl::string_view(
|
||||
reinterpret_cast<const char*>(key_id.data()), key_id.size())));
|
||||
for (const std::string& key_id_in_pssh : pssh_proto.key_id()) {
|
||||
const std::string key_id_hex =
|
||||
base::HexEncode(key_id_in_pssh.data(), key_id_in_pssh.size());
|
||||
const std::string key_id_hex = absl::BytesToHexString(
|
||||
absl::string_view(reinterpret_cast<const char*>(key_id_in_pssh.data()),
|
||||
key_id_in_pssh.size()));
|
||||
if (widevine_header.key_ids(0) != key_id_hex)
|
||||
widevine_header.add_key_ids(key_id_hex);
|
||||
}
|
||||
|
@ -180,7 +158,7 @@ bool WidevinePsshToJson(const std::vector<uint8_t>& pssh_box,
|
|||
return true;
|
||||
}
|
||||
|
||||
base::Optional<MediaPlaylist::EncryptionMethod> StringToEncryptionMethod(
|
||||
std::optional<MediaPlaylist::EncryptionMethod> StringToEncryptionMethod(
|
||||
const std::string& method) {
|
||||
if (method == "cenc") {
|
||||
return MediaPlaylist::EncryptionMethod::kSampleAesCenc;
|
||||
|
@ -192,7 +170,7 @@ base::Optional<MediaPlaylist::EncryptionMethod> StringToEncryptionMethod(
|
|||
// cbca is a place holder for sample aes.
|
||||
return MediaPlaylist::EncryptionMethod::kSampleAes;
|
||||
}
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void NotifyEncryptionToMediaPlaylist(
|
||||
|
@ -205,11 +183,15 @@ void NotifyEncryptionToMediaPlaylist(
|
|||
MediaPlaylist* media_playlist) {
|
||||
std::string iv_string;
|
||||
if (!iv.empty()) {
|
||||
iv_string = "0x" + base::HexEncode(iv.data(), iv.size());
|
||||
iv_string =
|
||||
"0x" + absl::BytesToHexString(absl::string_view(
|
||||
reinterpret_cast<const char*>(iv.data()), iv.size()));
|
||||
}
|
||||
std::string key_id_string;
|
||||
if (!key_id.empty()) {
|
||||
key_id_string = "0x" + base::HexEncode(key_id.data(), key_id.size());
|
||||
key_id_string = "0x" + absl::BytesToHexString(absl::string_view(
|
||||
reinterpret_cast<const char*>(key_id.data()),
|
||||
key_id.size()));
|
||||
}
|
||||
|
||||
media_playlist->AddEncryptionInfo(
|
||||
|
@ -225,7 +207,7 @@ bool HandleWidevineKeyFormats(
|
|||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& protection_system_specific_data,
|
||||
MediaPlaylist* media_playlist) {
|
||||
if (FLAGS_enable_legacy_widevine_hls_signaling &&
|
||||
if (absl::GetFlag(FLAGS_enable_legacy_widevine_hls_signaling) &&
|
||||
encryption_method == MediaPlaylist::EncryptionMethod::kSampleAes) {
|
||||
// This format allows SAMPLE-AES only.
|
||||
std::string key_uri_data;
|
||||
|
@ -253,12 +235,9 @@ bool HandleWidevineKeyFormats(
|
|||
|
||||
bool WriteMediaPlaylist(const std::string& output_dir,
|
||||
MediaPlaylist* playlist) {
|
||||
std::string file_path =
|
||||
FilePath::FromUTF8Unsafe(output_dir)
|
||||
.Append(FilePath::FromUTF8Unsafe(playlist->file_name()))
|
||||
.AsUTF8Unsafe();
|
||||
auto file_path = std::filesystem::u8path(output_dir) / playlist->file_name();
|
||||
if (!playlist->WriteToFile(file_path)) {
|
||||
LOG(ERROR) << "Failed to write playlist " << file_path;
|
||||
LOG(ERROR) << "Failed to write playlist " << file_path.string();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -280,18 +259,17 @@ std::unique_ptr<MediaPlaylist> MediaPlaylistFactory::Create(
|
|||
SimpleHlsNotifier::SimpleHlsNotifier(const HlsParams& hls_params)
|
||||
: HlsNotifier(hls_params),
|
||||
media_playlist_factory_(new MediaPlaylistFactory()) {
|
||||
const base::FilePath master_playlist_path(
|
||||
base::FilePath::FromUTF8Unsafe(hls_params.master_playlist_output));
|
||||
master_playlist_dir_ = master_playlist_path.DirName().AsUTF8Unsafe();
|
||||
const auto master_playlist_path =
|
||||
std::filesystem::u8path(hls_params.master_playlist_output);
|
||||
master_playlist_dir_ = master_playlist_path.parent_path().string();
|
||||
const std::string& default_audio_langauge = hls_params.default_language;
|
||||
const std::string& default_text_language =
|
||||
hls_params.default_text_language.empty()
|
||||
? hls_params.default_language
|
||||
: hls_params.default_text_language;
|
||||
master_playlist_.reset(
|
||||
new MasterPlaylist(master_playlist_path.BaseName().AsUTF8Unsafe(),
|
||||
default_audio_langauge, default_text_language,
|
||||
hls_params.is_independent_segments));
|
||||
master_playlist_.reset(new MasterPlaylist(
|
||||
master_playlist_path.filename(), default_audio_langauge,
|
||||
default_text_language, hls_params.is_independent_segments));
|
||||
}
|
||||
|
||||
SimpleHlsNotifier::~SimpleHlsNotifier() {}
|
||||
|
@ -308,7 +286,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
|
|||
DCHECK(stream_id);
|
||||
|
||||
const std::string relative_playlist_path = MakePathRelative(
|
||||
playlist_name, FilePath::FromUTF8Unsafe(master_playlist_dir_));
|
||||
playlist_name, std::filesystem::u8path(master_playlist_dir_));
|
||||
|
||||
std::unique_ptr<MediaPlaylist> media_playlist =
|
||||
media_playlist_factory_->Create(hls_params(), relative_playlist_path,
|
||||
|
@ -326,7 +304,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
|
|||
if (media_info.protected_content().has_protection_scheme()) {
|
||||
const std::string& protection_scheme =
|
||||
media_info.protected_content().protection_scheme();
|
||||
base::Optional<MediaPlaylist::EncryptionMethod> enc_method =
|
||||
std::optional<MediaPlaylist::EncryptionMethod> enc_method =
|
||||
StringToEncryptionMethod(protection_scheme);
|
||||
if (!enc_method) {
|
||||
LOG(ERROR) << "Failed to recognize protection scheme "
|
||||
|
@ -336,7 +314,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
|
|||
encryption_method = enc_method.value();
|
||||
}
|
||||
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
*stream_id = sequence_number_++;
|
||||
media_playlists_.push_back(media_playlist.get());
|
||||
stream_map_[*stream_id].reset(
|
||||
|
@ -346,7 +324,7 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
|
|||
|
||||
bool SimpleHlsNotifier::NotifySampleDuration(uint32_t stream_id,
|
||||
int32_t sample_duration) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
auto stream_iterator = stream_map_.find(stream_id);
|
||||
if (stream_iterator == stream_map_.end()) {
|
||||
LOG(ERROR) << "Cannot find stream with ID: " << stream_id;
|
||||
|
@ -363,7 +341,7 @@ bool SimpleHlsNotifier::NotifyNewSegment(uint32_t stream_id,
|
|||
int64_t duration,
|
||||
uint64_t start_byte_offset,
|
||||
uint64_t size) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
auto stream_iterator = stream_map_.find(stream_id);
|
||||
if (stream_iterator == stream_map_.end()) {
|
||||
LOG(ERROR) << "Cannot find stream with ID: " << stream_id;
|
||||
|
@ -412,7 +390,7 @@ bool SimpleHlsNotifier::NotifyKeyFrame(uint32_t stream_id,
|
|||
int64_t timestamp,
|
||||
uint64_t start_byte_offset,
|
||||
uint64_t size) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
auto stream_iterator = stream_map_.find(stream_id);
|
||||
if (stream_iterator == stream_map_.end()) {
|
||||
LOG(ERROR) << "Cannot find stream with ID: " << stream_id;
|
||||
|
@ -424,7 +402,7 @@ bool SimpleHlsNotifier::NotifyKeyFrame(uint32_t stream_id,
|
|||
}
|
||||
|
||||
bool SimpleHlsNotifier::NotifyCueEvent(uint32_t stream_id, int64_t timestamp) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
auto stream_iterator = stream_map_.find(stream_id);
|
||||
if (stream_iterator == stream_map_.end()) {
|
||||
LOG(ERROR) << "Cannot find stream with ID: " << stream_id;
|
||||
|
@ -441,7 +419,7 @@ bool SimpleHlsNotifier::NotifyEncryptionUpdate(
|
|||
const std::vector<uint8_t>& system_id,
|
||||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& protection_system_specific_data) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
auto stream_iterator = stream_map_.find(stream_id);
|
||||
if (stream_iterator == stream_map_.end()) {
|
||||
LOG(ERROR) << "Cannot find stream with ID: " << stream_id;
|
||||
|
@ -493,12 +471,14 @@ bool SimpleHlsNotifier::NotifyEncryptionUpdate(
|
|||
}
|
||||
|
||||
LOG(WARNING) << "HLS: Ignore unknown or unsupported system ID: "
|
||||
<< base::HexEncode(system_id.data(), system_id.size());
|
||||
<< absl::BytesToHexString(absl::string_view(
|
||||
reinterpret_cast<const char*>(system_id.data()),
|
||||
system_id.size()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleHlsNotifier::Flush() {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
absl::MutexLock lock(&lock_);
|
||||
for (MediaPlaylist* playlist : media_playlists_) {
|
||||
playlist->SetTargetDuration(target_duration_);
|
||||
if (!WriteMediaPlaylist(master_playlist_dir_, playlist))
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/base/synchronization/lock.h"
|
||||
#include <absl/synchronization/mutex.h>
|
||||
|
||||
#include "packager/hls/base/hls_notifier.h"
|
||||
#include "packager/hls/base/master_playlist.h"
|
||||
#include "packager/hls/base/media_playlist.h"
|
||||
#include "packager/hls/public/hls_params.h"
|
||||
#include "packager/macros.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace hls {
|
||||
|
@ -91,7 +92,7 @@ class SimpleHlsNotifier : public HlsNotifier {
|
|||
|
||||
uint32_t sequence_number_ = 0;
|
||||
|
||||
base::Lock lock_;
|
||||
absl::Mutex lock_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SimpleHlsNotifier);
|
||||
};
|
||||
|
|
|
@ -7,23 +7,26 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
#include <memory>
|
||||
|
||||
#include "packager/base/base64.h"
|
||||
#include "packager/base/files/file_path.h"
|
||||
#include <absl/strings/escaping.h>
|
||||
#include <filesystem>
|
||||
#include "packager/flag_saver.h"
|
||||
#include "packager/hls/base/mock_media_playlist.h"
|
||||
#include "packager/hls/base/simple_hls_notifier.h"
|
||||
#include "packager/media/base/protection_system_ids.h"
|
||||
#include "packager/media/base/protection_system_specific_info.h"
|
||||
#include "packager/media/base/widevine_pssh_data.pb.h"
|
||||
|
||||
DECLARE_bool(enable_legacy_widevine_hls_signaling);
|
||||
ABSL_DECLARE_FLAG(bool, enable_legacy_widevine_hls_signaling);
|
||||
|
||||
namespace shaka {
|
||||
namespace hls {
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::InSequence;
|
||||
|
@ -245,10 +248,8 @@ TEST_F(SimpleHlsNotifierTest, NotifyNewSegment) {
|
|||
EXPECT_CALL(*mock_media_playlist, SetTargetDuration(kTargetDuration))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
WriteToFile(StrEq(
|
||||
base::FilePath::FromUTF8Unsafe(kAnyOutputDir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe("playlist.m3u8"))
|
||||
.AsUTF8Unsafe())))
|
||||
WriteToFile(Eq(
|
||||
(std::filesystem::u8path(kAnyOutputDir) / "playlist.m3u8"))))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_TRUE(notifier.Flush());
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ TEST_F(SimpleHlsNotifierTest, NotifyEncryptionUpdateIdentityKey) {
|
|||
const std::vector<uint8_t> dummy_pssh_data(10, 'p');
|
||||
|
||||
std::string expected_key_uri_base64;
|
||||
base::Base64Encode(std::string(key_id.begin(), key_id.end()),
|
||||
absl::Base64Escape(std::string(key_id.begin(), key_id.end()),
|
||||
&expected_key_uri_base64);
|
||||
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
|
@ -557,10 +558,8 @@ TEST_P(LiveOrEventSimpleHlsNotifierTest, NotifyNewSegment) {
|
|||
EXPECT_CALL(*mock_media_playlist, SetTargetDuration(kTargetDuration))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
WriteToFile(StrEq(
|
||||
base::FilePath::FromUTF8Unsafe(kAnyOutputDir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe("playlist.m3u8"))
|
||||
.AsUTF8Unsafe())))
|
||||
WriteToFile(Eq(
|
||||
(std::filesystem::u8path(kAnyOutputDir) / "playlist.m3u8"))))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
hls_params_.playlist_type = GetParam();
|
||||
|
@ -627,18 +626,14 @@ TEST_P(LiveOrEventSimpleHlsNotifierTest, NotifyNewSegmentsWithMultipleStreams) {
|
|||
EXPECT_CALL(*mock_media_playlist1, SetTargetDuration(kTargetDuration))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mock_media_playlist1,
|
||||
WriteToFile(StrEq(
|
||||
base::FilePath::FromUTF8Unsafe(kAnyOutputDir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe("playlist1.m3u8"))
|
||||
.AsUTF8Unsafe())))
|
||||
WriteToFile(Eq(
|
||||
(std::filesystem::u8path(kAnyOutputDir) / "playlist1.m3u8"))))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*mock_media_playlist2, SetTargetDuration(kTargetDuration))
|
||||
.Times(1);
|
||||
EXPECT_CALL(*mock_media_playlist2,
|
||||
WriteToFile(StrEq(
|
||||
base::FilePath::FromUTF8Unsafe(kAnyOutputDir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe("playlist2.m3u8"))
|
||||
.AsUTF8Unsafe())))
|
||||
WriteToFile(Eq(
|
||||
(std::filesystem::u8path(kAnyOutputDir) / "playlist2.m3u8"))))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(
|
||||
*mock_master_playlist_ptr,
|
||||
|
@ -653,10 +648,8 @@ TEST_P(LiveOrEventSimpleHlsNotifierTest, NotifyNewSegmentsWithMultipleStreams) {
|
|||
.WillOnce(Return(kLongestSegmentDuration));
|
||||
// Not updating other playlists as target duration does not change.
|
||||
EXPECT_CALL(*mock_media_playlist2,
|
||||
WriteToFile(StrEq(
|
||||
base::FilePath::FromUTF8Unsafe(kAnyOutputDir)
|
||||
.Append(base::FilePath::FromUTF8Unsafe("playlist2.m3u8"))
|
||||
.AsUTF8Unsafe())))
|
||||
WriteToFile(Eq(
|
||||
(std::filesystem::u8path(kAnyOutputDir) / "playlist2.m3u8"))))
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(*mock_master_playlist_ptr, WriteMasterPlaylist(_, _, _))
|
||||
.WillOnce(Return(true));
|
||||
|
@ -673,12 +666,16 @@ class WidevineSimpleHlsNotifierTest : public SimpleHlsNotifierTest,
|
|||
public WithParamInterface<bool> {
|
||||
protected:
|
||||
WidevineSimpleHlsNotifierTest()
|
||||
: enable_legacy_widevine_hls_signaling_(GetParam()) {
|
||||
FLAGS_enable_legacy_widevine_hls_signaling =
|
||||
enable_legacy_widevine_hls_signaling_;
|
||||
: enable_legacy_widevine_hls_signaling_(GetParam()),
|
||||
saver(&FLAGS_enable_legacy_widevine_hls_signaling) {
|
||||
absl::SetFlag(&FLAGS_enable_legacy_widevine_hls_signaling,
|
||||
enable_legacy_widevine_hls_signaling_);
|
||||
}
|
||||
|
||||
bool enable_legacy_widevine_hls_signaling_ = false;
|
||||
|
||||
private:
|
||||
FlagSaver<bool> saver;
|
||||
};
|
||||
|
||||
TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdate) {
|
||||
|
@ -698,9 +695,9 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdate) {
|
|||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
};
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId));
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId));
|
||||
widevine_pssh_data.add_key_id()->assign(kAnyKeyId,
|
||||
kAnyKeyId + arraysize(kAnyKeyId));
|
||||
kAnyKeyId + std::size(kAnyKeyId));
|
||||
std::string widevine_pssh_data_str = widevine_pssh_data.SerializeAsString();
|
||||
|
||||
EXPECT_TRUE(!widevine_pssh_data_str.empty());
|
||||
|
@ -717,11 +714,11 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdate) {
|
|||
R"({"key_ids":["11223344112233441122334411223344"],)"
|
||||
R"("provider":"someprovider","content_id":"Y29udGVudGlk"})";
|
||||
std::string expected_json_base64;
|
||||
base::Base64Encode(kExpectedJson, &expected_json_base64);
|
||||
absl::Base64Escape(kExpectedJson, &expected_json_base64);
|
||||
|
||||
std::string expected_pssh_base64;
|
||||
const std::vector<uint8_t> pssh_box = pssh_builder.CreateBox();
|
||||
base::Base64Encode(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
absl::Base64Escape(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
&expected_pssh_base64);
|
||||
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
|
@ -763,7 +760,7 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateNoKeyidsInPssh) {
|
|||
R"({"key_ids":["11223344112233441122334411223344"],)"
|
||||
R"("provider":"someprovider","content_id":"Y29udGVudGlk"})";
|
||||
std::string expected_json_base64;
|
||||
base::Base64Encode(kExpectedJson, &expected_json_base64);
|
||||
absl::Base64Escape(kExpectedJson, &expected_json_base64);
|
||||
|
||||
media::PsshBoxBuilder pssh_builder;
|
||||
pssh_builder.set_pssh_data(pssh_data);
|
||||
|
@ -772,7 +769,7 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateNoKeyidsInPssh) {
|
|||
|
||||
std::string expected_pssh_base64;
|
||||
const std::vector<uint8_t> pssh_box = pssh_builder.CreateBox();
|
||||
base::Base64Encode(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
absl::Base64Escape(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
&expected_pssh_base64);
|
||||
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
|
@ -793,7 +790,7 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateNoKeyidsInPssh) {
|
|||
};
|
||||
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
||||
stream_id,
|
||||
std::vector<uint8_t>(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)),
|
||||
std::vector<uint8_t>(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId)),
|
||||
widevine_system_id_, iv, pssh_box));
|
||||
}
|
||||
|
||||
|
@ -821,14 +818,14 @@ TEST_P(WidevineSimpleHlsNotifierTest, MultipleKeyIdsNoContentIdInPssh) {
|
|||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
};
|
||||
std::vector<uint8_t> first_keyid(kFirstKeyId,
|
||||
kFirstKeyId + arraysize(kFirstKeyId));
|
||||
kFirstKeyId + std::size(kFirstKeyId));
|
||||
std::vector<uint8_t> second_keyid(kSecondKeyId,
|
||||
kSecondKeyId + arraysize(kSecondKeyId));
|
||||
kSecondKeyId + std::size(kSecondKeyId));
|
||||
|
||||
widevine_pssh_data.add_key_id()->assign(kFirstKeyId,
|
||||
kFirstKeyId + arraysize(kFirstKeyId));
|
||||
kFirstKeyId + std::size(kFirstKeyId));
|
||||
widevine_pssh_data.add_key_id()->assign(
|
||||
kSecondKeyId, kSecondKeyId + arraysize(kSecondKeyId));
|
||||
kSecondKeyId, kSecondKeyId + std::size(kSecondKeyId));
|
||||
std::string widevine_pssh_data_str = widevine_pssh_data.SerializeAsString();
|
||||
EXPECT_TRUE(!widevine_pssh_data_str.empty());
|
||||
std::vector<uint8_t> pssh_data(widevine_pssh_data_str.begin(),
|
||||
|
@ -847,11 +844,11 @@ TEST_P(WidevineSimpleHlsNotifierTest, MultipleKeyIdsNoContentIdInPssh) {
|
|||
R"("11111111111111111111111111111111"],)"
|
||||
R"("provider":"someprovider"})";
|
||||
std::string expected_json_base64;
|
||||
base::Base64Encode(kExpectedJson, &expected_json_base64);
|
||||
absl::Base64Escape(kExpectedJson, &expected_json_base64);
|
||||
|
||||
std::string expected_pssh_base64;
|
||||
const std::vector<uint8_t> pssh_box = pssh_builder.CreateBox();
|
||||
base::Base64Encode(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
absl::Base64Escape(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
&expected_pssh_base64);
|
||||
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
|
@ -893,9 +890,9 @@ TEST_P(WidevineSimpleHlsNotifierTest, CencEncryptionScheme) {
|
|||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
};
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId));
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId));
|
||||
widevine_pssh_data.add_key_id()->assign(kAnyKeyId,
|
||||
kAnyKeyId + arraysize(kAnyKeyId));
|
||||
kAnyKeyId + std::size(kAnyKeyId));
|
||||
std::string widevine_pssh_data_str = widevine_pssh_data.SerializeAsString();
|
||||
|
||||
EXPECT_TRUE(!widevine_pssh_data_str.empty());
|
||||
|
@ -904,7 +901,7 @@ TEST_P(WidevineSimpleHlsNotifierTest, CencEncryptionScheme) {
|
|||
|
||||
std::string expected_pssh_base64;
|
||||
const std::vector<uint8_t> pssh_box = {'p', 's', 's', 'h'};
|
||||
base::Base64Encode(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
absl::Base64Escape(std::string(pssh_box.begin(), pssh_box.end()),
|
||||
&expected_pssh_base64);
|
||||
|
||||
EXPECT_CALL(*mock_media_playlist,
|
||||
|
@ -932,9 +929,9 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateEmptyIv) {
|
|||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
0x11, 0x22, 0x33, 0x44, 0x11, 0x22, 0x33, 0x44,
|
||||
};
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId));
|
||||
std::vector<uint8_t> any_key_id(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId));
|
||||
widevine_pssh_data.add_key_id()->assign(kAnyKeyId,
|
||||
kAnyKeyId + arraysize(kAnyKeyId));
|
||||
kAnyKeyId + std::size(kAnyKeyId));
|
||||
std::string widevine_pssh_data_str = widevine_pssh_data.SerializeAsString();
|
||||
EXPECT_TRUE(!widevine_pssh_data_str.empty());
|
||||
std::vector<uint8_t> pssh_data(widevine_pssh_data_str.begin(),
|
||||
|
@ -944,7 +941,7 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateEmptyIv) {
|
|||
R"({"key_ids":["11223344112233441122334411223344"],)"
|
||||
R"("provider":"someprovider","content_id":"Y29udGVudGlk"})";
|
||||
std::string expected_json_base64;
|
||||
base::Base64Encode(kExpectedJson, &expected_json_base64);
|
||||
absl::Base64Escape(kExpectedJson, &expected_json_base64);
|
||||
|
||||
media::PsshBoxBuilder pssh_builder;
|
||||
pssh_builder.set_pssh_data(pssh_data);
|
||||
|
@ -971,13 +968,13 @@ TEST_P(WidevineSimpleHlsNotifierTest, NotifyEncryptionUpdateEmptyIv) {
|
|||
std::vector<uint8_t> pssh_as_vec = pssh_builder.CreateBox();
|
||||
std::string pssh_in_string(pssh_as_vec.begin(), pssh_as_vec.end());
|
||||
std::string base_64_encoded_pssh;
|
||||
base::Base64Encode(pssh_in_string, &base_64_encoded_pssh);
|
||||
absl::Base64Escape(pssh_in_string, &base_64_encoded_pssh);
|
||||
LOG(INFO) << base_64_encoded_pssh;
|
||||
|
||||
std::vector<uint8_t> empty_iv;
|
||||
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
||||
stream_id,
|
||||
std::vector<uint8_t>(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)),
|
||||
std::vector<uint8_t>(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId)),
|
||||
widevine_system_id_, empty_iv, pssh_builder.CreateBox()));
|
||||
}
|
||||
|
||||
|
|
|
@ -6,35 +6,34 @@
|
|||
|
||||
#include "packager/hls/base/tag.h"
|
||||
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace hls {
|
||||
|
||||
Tag::Tag(const std::string& name, std::string* buffer) : buffer_(buffer) {
|
||||
base::StringAppendF(buffer_, "%s:", name.c_str());
|
||||
absl::StrAppendFormat(buffer_, "%s:", name.c_str());
|
||||
}
|
||||
|
||||
void Tag::AddString(const std::string& key, const std::string& value) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=%s", key.c_str(), value.c_str());
|
||||
absl::StrAppendFormat(buffer_, "%s=%s", key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void Tag::AddQuotedString(const std::string& key, const std::string& value) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=\"%s\"", key.c_str(), value.c_str());
|
||||
absl::StrAppendFormat(buffer_, "%s=\"%s\"", key.c_str(), value.c_str());
|
||||
}
|
||||
|
||||
void Tag::AddNumber(const std::string& key, uint64_t value) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=%" PRIu64, key.c_str(), value);
|
||||
absl::StrAppendFormat(buffer_, "%s=%" PRIu64, key.c_str(), value);
|
||||
}
|
||||
|
||||
void Tag::AddFloat(const std::string& key, float value) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=%.3f", key.c_str(), value);
|
||||
absl::StrAppendFormat(buffer_, "%s=%.3f", key.c_str(), value);
|
||||
}
|
||||
|
||||
void Tag::AddNumberPair(const std::string& key,
|
||||
|
@ -42,8 +41,8 @@ void Tag::AddNumberPair(const std::string& key,
|
|||
char separator,
|
||||
uint64_t number2) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=%" PRIu64 "%c%" PRIu64, key.c_str(), number1,
|
||||
separator, number2);
|
||||
absl::StrAppendFormat(buffer_, "%s=%" PRIu64 "%c%" PRIu64, key.c_str(),
|
||||
number1, separator, number2);
|
||||
}
|
||||
|
||||
void Tag::AddQuotedNumberPair(const std::string& key,
|
||||
|
@ -51,8 +50,8 @@ void Tag::AddQuotedNumberPair(const std::string& key,
|
|||
char separator,
|
||||
uint64_t number2) {
|
||||
NextField();
|
||||
base::StringAppendF(buffer_, "%s=\"%" PRIu64 "%c%" PRIu64 "\"", key.c_str(),
|
||||
number1, separator, number2);
|
||||
absl::StrAppendFormat(buffer_, "%s=\"%" PRIu64 "%c%" PRIu64 "\"", key.c_str(),
|
||||
number1, separator, number2);
|
||||
}
|
||||
|
||||
void Tag::NextField() {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef PACKAGER_HLS_BASE_TAG_H_
|
||||
#define PACKAGER_HLS_BASE_TAG_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace shaka {
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
# Copyright 2016 Google LLC. All rights reserved.
|
||||
#
|
||||
# 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
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'shaka_code': 1,
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'hls_builder',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'base/hls_notifier.h',
|
||||
'base/master_playlist.cc',
|
||||
'base/master_playlist.h',
|
||||
'base/media_playlist.cc',
|
||||
'base/media_playlist.h',
|
||||
'base/simple_hls_notifier.cc',
|
||||
'base/simple_hls_notifier.h',
|
||||
'base/tag.cc',
|
||||
'base/tag.h',
|
||||
'public/hls_params.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'../base/base.gyp:base',
|
||||
'../file/file.gyp:file',
|
||||
'../media/base/media_base.gyp:media_base',
|
||||
'../media/base/media_base.gyp:widevine_pssh_data_proto',
|
||||
'../mpd/mpd.gyp:manifest_base',
|
||||
'../mpd/mpd.gyp:media_info_proto',
|
||||
'../third_party/gflags/gflags.gyp:gflags',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'hls_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'base/master_playlist_unittest.cc',
|
||||
'base/media_playlist_unittest.cc',
|
||||
'base/mock_media_playlist.cc',
|
||||
'base/mock_media_playlist.h',
|
||||
'base/simple_hls_notifier_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'../base/base.gyp:base',
|
||||
'../media/test/media_test.gyp:run_tests_with_atexit_manager',
|
||||
'../mpd/mpd.gyp:media_info_proto',
|
||||
'../testing/gmock.gyp:gmock',
|
||||
'../testing/gtest.gyp:gtest',
|
||||
'../third_party/gflags/gflags.gyp:gflags',
|
||||
'hls_builder',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
|
@ -31,8 +31,7 @@ target_link_libraries(mock_muxer_listener
|
|||
add_executable(media_event_unittest
|
||||
hls_notify_muxer_listener_unittest.cc
|
||||
muxer_listener_internal_unittest.cc
|
||||
# TODO(cmake): Re-enable when mpd/base is ported (needs MockMpdNotifier)
|
||||
# mpd_notify_muxer_listener_unittest.cc
|
||||
mpd_notify_muxer_listener_unittest.cc
|
||||
multi_codec_muxer_listener_unittest.cc
|
||||
muxer_listener_test_helper.cc
|
||||
vod_media_info_dump_muxer_listener_unittest.cc
|
||||
|
@ -40,6 +39,7 @@ add_executable(media_event_unittest
|
|||
target_link_libraries(media_event_unittest
|
||||
file
|
||||
file_test_util
|
||||
mpd_mocks
|
||||
mpd_media_info_proto
|
||||
gmock
|
||||
gtest
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "packager/file/file_util.h"
|
||||
#include "packager/media/base/rcheck.h"
|
||||
#include "packager/mpd/base/adaptation_set.h"
|
||||
#include "packager/mpd/base/mpd_utils.h"
|
||||
|
@ -88,17 +89,6 @@ bool SetIfPositive(const char* attr_name, double value, XmlNode* mpd) {
|
|||
mpd->SetStringAttribute(attr_name, SecondsToXmlDuration(value));
|
||||
}
|
||||
|
||||
std::string MakePathRelative(const std::filesystem::path& media_path,
|
||||
const std::filesystem::path& parent_path) {
|
||||
auto relative_path = std::filesystem::relative(media_path, parent_path);
|
||||
if (relative_path.empty() || *relative_path.begin() == "..") {
|
||||
// Not related.
|
||||
relative_path = media_path;
|
||||
}
|
||||
|
||||
return relative_path.lexically_normal().generic_string();
|
||||
}
|
||||
|
||||
// Spooky static initialization/cleanup of libxml.
|
||||
class LibXmlInitializer {
|
||||
public:
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
namespace shaka {
|
||||
|
||||
std::filesystem::path GetTestDataFilePath(const std::string& name) {
|
||||
auto data_dir = std::filesystem::path(TEST_DATA_DIR);
|
||||
auto data_dir = std::filesystem::u8path(TEST_DATA_DIR);
|
||||
return data_dir / name;
|
||||
}
|
||||
|
||||
std::filesystem::path GetSchemaPath() {
|
||||
auto schema_dir = std::filesystem::path(TEST_SCHEMA_DIR);
|
||||
auto schema_dir = std::filesystem::u8path(TEST_SCHEMA_DIR);
|
||||
return schema_dir / "DASH-MPD.xsd";
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
FROM archlinux:latest
|
||||
|
||||
# Install utilities, libraries, and dev tools.
|
||||
RUN pacman -Sy --needed --noconfirm \
|
||||
RUN pacman -Suy --needed --noconfirm \
|
||||
core/which \
|
||||
c-ares \
|
||||
cmake gcc git ninja python3
|
||||
|
|
|
@ -2,7 +2,7 @@ FROM tgagor/centos:stream9
|
|||
|
||||
# For CentOS, Ninja is only available from the "CRB" ("Code Ready Builder")
|
||||
# repo. Enable that first.
|
||||
RUN dnf update
|
||||
RUN dnf update -y
|
||||
RUN dnf install -y yum-utils
|
||||
RUN dnf config-manager --set-enabled crb
|
||||
|
||||
|
|
Loading…
Reference in New Issue