Creates directories in the output path if not exist
Also added end to end tests for single segment HLS and multi-segment HLS. Fixes #276 Change-Id: I27e5d57cdc3ab79a8e5ae0c3a8da46fcf2c467b6
This commit is contained in:
parent
c87c4c2327
commit
e889578a2d
|
@ -63,6 +63,7 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
language_override=None,
|
language_override=None,
|
||||||
output_format=None,
|
output_format=None,
|
||||||
live=False,
|
live=False,
|
||||||
|
hls=False,
|
||||||
test_files=None):
|
test_files=None):
|
||||||
if test_files is None:
|
if test_files is None:
|
||||||
test_files = ['bear-640x360.mp4']
|
test_files = ['bear-640x360.mp4']
|
||||||
|
@ -85,10 +86,8 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
|
|
||||||
if live:
|
if live:
|
||||||
if output_format == 'ts':
|
if output_format == 'ts':
|
||||||
stream = ('input=%s,stream=%s,segment_template=%s-$Number$.ts,'
|
stream = ('input=%s,stream=%s,segment_template=%s-$Number$.ts' %
|
||||||
'playlist_name=%s.m3u8' % (test_file, stream_descriptor,
|
(test_file, stream_descriptor, output_prefix))
|
||||||
output_prefix,
|
|
||||||
stream_descriptor))
|
|
||||||
else:
|
else:
|
||||||
stream = (
|
stream = (
|
||||||
'input=%s,stream=%s,init_segment=%s-init.mp4,'
|
'input=%s,stream=%s,init_segment=%s-init.mp4,'
|
||||||
|
@ -106,6 +105,8 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
stream += ',format=%s' % output_format
|
stream += ',format=%s' % output_format
|
||||||
if language_override:
|
if language_override:
|
||||||
stream += ',lang=%s' % language_override
|
stream += ',lang=%s' % language_override
|
||||||
|
if hls:
|
||||||
|
stream += ',playlist_name=%s.m3u8' % stream_descriptor
|
||||||
streams.append(stream)
|
streams.append(stream)
|
||||||
return streams
|
return streams
|
||||||
|
|
||||||
|
@ -417,9 +418,11 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
def testPackageAvcTs(self):
|
def testPackageAvcTs(self):
|
||||||
# Currently we only support live packaging for ts.
|
# Currently we only support live packaging for ts.
|
||||||
self.assertPackageSuccess(
|
self.assertPackageSuccess(
|
||||||
self._GetStreams(['audio', 'video'],
|
self._GetStreams(
|
||||||
|
['audio', 'video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['bear-640x360.ts']),
|
test_files=['bear-640x360.ts']),
|
||||||
self._GetFlags(output_hls=True))
|
self._GetFlags(output_hls=True))
|
||||||
self._DiffLiveGold(self.output[0],
|
self._DiffLiveGold(self.output[0],
|
||||||
|
@ -441,6 +444,7 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
['audio', 'video'],
|
['audio', 'video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['bear-640x360.ts']),
|
test_files=['bear-640x360.ts']),
|
||||||
self._GetFlags(
|
self._GetFlags(
|
||||||
output_hls=True,
|
output_hls=True,
|
||||||
|
@ -467,6 +471,7 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
['audio', 'video'],
|
['audio', 'video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['bear-640x360.ts']),
|
test_files=['bear-640x360.ts']),
|
||||||
self._GetFlags(
|
self._GetFlags(
|
||||||
encryption=True,
|
encryption=True,
|
||||||
|
@ -495,6 +500,7 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
['audio', 'video'],
|
['audio', 'video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['bear-640x360.ts']),
|
test_files=['bear-640x360.ts']),
|
||||||
self._GetFlags(
|
self._GetFlags(
|
||||||
output_hls=True,
|
output_hls=True,
|
||||||
|
@ -680,9 +686,11 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
def testPackageAvcTsWithEncryption(self):
|
def testPackageAvcTsWithEncryption(self):
|
||||||
# Currently we only support live packaging for ts.
|
# Currently we only support live packaging for ts.
|
||||||
self.assertPackageSuccess(
|
self.assertPackageSuccess(
|
||||||
self._GetStreams(['audio', 'video'],
|
self._GetStreams(
|
||||||
|
['audio', 'video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['bear-640x360.ts']),
|
test_files=['bear-640x360.ts']),
|
||||||
self._GetFlags(encryption=True, output_hls=True))
|
self._GetFlags(encryption=True, output_hls=True))
|
||||||
self._DiffLiveGold(self.output[0],
|
self._DiffLiveGold(self.output[0],
|
||||||
|
@ -708,6 +716,7 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
['video'],
|
['video'],
|
||||||
output_format='ts',
|
output_format='ts',
|
||||||
live=True,
|
live=True,
|
||||||
|
hls=True,
|
||||||
test_files=['sintel-1024x436.mp4']),
|
test_files=['sintel-1024x436.mp4']),
|
||||||
self._GetFlags(
|
self._GetFlags(
|
||||||
encryption=True,
|
encryption=True,
|
||||||
|
@ -844,6 +853,49 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
self._DiffMediaInfoGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
|
self._DiffMediaInfoGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
|
||||||
self._DiffMediaInfoGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
|
self._DiffMediaInfoGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
|
||||||
|
|
||||||
|
def testPackageWithHlsSingleSegmentMp4Encrypted(self):
|
||||||
|
self.assertPackageSuccess(
|
||||||
|
self._GetStreams(['audio', 'video'], hls=True),
|
||||||
|
self._GetFlags(encryption=True, output_hls=True))
|
||||||
|
self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
|
||||||
|
self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
|
||||||
|
self._DiffGold(self.hls_master_playlist_output,
|
||||||
|
'bear-640x360-av-mp4-master-cenc-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'audio.m3u8'),
|
||||||
|
'bear-640x360-a-mp4-cenc-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'video.m3u8'),
|
||||||
|
'bear-640x360-v-mp4-cenc-golden.m3u8')
|
||||||
|
|
||||||
|
# Test HLS with multi-segment mp4 and content in subdirectories.
|
||||||
|
def testPackageWithHlsMultiSegmentMp4WithCustomPath(self):
|
||||||
|
test_file = os.path.join(self.test_data_dir, 'bear-640x360.mp4')
|
||||||
|
# {tmp}/audio/audio-init.mp4, {tmp}/audio/audio-1.m4s etc.
|
||||||
|
audio_output_prefix = os.path.join(self.tmp_dir, 'audio', 'audio')
|
||||||
|
# {tmp}/video/video-init.mp4, {tmp}/video/video-1.m4s etc.
|
||||||
|
video_output_prefix = os.path.join(self.tmp_dir, 'video', 'video')
|
||||||
|
self.assertPackageSuccess(
|
||||||
|
[
|
||||||
|
'input=%s,stream=audio,init_segment=%s-init.mp4,'
|
||||||
|
'segment_template=%s-$Number$.m4s,playlist_name=audio/audio.m3u8' %
|
||||||
|
(test_file, audio_output_prefix, audio_output_prefix),
|
||||||
|
'input=%s,stream=video,init_segment=%s-init.mp4,'
|
||||||
|
'segment_template=%s-$Number$.m4s,playlist_name=video/video.m3u8' %
|
||||||
|
(test_file, video_output_prefix, video_output_prefix),
|
||||||
|
],
|
||||||
|
self._GetFlags(output_hls=True))
|
||||||
|
self._DiffLiveGold(audio_output_prefix, 'bear-640x360-a-live-golden')
|
||||||
|
self._DiffLiveGold(video_output_prefix, 'bear-640x360-v-live-golden')
|
||||||
|
self._DiffGold(self.hls_master_playlist_output,
|
||||||
|
'bear-640x360-av-mp4-master-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'audio', 'audio.m3u8'),
|
||||||
|
'bear-640x360-a-mp4-golden.m3u8')
|
||||||
|
self._DiffGold(
|
||||||
|
os.path.join(self.tmp_dir, 'video', 'video.m3u8'),
|
||||||
|
'bear-640x360-v-mp4-golden.m3u8')
|
||||||
|
|
||||||
def testPackageWithLiveProfile(self):
|
def testPackageWithLiveProfile(self):
|
||||||
self.assertPackageSuccess(
|
self.assertPackageSuccess(
|
||||||
self._GetStreams(['audio', 'video'], live=True), self._GetFlags())
|
self._GetStreams(['audio', 'video'], live=True), self._GetFlags())
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXT-X-MAP:URI="output_audio.mp4",BYTERANGE="967@0"
|
||||||
|
#EXT-X-KEY:METHOD=SAMPLE-AES-CENC,URI="data:text/plain;base64,MTIzNDU2Nzg5MDEyMzQ1Ng==",KEYFORMAT="identity"
|
||||||
|
#EXTINF:1.022,
|
||||||
|
#EXT-X-BYTERANGE:16655@1035
|
||||||
|
output_audio.mp4
|
||||||
|
#EXTINF:0.998,
|
||||||
|
#EXT-X-BYTERANGE:16650
|
||||||
|
output_audio.mp4
|
||||||
|
#EXTINF:0.743,
|
||||||
|
#EXT-X-BYTERANGE:10272
|
||||||
|
output_audio.mp4
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -0,0 +1,13 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXT-X-MAP:URI="audio-init.mp4"
|
||||||
|
#EXTINF:1.022,
|
||||||
|
audio-1.m4s
|
||||||
|
#EXTINF:0.998,
|
||||||
|
audio-2.m4s
|
||||||
|
#EXTINF:0.743,
|
||||||
|
audio-3.m4s
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -0,0 +1,5 @@
|
||||||
|
#EXTM3U
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="stream_0",URI="audio.m3u8"
|
||||||
|
#EXT-X-STREAM-INF:BANDWIDTH=1111147,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio"
|
||||||
|
video.m3u8
|
|
@ -0,0 +1,5 @@
|
||||||
|
#EXTM3U
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="stream_0",URI="audio/audio.m3u8"
|
||||||
|
#EXT-X-STREAM-INF:BANDWIDTH=1105129,CODECS="avc1.64001e,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio"
|
||||||
|
video/video.m3u8
|
|
@ -0,0 +1,17 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXT-X-MAP:URI="output_video.mp4",BYTERANGE="1091@0"
|
||||||
|
#EXT-X-KEY:METHOD=SAMPLE-AES-CENC,URI="data:text/plain;base64,MTIzNDU2Nzg5MDEyMzQ1Ng==",KEYFORMAT="identity"
|
||||||
|
#EXTINF:1.001,
|
||||||
|
#EXT-X-BYTERANGE:99313@1159
|
||||||
|
output_video.mp4
|
||||||
|
#EXTINF:1.001,
|
||||||
|
#EXT-X-BYTERANGE:122340
|
||||||
|
output_video.mp4
|
||||||
|
#EXTINF:0.734,
|
||||||
|
#EXT-X-BYTERANGE:80067
|
||||||
|
output_video.mp4
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -0,0 +1,13 @@
|
||||||
|
#EXTM3U
|
||||||
|
#EXT-X-VERSION:6
|
||||||
|
## Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>
|
||||||
|
#EXT-X-TARGETDURATION:2
|
||||||
|
#EXT-X-PLAYLIST-TYPE:VOD
|
||||||
|
#EXT-X-MAP:URI="video-init.mp4"
|
||||||
|
#EXTINF:1.001,
|
||||||
|
video-1.m4s
|
||||||
|
#EXTINF:1.001,
|
||||||
|
video-2.m4s
|
||||||
|
#EXTINF:0.734,
|
||||||
|
video-3.m4s
|
||||||
|
#EXT-X-ENDLIST
|
|
@ -105,8 +105,21 @@ bool LocalFile::Tell(uint64_t* position) {
|
||||||
LocalFile::~LocalFile() {}
|
LocalFile::~LocalFile() {}
|
||||||
|
|
||||||
bool LocalFile::Open() {
|
bool LocalFile::Open() {
|
||||||
internal_file_ = base::OpenFile(base::FilePath::FromUTF8Unsafe(file_name()),
|
base::FilePath file_path(base::FilePath::FromUTF8Unsafe(file_name()));
|
||||||
file_mode_.c_str());
|
|
||||||
|
// Create upper level directories for write mode.
|
||||||
|
if (file_mode_.find("w") != std::string::npos) {
|
||||||
|
base::File::Error error;
|
||||||
|
// The function returns success if the directories already exist.
|
||||||
|
if (!base::CreateDirectoryAndGetError(file_path.DirName(), &error)) {
|
||||||
|
LOG(ERROR) << "Failed to create directories for file '"
|
||||||
|
<< file_path.AsUTF8Unsafe()
|
||||||
|
<< "'. Error: " << base::File::ErrorToString(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal_file_ = base::OpenFile(file_path, file_mode_.c_str());
|
||||||
return (internal_file_ != NULL);
|
return (internal_file_ != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue