Add support for skip_encryption stream descriptor (#219)

This option makes it possible to control encryption for specific streams,
e.g. for audio and video separately.
This commit is contained in:
sylt 2017-05-22 19:17:58 +02:00 committed by Kongqun Yang
parent 3443048e80
commit bfe302bd5c
5 changed files with 58 additions and 2 deletions

View File

@ -107,7 +107,9 @@ const char kUsage[] =
" The group ID for the output stream. For HLS this is used as the\n" " The group ID for the output stream. For HLS this is used as the\n"
" GROUP-ID attribute for EXT-X-MEDIA.\n" " GROUP-ID attribute for EXT-X-MEDIA.\n"
" - playlist_name: Required for HLS output.\n" " - playlist_name: Required for HLS output.\n"
" Name of the playlist for the stream. Usually ends with '.m3u8'.\n"; " Name of the playlist for the stream. Usually ends with '.m3u8'.\n"
" - skip_encryption=0|1: Optional. Defaults to 0 if not specified. If\n"
" it is set to 1, no encryption of the stream will be made.\n";
const char kMediaInfoSuffix[] = ".media_info"; const char kMediaInfoSuffix[] = ".media_info";
@ -378,7 +380,7 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
handlers.push_back(chunking_handler); handlers.push_back(chunking_handler);
Status status; Status status;
if (encryption_key_source) { if (encryption_key_source && !stream_iter->skip_encryption) {
auto new_encryption_options = encryption_options; auto new_encryption_options = encryption_options;
// Use Sample AES in MPEG2TS. // Use Sample AES in MPEG2TS.
// TODO(kqyang): Consider adding a new flag to enable Sample AES as we // TODO(kqyang): Consider adding a new flag to enable Sample AES as we

View File

@ -31,6 +31,7 @@ enum FieldType {
kHlsGroupIdField, kHlsGroupIdField,
kHlsPlaylistNameField, kHlsPlaylistNameField,
kTrickPlayFactorField, kTrickPlayFactorField,
kSkipEncryptionField,
}; };
struct FieldNameToTypeMapping { struct FieldNameToTypeMapping {
@ -60,6 +61,7 @@ const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
{"playlist_name", kHlsPlaylistNameField}, {"playlist_name", kHlsPlaylistNameField},
{"trick_play_factor", kTrickPlayFactorField}, {"trick_play_factor", kTrickPlayFactorField},
{"tpf", kTrickPlayFactorField}, {"tpf", kTrickPlayFactorField},
{"skip_encryption", kSkipEncryptionField},
}; };
FieldType GetFieldType(const std::string& field_name) { FieldType GetFieldType(const std::string& field_name) {
@ -158,6 +160,21 @@ bool InsertStreamDescriptor(const std::string& descriptor_string,
descriptor.trick_play_factor = factor; descriptor.trick_play_factor = factor;
break; break;
} }
case kSkipEncryptionField: {
unsigned skip_encryption_value;
if (!base::StringToUint(iter->second, &skip_encryption_value)) {
LOG(ERROR) << "Non-numeric option for skip encryption field "
"specified (" << iter->second << ").";
return false;
}
if (skip_encryption_value > 1) {
LOG(ERROR) << "skip_encryption should be either 0 or 1.";
return false;
}
descriptor.skip_encryption = skip_encryption_value > 0;
break;
}
default: default:
LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
<< "\")."; << "\").";

View File

@ -34,6 +34,7 @@ struct StreamDescriptor {
std::string hls_group_id; std::string hls_group_id;
std::string hls_playlist_name; std::string hls_playlist_name;
uint32_t trick_play_factor = 0; uint32_t trick_play_factor = 0;
bool skip_encryption = false;
}; };
class StreamDescriptorCompareFn { class StreamDescriptorCompareFn {

View File

@ -240,6 +240,15 @@ class PackagerAppTest(unittest.TestCase):
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4') self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4') self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
def testPackageWithEncryptionOfOnlyVideoStream(self):
self.packager.Package(
self._GetStreams(['audio,skip_encryption=1', 'video']),
self._GetFlags(encryption=True))
self._DiffGold(self.output[0], 'bear-640x360-a-golden.mp4')
self._DiffGold(self.output[1], 'bear-640x360-v-cenc-golden.mp4')
self._DiffGold(self.mpd_output, 'bear-640x360-a-clear-v-cenc-golden.mpd')
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
def testPackageWithEncryptionAndTrickPlay(self): def testPackageWithEncryptionAndTrickPlay(self):
self.packager.Package( self.packager.Package(
self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']), self._GetStreams(['audio', 'video', 'video,trick_play_factor=1']),

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.76317S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
</ContentProtection>
<Representation id="0" bandwidth="885590" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
<BaseURL>output_video.mp4</BaseURL>
<SegmentBase indexRange="1091-1158" timescale="30000">
<Initialization range="0-1090"/>
</SegmentBase>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
<Representation id="1" bandwidth="126510" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
<BaseURL>output_audio_skip_encryption_1.mp4</BaseURL>
<SegmentBase indexRange="757-824" timescale="44100">
<Initialization range="0-756"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>