diff --git a/README.md b/README.md
index 99b20398f3..43166fd7c5 100644
--- a/README.md
+++ b/README.md
@@ -16,28 +16,30 @@ Shaka Packager supports:
- [HLS](https://developer.apple.com/streaming/)
- Key systems:
- [Widevine](http://www.widevine.com/)
- - [PlayReady](https://www.microsoft.com/playready/)1
- - [Fairplay](https://developer.apple.com/streaming/fps/)1
+ - [PlayReady](https://www.microsoft.com/playready/)¹
+ - [Fairplay](https://developer.apple.com/streaming/fps/)¹
- Encryption standards:
- [CENC](https://en.wikipedia.org/wiki/MPEG_Common_Encryption)
- [SAMPLE-AES](https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption/Intro/Intro.html)
- Media Containers and codecs
- | Codecs | ISO-BMFF | WebM | MPEG2-TS | WVM |
- |:-----------------:|:------------:|:------------:|:------------:|:-----------:|
- | H264 (AVC) | I / O | - | I / O | I |
- | H265 (HEVC) | I / O | - | I | - |
- | VP8 | I / O | I / O | - | - |
- | VP9 | I / O | I / O | - | - |
- | AAC | I / O | - | I / O | I |
- | Dolby AC3/EAC3 | I / O | - | I | - |
- | DTS | I / O | - | - | - |
- | FLAC | I / O | - | - | - |
- | Opus | *I / O* | I / O | - | - |
- | Vorbis | - | I / O | - | - |
+ | Codecs | ISO-BMFF | WebM | MPEG2-TS | WVM | Packed Audio²|
+ |:-----------------:|:------------:|:------------:|:------------:|:-----------:|:------------:|
+ | H264 (AVC) | I / O | - | I / O | I | - |
+ | H265 (HEVC) | I / O | - | I | - | - |
+ | VP8 | I / O | I / O | - | - | - |
+ | VP9 | I / O | I / O | - | - | - |
+ | AAC | I / O | - | I / O | I | O |
+ | Dolby AC3/EAC3 | I / O | - | I | - | O |
+ | DTS | I / O | - | - | - | - |
+ | FLAC | I / O | - | - | - | - |
+ | Opus | I / O³ | I / O | - | - | - |
+ | Vorbis | - | I / O | - | - | - |
- ** I for input and O for output.
- ** Opus support in ISO-BMFF is experimental.
+ NOTES:
+ - I for input and O for output.
+ - ²: https://tools.ietf.org/html/draft-pantos-http-live-streaming-23#section-3.4
+ - ³: Opus support in ISO-BMFF is experimental.
- Subtitles
- WebVTT in both text form and embedded in MP4
- TTML in text form (DASH only)
diff --git a/packager/app/muxer_factory.cc b/packager/app/muxer_factory.cc
index 618455de70..402a121512 100644
--- a/packager/app/muxer_factory.cc
+++ b/packager/app/muxer_factory.cc
@@ -11,6 +11,7 @@
#include "packager/media/base/muxer_options.h"
#include "packager/media/formats/mp2t/ts_muxer.h"
#include "packager/media/formats/mp4/mp4_muxer.h"
+#include "packager/media/formats/packed_audio/packed_audio_writer.h"
#include "packager/media/formats/webm/webm_muxer.h"
#include "packager/packager.h"
@@ -34,6 +35,11 @@ std::shared_ptr MuxerFactory::CreateMuxer(
std::shared_ptr muxer;
switch (output_format) {
+ case CONTAINER_AAC:
+ case CONTAINER_AC3:
+ case CONTAINER_EAC3:
+ muxer = std::make_shared(options);
+ break;
case CONTAINER_WEBM:
muxer = std::make_shared(options);
break;
diff --git a/packager/media/base/container_names.cc b/packager/media/base/container_names.cc
index 2521bf2427..a07a026a26 100644
--- a/packager/media/base/container_names.cc
+++ b/packager/media/base/container_names.cc
@@ -1726,7 +1726,15 @@ MediaContainerName DetermineContainer(const uint8_t* buffer, int buffer_size) {
MediaContainerName DetermineContainerFromFormatName(
const std::string& format_name) {
- if (base::EqualsCaseInsensitiveASCII(format_name, "webm")) {
+ if (base::EqualsCaseInsensitiveASCII(format_name, "aac") ||
+ base::EqualsCaseInsensitiveASCII(format_name, "adts")) {
+ return CONTAINER_AAC;
+ } else if (base::EqualsCaseInsensitiveASCII(format_name, "ac3")) {
+ return CONTAINER_AC3;
+ } else if (base::EqualsCaseInsensitiveASCII(format_name, "ec3") ||
+ base::EqualsCaseInsensitiveASCII(format_name, "eac3")) {
+ return CONTAINER_EAC3;
+ } else if (base::EqualsCaseInsensitiveASCII(format_name, "webm")) {
return CONTAINER_WEBM;
} else if (base::EqualsCaseInsensitiveASCII(format_name, "m4a") ||
base::EqualsCaseInsensitiveASCII(format_name, "m4v") ||
diff --git a/packager/media/event/muxer_listener_internal.cc b/packager/media/event/muxer_listener_internal.cc
index dc8974aae5..e8980a78a6 100644
--- a/packager/media/event/muxer_listener_internal.cc
+++ b/packager/media/event/muxer_listener_internal.cc
@@ -46,6 +46,9 @@ void SetMediaInfoContainerType(MuxerListener::ContainerType container_type,
case MuxerListener::kContainerMpeg2ts:
media_info->set_container_type(MediaInfo::CONTAINER_MPEG2_TS);
break;
+ case MuxerListener::kContainerPackedAudio:
+ media_info->set_container_type(MediaInfo::CONTAINER_PACKED_AUDIO);
+ break;
case MuxerListener::kContainerWebM:
media_info->set_container_type(MediaInfo::CONTAINER_WEBM);
break;
diff --git a/packager/mpd/base/media_info.proto b/packager/mpd/base/media_info.proto
index 6555306b94..8c9c02d16c 100644
--- a/packager/mpd/base/media_info.proto
+++ b/packager/mpd/base/media_info.proto
@@ -17,6 +17,7 @@ message MediaInfo {
CONTAINER_MPEG2_TS= 2;
CONTAINER_WEBM = 3;
CONTAINER_TEXT = 4;
+ CONTAINER_PACKED_AUDIO = 5;
}
message VideoInfo {
diff --git a/packager/packager.cc b/packager/packager.cc
index 27efb3aa7d..b8609a0e58 100644
--- a/packager/packager.cc
+++ b/packager/packager.cc
@@ -218,15 +218,17 @@ Status ValidateStreamDescriptor(bool dump_stream_info,
"All TS segments must be self-initializing. Stream "
"descriptors 'output' or 'init_segment' are not allowed.");
}
- } else if (output_format == CONTAINER_WEBVTT) {
- // There is no need for an init segment when outputting to WebVTT because
- // there is no initialization data.
+ } else if (output_format == CONTAINER_WEBVTT ||
+ output_format == CONTAINER_AAC || output_format == CONTAINER_AC3 ||
+ output_format == CONTAINER_EAC3) {
+ // There is no need for an init segment when outputting because there is no
+ // initialization data.
if (stream.segment_template.length() && stream.output.length()) {
return Status(
error::INVALID_ARGUMENT,
- "Segmented WebVTT output cannot have an init segment. Do not specify "
- "stream descriptors 'output' or 'init_segment' when using "
- "'segment_template' with WebVtt.");
+ "Segmented WebVTT or PackedAudio output cannot have an init segment. "
+ "Do not specify stream descriptors 'output' or 'init_segment' when "
+ "using 'segment_template'.");
}
} else {
// For any other format, if there is a segment template, there must be an
@@ -386,8 +388,11 @@ std::shared_ptr CreateEncryptionHandler(
// Use Sample AES in MPEG2TS.
// TODO(kqyang): Consider adding a new flag to enable Sample AES as we
// will support CENC in TS in the future.
- if (GetOutputFormat(stream) == CONTAINER_MPEG2TS) {
- VLOG(1) << "Use Apple Sample AES encryption for MPEG2TS.";
+ if (GetOutputFormat(stream) == CONTAINER_MPEG2TS ||
+ GetOutputFormat(stream) == CONTAINER_AAC ||
+ GetOutputFormat(stream) == CONTAINER_AC3 ||
+ GetOutputFormat(stream) == CONTAINER_EAC3) {
+ VLOG(1) << "Use Apple Sample AES encryption for MPEG2TS or Packed Audio.";
encryption_params.protection_scheme = kAppleSampleAesProtectionScheme;
}
diff --git a/packager/packager.gyp b/packager/packager.gyp
index d1ce240f27..f4c03647ea 100644
--- a/packager/packager.gyp
+++ b/packager/packager.gyp
@@ -36,6 +36,7 @@
'media/event/media_event.gyp:media_event',
'media/formats/mp2t/mp2t.gyp:mp2t',
'media/formats/mp4/mp4.gyp:mp4',
+ 'media/formats/packed_audio/packed_audio.gyp:packed_audio',
'media/formats/webm/webm.gyp:webm',
'media/formats/webvtt/webvtt.gyp:webvtt',
'media/formats/wvm/wvm.gyp:wvm',