A media packaging and development framework for VOD and Live DASH and HLS applications, supporting Common Encryption for Widevine and other DRM Systems.
Go to file
KongQun Yang 05a5a41969 Support generation of libpackager.so (shared_library)
Shared libpackager can be built by setting libpackager_type to
shared_library, e.g.

GYP_DEFINES='libpackager_type=shared_library' gclient runhooks
ninja -C out/Debug

will generate libpackager.so in out/Debug/lib directory.

Here is a few other changes to make shared_library builds and
tests pass:

- Add several test parameters to packager.h, which is needed for
  testing.
- Create a protoc.gypi from build/protoc.gypi but depending on
  protobuf_full_do_not_use instead of protobuf_lite, since we need
  protobuf_full_do_not_use for text parsing and generation of media
  info proto. Somehow shared_library build does not allow mixed use
  of protobuf_full_do_not_use and protobuf_lite.
- Remove the use of LazyInstance in version/version.cc and use static
  variable directly. This is because LazyInstance needs AtExitManager
  which may not be easy to setup when calling GetVersion.
- Allow skipping testPackageWvmInputWithoutStrippingParameterSetNalus
  with flag --shared_library, which is needed as shared_library build
  does not support --strip_parameter_set_nalus flag yet.

Fixes #227

Change-Id: Iff05a50baa28134faa7218664c96114cb9e70329
2017-06-13 20:42:32 +00:00
.github Update github issue template with mailing list for test files 2017-06-02 18:16:41 +00:00
docs Deprecate availability_time_offset MPD flag 2017-05-22 23:14:16 +00:00
kokoro Batch script should fail if ninja fails 2017-04-20 21:25:10 +00:00
packager Support generation of libpackager.so (shared_library) 2017-06-13 20:42:32 +00:00
.clang-format Use Chromium style for clang-format 2014-07-02 22:49:46 +00:00
.gitignore Add gitignores for msvs files 2016-12-19 21:26:26 +00:00
.gitmodules Add an empty .gitmodules to avoid gclient warning 2014-03-28 22:13:33 +00:00
.travis.yml Add appveyor config for Windows CI 2016-08-23 12:24:34 -07:00
AUTHORS Fix possible integer overflow in WebM duration 2017-03-23 09:38:51 -07:00
CHANGELOG.md Add v1.6.2 tag in CHANGELOG 2017-04-18 13:56:18 -07:00
CONTRIBUTING.md Add AUTHORS, CONTRIBUTORS, CONTRIBUTING.md, and README.md 2014-04-19 00:05:38 +00:00
CONTRIBUTORS Fix possible integer overflow in WebM duration 2017-03-23 09:38:51 -07:00
DEPS Organize DEPS file 2017-04-11 17:38:19 +00:00
Dockerfile Fix docker build failure due to build update 2016-08-29 17:52:53 -07:00
LICENSE Update README and LICENSE 2016-09-07 19:22:41 +00:00
README.md Add sample usage for trick play in README.md. 2017-05-23 18:33:33 +00:00
appveyor.yml Fix build break in win64 2017-02-10 22:57:35 -08:00
chromium-LICENSE Add Chromium license 2014-04-10 19:58:08 +00:00
gyp_packager.py Update DEPS to fix mac build failure 2016-08-19 13:49:41 -07:00

README.md

Shaka Packager

Build Status Build status

Media packaging SDK intended for C++ programmers writing DASH/HLS packager applications with common encryption support, Widevine DRM support, Live, and Video-On-Demand.

This document provides the information needed to create a DASH/HLS packager that is able to remux and encrypt a video into fragmented ISO BMFF format with common encryption (CENC) support. The DASH/HLS packaging API is also designed in such a way for easy extension to more source and destination formats.

Current supported 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 - - -
DTS I / O - - -
Opus I / O I / O - -
Vorbis - I / O - -
** I for input and O for output.
** VP8/VP9/Opus support in ISO-BMFF is experimental.

This project is supported on Linux, Windows and MacOSX platforms.

Useful Links

Setting Up For Development

  1. Packager source is managed by Git at https://www.github.com/google/shaka-packager. We use gclient tool from Chromium to manage third party libraries. You will need Git (v1.7.5 or above) installed on your machine to access the source code.

  2. Install Chromium depot tools which contains gclient and ninja

See http://www.chromium.org/developers/how-tos/install-depot-tools for details.

  1. Get the source
mkdir shaka_packager
cd shaka_packager
gclient config https://www.github.com/google/shaka-packager.git --name=src
gclient sync

To sync to a particular commit or version, use 'gclient sync -r <revision>', e.g.

# Sync to commit 4cb5326355e1559d60b46167740e04624d0d2f51
gclient sync -r 4cb5326355e1559d60b46167740e04624d0d2f51
# Sync to version 1.2.0
gclient sync -r v1.2.0
  1. Build

We use ninja, which is much faster than make, to build our code:

cd src
ninja -C out/{Debug,Release} [Module]

Module is optional. If not specified, build all, e.g.

ninja -C out/Debug                     # build all modules in Debug mode
ninja -C out/Release                   # build all modules in Release mode
ninja -C out/Release mp4               # build mp4 module in Release mode

Refer to ninja manual for details.

We also provide a mechanism to change build configurations, for example, developers can change build system to “make” by overriding GYP_GENERATORS.

GYP_GENERATORS='make' gclient runhooks

Another example, developers can also enable clang by overriding GYP_DEFINE.

GYP_DEFINES='clang=1' gclient runhooks
  1. Updating the code

Update your current branch with git pull followed by gclient sync. Note that if you are not on a branch, git pull will not work, and you will need to use git fetch instead.

  1. Contributing

See https://github.com/google/shaka-packager/blob/master/CONTRIBUTING.md for details.

Using Docker For Testing / Development

Docker is a tool that can package an application and its dependencies in a virtual container to run on different host operating systems.

  1. Install Docker.

  2. Pull prebuilt image from Dockerhub or build an image locally

2.a. Pull prebuilt image from Dockerhub

```Shell
docker pull google/shaka-packager
```

2.b. Build an image locally

```Shell
docker build -t google/shaka-packager github.com/google/shaka-packager.git
```
  1. Run the container (your_media_path should be your media folder)
docker run -v /your_media_path/:/media -it --rm google/shaka-packager
  1. Testing
# Make sure you run step 3 and you're inside the container.
cd /media

# VOD: mp4 --> dash
packager input=/media/example.mp4,stream=audio,output=audio.mp4 \
         input=/media/example.mp4,stream=video,output=video.mp4 \
         --mpd_output example.mpd

# Leave the container.
exit

Outputs are available in your media folder your_media_path.

Design Overview

Major modules are described below:

Demuxer is responsible for extracting elementary stream samples from a multimedia file, e.g. an ISO BMFF file. The demuxed streams can be fed into a muxer to generate multimedia files. An optional KeySource can be provided to Demuxer to decrypt CENC and WVM source content.

Demuxer reads from source through the File interface. A concrete LocalFile class is already implemented. The users may also implement their own File class if they want to read/write using a different kinds of protocol, e.g. network storage, http etc.

Muxer is responsible for taking elementary stream samples and producing media segments. An optional KeySource can be provided to Muxer to generate encrypted outputs. Muxer writes to output using the same File interface as Demuxer.

Demuxer and Muxer are connected using MediaStream. MediaStream wraps the elementary streams and is responsible for the interaction between Demuxer and Muxer. A demuxer can transmits multiple MediaStreams; similarly, A muxer is able to accept and mux multiple MediaStreams, not necessarily from the same Demuxer.

MpdBuilder is responsible for the creation of Media Presentation Description as specified in ISO/IEC 23009-1 DASH MPD spec.

Refer to Design, API for details.

DASH-IF IOP Compliance

We try out best to be compliant to Guidelines for Implementation: DASH-IF Interoperability Points.

We are already compliant to most of the requirements specified by the document, with two exceptions:

  • ContentProtection elements are still put under Representation element instead of AdaptationSet element;
  • Representations encrypted with different keys are still put under the same AdaptationSet.

We created a flag '--generate_dash_if_iop_compliant_mpd', if enabled,

  • ContentProtection elements will be moved under AdaptationSet;
  • Representations encrypted with different keys will be put under different AdaptationSets, grouped by @group attribute.

Users can enable the flag '--generate_dash_if_iop_compliant_mpd' to have these features. This flag will be enabled by default in a future release.

Please feel free to file a bug or feature request if there are any incompatibilities with DASH-IF IOP or other standards / specifications.

Driver Program Sample Usage

Sample driver programs packager and mpd_generator are written using the SDK.

Some sample usages:

Run the program without arguments will display the help page with the list of command line arguments:

packager

Dump stream info:

packager input=sintel.mp4 --dump_stream_info

Demux audio from the input and generate a fragmented mp4:

packager input=sintel.mp4,stream=audio,output=fragmented_sintel.mp4

Demux streams from the input and generates a mpd with fragmented mp4:

packager \
  input=sintel.mp4,stream=audio,output=sintel_audio.mp4 \
  input=sintel.mp4,stream=video,output=sintel_video.mp4 \
--mpd_output sintel_vod.mpd

Includes a subtitle input from webvtt:

packager \
  input=sintel.mp4,stream=audio,output=sintel_audio.mp4 \
  input=sintel.mp4,stream=video,output=sintel_video.mp4 \
  input=sintel_english_input.vtt,stream=text,output=sintel_english.vtt \
--mpd_output sintel_vod.mpd

You may also generate mpd with live profile by specifying segment_template in stream descriptors. Here is an example with IPTV input streams:

packager \
  'input=udp://224.1.1.5:5003,stream=audio,init_segment=live-audio.mp4,segment_template=live-audio-$Number$.mp4,bandwidth=130000'  \
  'input=udp://224.1.1.5:5003,stream=video,init_segment=live-video-sd.mp4,segment_template=live-video-sd-$Number$.mp4,bandwidth=2000000' \
  'input=udp://224.1.1.5:5002,stream=video,init_segment=live-video-hd.mp4,segment_template=live-video-hd-$Number$.mp4,bandwidth=5000000' \
--mpd_output live.mpd

A UDP url is of the form udp://ip:port[?options]. Here is an example: udp://224.1.1.5:5003?reuse=1&interface=10.11.12.13&timeout=1234567.

Three options are supported right now:

  • reuse=1|0 Allow or disallow reusing UDP sockets. Default to 0.
  • interface=interface_ip_address Address of the interface over which to receive UDP multicast streams.
  • timeout=microseconds Timeout in microseconds. Default to unlimited.

To generate static mpd with live profile. An additional flag needs to be specified:

packager \
  'input=sintel.mp4,stream=audio,init_segment=audio.mp4,segment_template=audio-$Number$.mp4'  \
  'input=sintel.mp4,stream=video,init_segment=video.mp4,segment_template=video-$Number$.mp4' \
--mpd_output live_static.mpd \
--generate_static_mpd

Demux video from the input and generate an encrypted fragmented mp4 using Widevine encryption with RSA signing key file widevine_test_private.der:

packager input=sintel.mp4,stream=video,output=encrypted_sintel.mp4 \
--enable_widevine_encryption \
--key_server_url "https://license.uat.widevine.com/cenc/getcontentkey/widevine_test" \
--content_id "3031323334353637" \
--signer "widevine_test" \
--rsa_signing_key_path "widevine_test_private.der"

The program also supports AES signing. Here is an example with encryption key rotates every 1800 seconds:

packager \
  'input=udp://224.1.1.5:5003,stream=audio,init_segment=live-audio.mp4,segment_template=live-audio-$Number$.mp4,bandwidth=130000'  \
  'input=udp://224.1.1.5:5003,stream=video,init_segment=live-video-sd.mp4,segment_template=live-video-sd-$Number$.mp4,bandwidth=2000000' \
  'input=udp://224.1.1.5:5002,stream=video,init_segment=live-video-hd.mp4,segment_template=live-video-hd-$Number$.mp4,bandwidth=5000000' \
--mpd_output live.mpd \
--enable_widevine_encryption \
--key_server_url "https://license.uat.widevine.com/cenc/getcontentkey/widevine_test" \
--content_id "3031323334353637" \
--signer "widevine_test" \
--aes_signing_key "1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9" \
--aes_signing_iv "d58ce954203b7c9a9a9d467f59839249" \
--crypto_period_duration 1800

Note that key rotation is only supported for live profile.

Demux and decrypt video from a WVM container, and generate encrypted fragmented mp4 using Widevine encryption with RSA signing key file widevine_test_private.der:

packager input=sintel.wvm,stream=video,output=encrypted_sintel.mp4 \
--enable_widevine_decryption \
--enable_widevine_encryption \
--key_server_url "https://license.uat.widevine.com/cenc/getcontentkey/widevine_test" \
--content_id "3031323334353637" \
--signer "widevine_test" \
--rsa_signing_key_path "widevine_test_private.der"

The program can be told to generate MediaInfo files, which can be fed to mpd_generate to generate the mpd file.

packager \
  input=sintel.mp4,stream=video,output=sintel_video.mp4 \
  input=sintel.mp4,stream=audio,output=sintel_audio.mp4 \
--output_media_info

mpd_generator \
--input "sintel_video.mp4.media_info,sintel_audio.mp4.media_info" \
--output "sintel.mpd"

Output MPEG2-TS video.

packager \
 'input=bear-1280x720.mp4,stream=video,segment_template=bear$Number$.ts'

Output HLS playlists with MPEG2-TS video. The following outputs a Master Playlist as master.m3u8. And the Media Playlist for the video as playlist.m3u8. The optional --hls_base_url specifies the prefix for the generated TS segments.

packager \
  'input=bear-1280x720.mp4,stream=video,segment_template=bear$Number$.ts,playlist_name=playlist.m3u8' \
  --hls_master_playlist_output="master.m3u8" \
  --hls_base_url="http://localhost:10000/"

For audio Media Playlists, the name and group for EXT-X-MEDIA tag must be specified.

packager \
  'input=input.mp4,stream=video,segment_template=output$Number$.ts,playlist_name=video_playlist.m3u8' \
  'input=input.mp4,stream=audio,segment_template=output_audio$Number$.ts,playlist_name=audio_playlist.m3u8,hls_group_id=audio,hls_name=ENGLISH' \
  --hls_master_playlist_output="master_playlist.m3u8" \
  --hls_base_url="http://localhost:10000/"

Create DASH trick play, a.k.a. trick mode, stream. The trick_play_factor in the stream descriptor specifies the sampling rate among the key frames in the video. For example, 1 means every key frame and 2 means every other key frame.

packager \
  'input=bear-1280x720.mp4,stream=video,output=bear-1280x720_video.mp4' \
  'input=bear-1280x720.mp4,stream=video,output=bear-1280x720_video_trick_play.mp4,trick_play_factor=1' \
  --mpd_output bear_trick_play.mpd