Support absolute file path in playlist_name

Fixes #585.

Change-Id: Icd0bc97a0b210c22a2dab716542d993a69d3d081
This commit is contained in:
KongQun Yang 2019-04-30 15:29:37 -07:00
parent ac616f36e4
commit adc3c804a9
4 changed files with 60 additions and 34 deletions

View File

@ -61,7 +61,8 @@ class MediaPlaylist {
}; };
/// @param hls_params contains HLS parameters. /// @param hls_params contains HLS parameters.
/// @param file_name is the file name of this media playlist. /// @param file_name is the file name of this media playlist, relative to
/// master playlist output path.
/// @param name is the name of this playlist. In other words this is the /// @param name is the name of this playlist. In other words this is the
/// value of the NAME attribute for EXT-X-MEDIA. This is not /// value of the NAME attribute for EXT-X-MEDIA. This is not
/// necessarily the same as @a file_name. /// necessarily the same as @a file_name.

View File

@ -281,7 +281,7 @@ SimpleHlsNotifier::SimpleHlsNotifier(const HlsParams& hls_params)
media_playlist_factory_(new MediaPlaylistFactory()) { media_playlist_factory_(new MediaPlaylistFactory()) {
const base::FilePath master_playlist_path( const base::FilePath master_playlist_path(
base::FilePath::FromUTF8Unsafe(hls_params.master_playlist_output)); base::FilePath::FromUTF8Unsafe(hls_params.master_playlist_output));
output_dir_ = master_playlist_path.DirName().AsUTF8Unsafe(); master_playlist_dir_ = master_playlist_path.DirName().AsUTF8Unsafe();
const std::string& default_audio_langauge = hls_params.default_language; const std::string& default_audio_langauge = hls_params.default_language;
const std::string& default_text_language = const std::string& default_text_language =
hls_params.default_text_language.empty() hls_params.default_text_language.empty()
@ -305,11 +305,14 @@ bool SimpleHlsNotifier::NotifyNewStream(const MediaInfo& media_info,
uint32_t* stream_id) { uint32_t* stream_id) {
DCHECK(stream_id); DCHECK(stream_id);
const std::string relative_playlist_path = MakePathRelative(
playlist_name, FilePath::FromUTF8Unsafe(master_playlist_dir_));
std::unique_ptr<MediaPlaylist> media_playlist = std::unique_ptr<MediaPlaylist> media_playlist =
media_playlist_factory_->Create(hls_params(), playlist_name, name, media_playlist_factory_->Create(hls_params(), relative_playlist_path,
group_id); name, group_id);
MediaInfo adjusted_media_info = MakeMediaInfoPathsRelativeToPlaylist( MediaInfo adjusted_media_info = MakeMediaInfoPathsRelativeToPlaylist(
media_info, hls_params().base_url, output_dir_, media_info, hls_params().base_url, master_playlist_dir_,
media_playlist->file_name()); media_playlist->file_name());
if (!media_playlist->SetMediaInfo(adjusted_media_info)) { if (!media_playlist->SetMediaInfo(adjusted_media_info)) {
LOG(ERROR) << "Failed to set media info for playlist " << playlist_name; LOG(ERROR) << "Failed to set media info for playlist " << playlist_name;
@ -353,8 +356,8 @@ bool SimpleHlsNotifier::NotifyNewSegment(uint32_t stream_id,
} }
auto& media_playlist = stream_iterator->second->media_playlist; auto& media_playlist = stream_iterator->second->media_playlist;
const std::string& segment_url = const std::string& segment_url =
GenerateSegmentUrl(segment_name, hls_params().base_url, output_dir_, GenerateSegmentUrl(segment_name, hls_params().base_url,
media_playlist->file_name()); master_playlist_dir_, media_playlist->file_name());
media_playlist->AddSegment(segment_url, start_time, duration, media_playlist->AddSegment(segment_url, start_time, duration,
start_byte_offset, size); start_byte_offset, size);
@ -374,15 +377,15 @@ bool SimpleHlsNotifier::NotifyNewSegment(uint32_t stream_id,
if (target_duration_updated) { if (target_duration_updated) {
for (MediaPlaylist* playlist : media_playlists_) { for (MediaPlaylist* playlist : media_playlists_) {
playlist->SetTargetDuration(target_duration_); playlist->SetTargetDuration(target_duration_);
if (!WriteMediaPlaylist(output_dir_, playlist)) if (!WriteMediaPlaylist(master_playlist_dir_, playlist))
return false; return false;
} }
} else { } else {
if (!WriteMediaPlaylist(output_dir_, media_playlist.get())) if (!WriteMediaPlaylist(master_playlist_dir_, media_playlist.get()))
return false; return false;
} }
if (!master_playlist_->WriteMasterPlaylist(hls_params().base_url, if (!master_playlist_->WriteMasterPlaylist(
output_dir_, media_playlists_)) { hls_params().base_url, master_playlist_dir_, media_playlists_)) {
LOG(ERROR) << "Failed to write master playlist."; LOG(ERROR) << "Failed to write master playlist.";
return false; return false;
} }
@ -482,11 +485,11 @@ bool SimpleHlsNotifier::Flush() {
base::AutoLock auto_lock(lock_); base::AutoLock auto_lock(lock_);
for (MediaPlaylist* playlist : media_playlists_) { for (MediaPlaylist* playlist : media_playlists_) {
playlist->SetTargetDuration(target_duration_); playlist->SetTargetDuration(target_duration_);
if (!WriteMediaPlaylist(output_dir_, playlist)) if (!WriteMediaPlaylist(master_playlist_dir_, playlist))
return false; return false;
} }
if (!master_playlist_->WriteMasterPlaylist(hls_params().base_url, output_dir_, if (!master_playlist_->WriteMasterPlaylist(
media_playlists_)) { hls_params().base_url, master_playlist_dir_, media_playlists_)) {
LOG(ERROR) << "Failed to write master playlist."; LOG(ERROR) << "Failed to write master playlist.";
return false; return false;
} }

View File

@ -77,7 +77,7 @@ class SimpleHlsNotifier : public HlsNotifier {
MediaPlaylist::EncryptionMethod encryption_method; MediaPlaylist::EncryptionMethod encryption_method;
}; };
std::string output_dir_; std::string master_playlist_dir_;
uint32_t target_duration_ = 0; uint32_t target_duration_ = 0;
std::unique_ptr<MediaPlaylistFactory> media_playlist_factory_; std::unique_ptr<MediaPlaylistFactory> media_playlist_factory_;

View File

@ -379,6 +379,8 @@ struct RebaseUrlTestData {
std::string master_playlist_dir; std::string master_playlist_dir;
// Media playlist path. This may be relative or absolute. // Media playlist path. This may be relative or absolute.
std::string playlist_path; std::string playlist_path;
// Expected relative playlist path. It is path_relative_to(master_directory).
std::string expected_relative_playlist_path;
// Media segment path. This may be relative or absolute. // Media segment path. This may be relative or absolute.
std::string segment_path; std::string segment_path;
// Expected segment URL in the media playlist: // Expected segment URL in the media playlist:
@ -421,7 +423,7 @@ TEST_P(SimpleHlsNotifierRebaseUrlTest, Test) {
// Pointer released by SimpleHlsNotifier. // Pointer released by SimpleHlsNotifier.
MockMediaPlaylist* mock_media_playlist = MockMediaPlaylist* mock_media_playlist =
new MockMediaPlaylist(test_data_.playlist_path, "", ""); new MockMediaPlaylist(test_data_.expected_relative_playlist_path, "", "");
EXPECT_CALL( EXPECT_CALL(
*mock_media_playlist, *mock_media_playlist,
@ -433,7 +435,8 @@ TEST_P(SimpleHlsNotifierRebaseUrlTest, Test) {
EXPECT_CALL(*mock_media_playlist, EXPECT_CALL(*mock_media_playlist,
AddSegment(test_data_.expected_segment_url, _, _, _, _)); AddSegment(test_data_.expected_segment_url, _, _, _, _));
} }
EXPECT_CALL(*factory, CreateMock(_, StrEq(test_data_.playlist_path), EXPECT_CALL(*factory,
CreateMock(_, StrEq(test_data_.expected_relative_playlist_path),
StrEq("name"), StrEq("groupid"))) StrEq("name"), StrEq("groupid")))
.WillOnce(Return(mock_media_playlist)); .WillOnce(Return(mock_media_playlist));
@ -459,35 +462,54 @@ INSTANTIATE_TEST_CASE_P(
SimpleHlsNotifierRebaseUrlTest, SimpleHlsNotifierRebaseUrlTest,
::testing::Values( ::testing::Values(
// Verify relative segment path. // Verify relative segment path.
RebaseUrlTestData{ RebaseUrlTestData{"http://testprefix.com/", "master_directory/",
"http://testprefix.com/", "master_directory/", "video_playlist.m3u8", "video_playlist.m3u8",
"video_playlist.m3u8", "master_directory/path/to/media1.ts", "master_directory/path/to/media1.ts",
"http://testprefix.com/path/to/media1.ts", "http://testprefix.com/path/to/media1.ts",
"" /* init segment path */, "" /* expected init segment url */}, "" /* init segment path */,
"" /* expected init segment url */},
// Verify relative init segment path. // Verify relative init segment path.
RebaseUrlTestData{"http://testprefix.com/", "master_directory/", RebaseUrlTestData{"http://testprefix.com/", "master_directory/",
"video_playlist.m3u8", "" /* segment path */, "video_playlist.m3u8", "video_playlist.m3u8",
"" /* expected segment url */, "" /* segment path */, "" /* expected segment url */,
"master_directory/path/to/init.mp4", "master_directory/path/to/init.mp4",
"http://testprefix.com/path/to/init.mp4"}, "http://testprefix.com/path/to/init.mp4"},
// Verify segment url relative to playlist. // Verify segment url relative to playlist.
RebaseUrlTestData{ RebaseUrlTestData{
"" /* no base_url */, "master_directory/", "" /* no base url */, "master_directory/",
"video/video_playlist.m3u8", "video/video_playlist.m3u8", "video/video_playlist.m3u8",
"master_directory/video/path/to/media1.m4s", "path/to/media1.m4s", "master_directory/video/path/to/media1.m4s", "path/to/media1.m4s",
"master_directory/video/path/to/init.mp4", "path/to/init.mp4"}, "master_directory/video/path/to/init.mp4", "path/to/init.mp4"},
// Verify absolute directory. // Verify absolute directory.
RebaseUrlTestData{ RebaseUrlTestData{
"http://testprefix.com/", "/tmp/something/", "video_playlist.m3u8", "http://testprefix.com/", "/tmp/something/", "video_playlist.m3u8",
"/tmp/something/media1.ts", "http://testprefix.com/media1.ts", "video_playlist.m3u8", "/tmp/something/media1.ts",
"" /* init segment path */, "" /* expected init segment url */}, "http://testprefix.com/media1.ts", "" /* init segment path */,
"" /* expected init segment url */},
// Verify absolute directory, but media in a different directory. // Verify absolute directory, but media in a different directory.
// Note that we don't really expect this in practice. // Note that we don't really expect this in practice.
RebaseUrlTestData{"http://testprefix.com/", "/tmp/something/", RebaseUrlTestData{
"http://testprefix.com/", "/tmp/something/", "video_playlist.m3u8",
"video_playlist.m3u8", "/var/somewhereelse/media1.ts", "video_playlist.m3u8", "/var/somewhereelse/media1.ts",
"http://testprefix.com//var/somewhereelse/media1.ts", "http://testprefix.com//var/somewhereelse/media1.ts",
"" /* init segment path */, "" /* init segment path */, "" /* expected init segment url */
"" /* expected init segment url */})); },
// Verify absolute directory, absolute media playlist path.
RebaseUrlTestData{
"http://testprefix.com/", "/tmp/something/",
"/tmp/something/video/video_playlist.m3u8",
"video/video_playlist.m3u8", "/tmp/something/video/media1.ts",
"http://testprefix.com/video/media1.ts", "" /* init segment path */,
"" /* expected init segment url */
},
// Same as above, but without base_url.
RebaseUrlTestData{
"" /* no base url */, "/tmp/something/",
"/tmp/something/video/video_playlist.m3u8",
"video/video_playlist.m3u8", "/tmp/something/video/media1.ts",
"media1.ts", "" /* init segment path */,
"" /* expected init segment url */
}));
class LiveOrEventSimpleHlsNotifierTest class LiveOrEventSimpleHlsNotifierTest
: public SimpleHlsNotifierTest, : public SimpleHlsNotifierTest,