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:
KongQun Yang 2017-10-10 14:54:36 -07:00
parent c87c4c2327
commit e889578a2d
8 changed files with 149 additions and 14 deletions

View File

@ -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())

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
} }