diff --git a/AUTHORS b/AUTHORS index 87504a5fd7..5aac736471 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,6 +20,7 @@ Anders Hasselqvist Audible <*@audible.com> Chun-da Chen Daniel CantarĂ­n +Dennis E. Mungai (Brainiarc7) Dolby Laboratories <*@dolby.com> Evgeny Zajcev Eyevinn Technology AB <*@eyevinn.se> @@ -27,13 +28,14 @@ Google LLC. <*@google.com> Ivi.ru LLC <*@ivi.ru> Leandro Moreira Leo Law +Meta Platforms, Inc. <*@meta.com> More Screens Ltd. <*@morescreens.net> Ole Andre Birkedal Philo Inc. <*@philo.com> Piotr Srebrny +Prakash Duggaraju Richard Eklycke Sanil Raut Sergio Ammirata The Chromium Authors <*@chromium.org> -Prakash Duggaraju -Dennis E. Mungai (Brainiarc7) + diff --git a/CONTRIBUTORS b/CONTRIBUTORS index eeeeaa47fb..f146ab0e21 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -27,8 +27,10 @@ Anders Hasselqvist Andreas Motl Bei Li Chun-da Chen +Cosmin Stejerean Daniel CantarĂ­n David Cavar +Dennis E. Mungai (Brainiarc7) Evgeny Zajcev Gabe Kopley Geoff Jukes @@ -42,6 +44,7 @@ Leo Law Marcus Spangenberg Ole Andre Birkedal Piotr Srebrny +Prakash Duggaraju Qingquan Wang Richard Eklycke Rintaro Kuroiwa @@ -52,5 +55,4 @@ Thomas Inskip Tim Lansen Vincent Nguyen Weiguo Shao -Prakash Duggaraju -Dennis E. Mungai (Brainiarc7) + diff --git a/packager/CMakeLists.txt b/packager/CMakeLists.txt index 76fbf93904..53c1f3a127 100644 --- a/packager/CMakeLists.txt +++ b/packager/CMakeLists.txt @@ -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) diff --git a/packager/file/file_util.cc b/packager/file/file_util.cc index eb4656e81a..7b4d5d1a06 100644 --- a/packager/file/file_util.cc +++ b/packager/file/file_util.cc @@ -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 diff --git a/packager/file/file_util.h b/packager/file/file_util.h index 156073adea..7dc71d1e45 100644 --- a/packager/file/file_util.h +++ b/packager/file/file_util.h @@ -4,6 +4,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include #include 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 diff --git a/packager/hls/CMakeLists.txt b/packager/hls/CMakeLists.txt new file mode 100644 index 0000000000..d186366213 --- /dev/null +++ b/packager/hls/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/packager/hls/base/master_playlist.cc b/packager/hls/base/master_playlist.cc index ec5849d2d9..257723fff8 100644 --- a/packager/hls/base/master_playlist.cc +++ b/packager/hls/base/master_playlist.cc @@ -10,10 +10,11 @@ #include -#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 +#include +#include +#include +#include #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(playlist.stream_type()); + NOTIMPLEMENTED() << "Cannot build STREAM-INFO tag for type " + << static_cast(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(playlist.stream_type()); + NOTIMPLEMENTED() << "Cannot build media tag for type " + << static_cast(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& 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; diff --git a/packager/hls/base/master_playlist.h b/packager/hls/base/master_playlist.h index 6f88a52bb2..a6708514ba 100644 --- a/packager/hls/base/master_playlist.h +++ b/packager/hls/base/master_playlist.h @@ -7,6 +7,7 @@ #ifndef PACKAGER_HLS_BASE_MASTER_PLAYLIST_H_ #define PACKAGER_HLS_BASE_MASTER_PLAYLIST_H_ +#include #include #include @@ -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_; diff --git a/packager/hls/base/master_playlist_unittest.cc b/packager/hls/base/master_playlist_unittest.cc index 23f5b09017..9de3281325 100644 --- a/packager/hls/base/master_playlist_unittest.cc +++ b/packager/hls/base/master_playlist_unittest.cc @@ -7,7 +7,7 @@ #include #include -#include "packager/base/files/file_path.h" +#include #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 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" diff --git a/packager/hls/base/media_playlist.cc b/packager/hls/base/media_playlist.cc index 9898779271..34ae6c0f0b 100644 --- a/packager/hls/base/media_playlist.cc +++ b/packager/hls/base/media_playlist.cc @@ -12,9 +12,9 @@ #include #include -#include "packager/base/logging.h" -#include "packager/base/strings/string_number_conversions.h" -#include "packager/base/strings/stringprintf.h" +#include +#include +#include #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(type); + NOTIMPLEMENTED() << "Unexpected MediaPlaylistType " + << static_cast(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(entry_type), + static_cast(HlsEntry::EntryType::kExtInf)); const SegmentInfoEntry& segment_info = *reinterpret_cast(last->get()); diff --git a/packager/hls/base/media_playlist.h b/packager/hls/base/media_playlist.h index a17ca0bbb6..6566f155eb 100644 --- a/packager/hls/base/media_playlist.h +++ b/packager/hls/base/media_playlist.h @@ -7,13 +7,14 @@ #ifndef PACKAGER_HLS_BASE_MEDIA_PLAYLIST_H_ #define PACKAGER_HLS_BASE_MEDIA_PLAYLIST_H_ +#include #include #include #include #include -#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. diff --git a/packager/hls/base/media_playlist_unittest.cc b/packager/hls/base/media_playlist_unittest.cc index c8b565b597..520b6dd10a 100644 --- a/packager/hls/base/media_playlist_unittest.cc +++ b/packager/hls/base/media_playlist_unittest.cc @@ -7,7 +7,7 @@ #include #include -#include "packager/base/strings/stringprintf.h" +#include #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) { diff --git a/packager/hls/base/mock_media_playlist.h b/packager/hls/base/mock_media_playlist.h index d224d8fd54..4b046a1492 100644 --- a/packager/hls/base/mock_media_playlist.h +++ b/packager/hls/base/mock_media_playlist.h @@ -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()); diff --git a/packager/hls/base/simple_hls_notifier.cc b/packager/hls/base/simple_hls_notifier.cc index 3b76b06598..68b717d015 100644 --- a/packager/hls/base/simple_hls_notifier.cc +++ b/packager/hls/base/simple_hls_notifier.cc @@ -6,31 +6,29 @@ #include "packager/hls/base/simple_hls_notifier.h" -#include +#include #include -#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 +#include +#include +#include +#include +#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& 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& 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& 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& 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& 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& 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(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(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& pssh_box, return true; } -base::Optional StringToEncryptionMethod( +std::optional StringToEncryptionMethod( const std::string& method) { if (method == "cenc") { return MediaPlaylist::EncryptionMethod::kSampleAesCenc; @@ -192,7 +170,7 @@ base::Optional 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(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(key_id.data()), + key_id.size())); } media_playlist->AddEncryptionInfo( @@ -225,7 +207,7 @@ bool HandleWidevineKeyFormats( const std::vector& iv, const std::vector& 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 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 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 enc_method = + std::optional 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& system_id, const std::vector& iv, const std::vector& 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(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)) diff --git a/packager/hls/base/simple_hls_notifier.h b/packager/hls/base/simple_hls_notifier.h index bfc886af30..3970fa588a 100644 --- a/packager/hls/base/simple_hls_notifier.h +++ b/packager/hls/base/simple_hls_notifier.h @@ -13,12 +13,13 @@ #include #include -#include "packager/base/macros.h" -#include "packager/base/synchronization/lock.h" +#include + #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); }; diff --git a/packager/hls/base/simple_hls_notifier_unittest.cc b/packager/hls/base/simple_hls_notifier_unittest.cc index 3bc8fb4c31..1aec3b131d 100644 --- a/packager/hls/base/simple_hls_notifier_unittest.cc +++ b/packager/hls/base/simple_hls_notifier_unittest.cc @@ -7,23 +7,26 @@ #include #include -#include +#include +#include #include -#include "packager/base/base64.h" -#include "packager/base/files/file_path.h" +#include +#include +#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 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 { 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 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 any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)); + std::vector 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 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 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(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)), + std::vector(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 first_keyid(kFirstKeyId, - kFirstKeyId + arraysize(kFirstKeyId)); + kFirstKeyId + std::size(kFirstKeyId)); std::vector 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 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 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 any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)); + std::vector 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 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 any_key_id(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)); + std::vector 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 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 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 empty_iv; EXPECT_TRUE(notifier.NotifyEncryptionUpdate( stream_id, - std::vector(kAnyKeyId, kAnyKeyId + arraysize(kAnyKeyId)), + std::vector(kAnyKeyId, kAnyKeyId + std::size(kAnyKeyId)), widevine_system_id_, empty_iv, pssh_builder.CreateBox())); } diff --git a/packager/hls/base/tag.cc b/packager/hls/base/tag.cc index 062fa2ab7f..2779d1995f 100644 --- a/packager/hls/base/tag.cc +++ b/packager/hls/base/tag.cc @@ -6,35 +6,34 @@ #include "packager/hls/base/tag.h" +#include #include -#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() { diff --git a/packager/hls/base/tag.h b/packager/hls/base/tag.h index 2ee3f05192..31a949ae30 100644 --- a/packager/hls/base/tag.h +++ b/packager/hls/base/tag.h @@ -7,6 +7,7 @@ #ifndef PACKAGER_HLS_BASE_TAG_H_ #define PACKAGER_HLS_BASE_TAG_H_ +#include #include namespace shaka { diff --git a/packager/hls/hls.gyp b/packager/hls/hls.gyp deleted file mode 100644 index 8f73bb8088..0000000000 --- a/packager/hls/hls.gyp +++ /dev/null @@ -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', - ], - }, - ], -} diff --git a/packager/media/event/CMakeLists.txt b/packager/media/event/CMakeLists.txt index 04d59477ee..92cda21792 100644 --- a/packager/media/event/CMakeLists.txt +++ b/packager/media/event/CMakeLists.txt @@ -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 diff --git a/packager/mpd/base/mpd_builder.cc b/packager/mpd/base/mpd_builder.cc index 14fa259e01..25c580d01a 100644 --- a/packager/mpd/base/mpd_builder.cc +++ b/packager/mpd/base/mpd_builder.cc @@ -15,6 +15,7 @@ #include #include +#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: diff --git a/packager/mpd/test/mpd_builder_test_helper.cc b/packager/mpd/test/mpd_builder_test_helper.cc index 30bfbbefcb..00d84ebad2 100644 --- a/packager/mpd/test/mpd_builder_test_helper.cc +++ b/packager/mpd/test/mpd_builder_test_helper.cc @@ -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"; } diff --git a/packager/testing/dockers/ArchLinux_Dockerfile b/packager/testing/dockers/ArchLinux_Dockerfile index 91311b04a4..35906e3266 100644 --- a/packager/testing/dockers/ArchLinux_Dockerfile +++ b/packager/testing/dockers/ArchLinux_Dockerfile @@ -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 diff --git a/packager/testing/dockers/CentOS_Dockerfile b/packager/testing/dockers/CentOS_Dockerfile index dacb1ffa25..59ba28260b 100644 --- a/packager/testing/dockers/CentOS_Dockerfile +++ b/packager/testing/dockers/CentOS_Dockerfile @@ -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