Skip to content

Commit

Permalink
hbbtv supportive features - part 2
Browse files Browse the repository at this point in the history
- add vod_drm_single_key
- add vod_dash_init_mp4_pssh
- add default_KID attribute to PlayReady ContentProtection (temporarily
  configurable, in the future will probably always be enabled)
  • Loading branch information
erankor committed Nov 29, 2016
1 parent e224451 commit 146d5f0
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 39 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,16 @@ See the list of nginx variables added by this module below.
When enabled, the module encrypts the media segments according to the response it gets from the drm upstream.
Currently supported only for dash and mss (play ready).

#### vod_drm_single_key
* **syntax**: `vod_drm_single_key on/off`
* **default**: `off`
* **context**: `http`, `server`, `location`

When enabled, the module requests the drm info only for the first sequence and applies it to all sequences.
When disabled, the drm info is requested for each sequence separately.
In addition, in DASH, enabling this setting makes the module place the ContentProtection tag under AdaptationSet,
otherwise, it is placed under Representation.

#### vod_drm_clear_lead_segment_count
* **syntax**: `vod_drm_clear_lead_segment_count count`
* **default**: `1`
Expand Down Expand Up @@ -1288,6 +1298,14 @@ Sets the MPD format, available options are:
* `segmenttemplate` - uses SegmentTemplate, reporting a single duration for all fragments
* `segmenttimeline` - uses SegmentTemplate and SegmentTimeline to explicitly set the duration of the fragments

#### vod_dash_init_mp4_pssh
* **syntax**: `vod_dash_init_mp4_pssh on/off`
* **default**: `on`
* **context**: `http`, `server`, `location`

When enabled, the DRM pssh boxes are returned in the DASH init segment and in the manifest.
When disabled, the pssh boxes are returned only in the manifest.

### Configuration directives - HDS

#### vod_hds_absolute_manifest_urls
Expand Down
9 changes: 9 additions & 0 deletions ngx_http_vod_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ ngx_http_vod_create_loc_conf(ngx_conf_t *cf)
conf->last_modified_time = NGX_CONF_UNSET;

conf->drm_enabled = NGX_CONF_UNSET;
conf->drm_single_key = NGX_CONF_UNSET;
conf->drm_clear_lead_segment_count = NGX_CONF_UNSET_UINT;
conf->drm_max_info_length = NGX_CONF_UNSET_SIZE;
conf->drm_info_cache = NGX_CONF_UNSET_PTR;
Expand Down Expand Up @@ -247,6 +248,7 @@ ngx_http_vod_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}

ngx_conf_merge_value(conf->drm_enabled, prev->drm_enabled, 0);
ngx_conf_merge_value(conf->drm_single_key, prev->drm_single_key, 0);
ngx_conf_merge_uint_value(conf->drm_clear_lead_segment_count, prev->drm_clear_lead_segment_count, 1);
ngx_conf_merge_str_value(conf->drm_upstream_location, prev->drm_upstream_location, "");
ngx_conf_merge_size_value(conf->drm_max_info_length, prev->drm_max_info_length, 4096);
Expand Down Expand Up @@ -1137,6 +1139,13 @@ ngx_command_t ngx_http_vod_commands[] = {
offsetof(ngx_http_vod_loc_conf_t, drm_enabled),
NULL },

{ ngx_string("vod_drm_single_key"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_vod_loc_conf_t, drm_single_key),
NULL },

{ ngx_string("vod_drm_clear_lead_segment_count"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
Expand Down
1 change: 1 addition & 0 deletions ngx_http_vod_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct ngx_http_vod_loc_conf_s {
ngx_array_t *last_modified_types_keys;

ngx_flag_t drm_enabled;
ngx_flag_t drm_single_key;
ngx_uint_t drm_clear_lead_segment_count;
ngx_str_t drm_upstream_location;
size_t drm_max_info_length;
Expand Down
27 changes: 23 additions & 4 deletions ngx_http_vod_dash.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ ngx_http_vod_dash_handle_manifest(
ngx_str_t* response,
ngx_str_t* content_type)
{
dash_manifest_extensions_t extensions;
ngx_http_vod_loc_conf_t* conf = submodule_context->conf;
ngx_str_t base_url = ngx_null_string;
vod_status_t rc;
Expand Down Expand Up @@ -72,18 +73,19 @@ ngx_http_vod_dash_handle_manifest(
&conf->dash.mpd_config,
&base_url,
&submodule_context->media_set,
conf->drm_single_key,
response);
}
else
{
vod_memzero(&extensions, sizeof(extensions));

rc = dash_packager_build_mpd(
&submodule_context->request_context,
&conf->dash.mpd_config,
&base_url,
&submodule_context->media_set,
0,
NULL,
NULL,
&extensions,
response);
}

Expand All @@ -108,13 +110,26 @@ ngx_http_vod_dash_mp4_handle_init_segment(
{
ngx_http_vod_loc_conf_t* conf = submodule_context->conf;
vod_status_t rc;
uint32_t flags;

if (conf->drm_enabled)
{
flags = 0;

if (conf->dash.init_mp4_pssh)
{
flags |= EDASH_INIT_MP4_WRITE_PSSH;
}

if (conf->drm_clear_lead_segment_count > 0)
{
flags |= EDASH_INIT_MP4_HAS_CLEAR_LEAD;
}

rc = edash_packager_build_init_mp4(
&submodule_context->request_context,
&submodule_context->media_set,
conf->drm_clear_lead_segment_count > 0,
flags,
ngx_http_vod_submodule_size_only(submodule_context),
response);
}
Expand Down Expand Up @@ -465,8 +480,10 @@ ngx_http_vod_dash_create_loc_conf(
ngx_http_vod_dash_loc_conf_t *conf)
{
conf->absolute_manifest_urls = NGX_CONF_UNSET;
conf->init_mp4_pssh = NGX_CONF_UNSET;
conf->mpd_config.manifest_format = NGX_CONF_UNSET_UINT;
conf->mpd_config.duplicate_bitrate_threshold = NGX_CONF_UNSET_UINT;
conf->mpd_config.write_playready_kid = NGX_CONF_UNSET;
}

static char *
Expand All @@ -477,6 +494,7 @@ ngx_http_vod_dash_merge_loc_conf(
ngx_http_vod_dash_loc_conf_t *prev)
{
ngx_conf_merge_value(conf->absolute_manifest_urls, prev->absolute_manifest_urls, 1);
ngx_conf_merge_value(conf->init_mp4_pssh, prev->init_mp4_pssh, 1);

ngx_conf_merge_str_value(conf->manifest_file_name_prefix, prev->manifest_file_name_prefix, "manifest");
ngx_conf_merge_str_value(conf->mpd_config.profiles, prev->mpd_config.profiles, "urn:mpeg:dash:profile:isoff-main:2011");
Expand All @@ -485,6 +503,7 @@ ngx_http_vod_dash_merge_loc_conf(
ngx_conf_merge_str_value(conf->mpd_config.subtitle_file_name_prefix, prev->mpd_config.subtitle_file_name_prefix, "sub");
ngx_conf_merge_uint_value(conf->mpd_config.manifest_format, prev->mpd_config.manifest_format, FORMAT_SEGMENT_TIMELINE);
ngx_conf_merge_uint_value(conf->mpd_config.duplicate_bitrate_threshold, prev->mpd_config.duplicate_bitrate_threshold, 4096);
ngx_conf_merge_value(conf->mpd_config.write_playready_kid, prev->mpd_config.write_playready_kid, 0);

return NGX_CONF_OK;
}
Expand Down
14 changes: 14 additions & 0 deletions ngx_http_vod_dash_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
BASE_OFFSET + offsetof(ngx_http_vod_dash_loc_conf_t, absolute_manifest_urls),
NULL },

{ ngx_string("vod_dash_init_mp4_pssh"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
BASE_OFFSET + offsetof(ngx_http_vod_dash_loc_conf_t, init_mp4_pssh),
NULL },

{ ngx_string("vod_dash_manifest_file_name_prefix"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
Expand Down Expand Up @@ -56,4 +63,11 @@
BASE_OFFSET + offsetof(ngx_http_vod_dash_loc_conf_t, mpd_config.duplicate_bitrate_threshold),
NULL },

{ ngx_string("vod_dash_write_playready_kid"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
BASE_OFFSET + offsetof(ngx_http_vod_dash_loc_conf_t, mpd_config.write_playready_kid),
NULL },

#undef BASE_OFFSET
1 change: 1 addition & 0 deletions ngx_http_vod_dash_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef struct
{
ngx_str_t manifest_file_name_prefix;
ngx_flag_t absolute_manifest_urls;
ngx_flag_t init_mp4_pssh;
dash_manifest_config_t mpd_config;
} ngx_http_vod_dash_loc_conf_t;

Expand Down
30 changes: 29 additions & 1 deletion ngx_http_vod_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,20 @@ ngx_http_vod_alloc_read_buffer(ngx_http_vod_ctx_t *ctx, size_t size, int alloc_p

////// DRM

static void
ngx_http_vod_copy_drm_info(ngx_http_vod_ctx_t *ctx)
{
media_sequence_t* ref_sequence = ctx->cur_sequence;
media_sequence_t* cur_sequence;

for (cur_sequence = ref_sequence + 1;
cur_sequence < ctx->submodule_context.media_set.sequences_end;
cur_sequence++)
{
cur_sequence->drm_info = ref_sequence->drm_info;
}
}

static void
ngx_http_vod_drm_info_request_finished(void* context, ngx_int_t rc, ngx_buf_t* response, ssize_t content_length)
{
Expand Down Expand Up @@ -1061,7 +1075,15 @@ ngx_http_vod_drm_info_request_finished(void* context, ngx_int_t rc, ngx_buf_t* r
}
}

ctx->cur_sequence++;
if (conf->drm_single_key)
{
ngx_http_vod_copy_drm_info(ctx);
ctx->cur_sequence = ctx->submodule_context.media_set.sequences_end;
}
else
{
ctx->cur_sequence++;
}

rc = ngx_http_vod_run_state_machine(ctx);
if (rc == NGX_AGAIN)
Expand Down Expand Up @@ -1142,6 +1164,12 @@ ngx_http_vod_state_machine_get_drm_info(ngx_http_vod_ctx_t *ctx)
return rc;
}

if (conf->drm_single_key)
{
ngx_http_vod_copy_drm_info(ctx);
ctx->cur_sequence = ctx->submodule_context.media_set.sequences_end - 1;
}

continue;
}
else
Expand Down
28 changes: 18 additions & 10 deletions vod/dash/dash_packager.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ typedef struct {
dash_manifest_config_t* conf;
vod_str_t* base_url;
media_set_t* media_set;
write_tags_callback_t write_representation_tags;
void* representation_tags_writer_context;
dash_manifest_extensions_t extensions;
u_char* base_url_temp_buffer;
segment_durations_t segment_durations[MEDIA_TYPE_COUNT];
segment_duration_item_t** cur_duration_items;
Expand Down Expand Up @@ -969,6 +968,14 @@ dash_packager_write_mpd_period(
continue;
}

if (context->extensions.adaptation_set.write != NULL)
{
p = context->extensions.adaptation_set.write(
context->extensions.adaptation_set.context,
p,
reference_track);
}

// get the segment index start number
start_number = (*cur_duration_items)[0].segment_index;

Expand Down Expand Up @@ -1079,9 +1086,12 @@ dash_packager_write_mpd_period(
}

// write any additional tags
if (context->write_representation_tags != NULL)
if (context->extensions.representation.write != NULL)
{
p = context->write_representation_tags(context->representation_tags_writer_context, p, cur_track);
p = context->extensions.representation.write(
context->extensions.representation.context,
p,
cur_track);
}

p = vod_copy(p, VOD_DASH_MANIFEST_REPRESENTATION_FOOTER, sizeof(VOD_DASH_MANIFEST_REPRESENTATION_FOOTER) - 1);
Expand Down Expand Up @@ -1287,9 +1297,7 @@ dash_packager_build_mpd(
dash_manifest_config_t* conf,
vod_str_t* base_url,
media_set_t* media_set,
size_t representation_tags_size,
write_tags_callback_t write_representation_tags,
void* representation_tags_writer_context,
dash_manifest_extensions_t* extensions,
vod_str_t* result)
{
segment_duration_item_t** cur_duration_items;
Expand Down Expand Up @@ -1389,7 +1397,8 @@ dash_packager_build_mpd(
base_url->len + conf->subtitle_file_name_prefix.len + MAX_CLIP_SPEC_LENGTH + MAX_TRACK_SPEC_LENGTH) *
context.adaptation_sets.count[ADAPTATION_TYPE_SUBTITLE] +
sizeof(VOD_DASH_MANIFEST_PERIOD_FOOTER) - 1 +
representation_tags_size;
extensions->representation.size +
extensions->adaptation_set.size;

switch (media_set->type)
{
Expand Down Expand Up @@ -1492,8 +1501,7 @@ dash_packager_build_mpd(
context.conf = conf;
context.base_url = base_url;
context.media_set = media_set;
context.write_representation_tags = write_representation_tags;
context.representation_tags_writer_context = representation_tags_writer_context;
context.extensions = *extensions;

// print the manifest header
switch (media_set->type)
Expand Down
16 changes: 13 additions & 3 deletions vod/dash/dash_packager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,27 @@ typedef struct {
void* context;
} atom_writer_t;

typedef struct {
size_t size;
write_tags_callback_t write;
void* context;
} tags_writer_t;

typedef struct {
vod_str_t profiles;
vod_str_t init_file_name_prefix;
vod_str_t fragment_file_name_prefix;
vod_str_t subtitle_file_name_prefix;
vod_uint_t manifest_format;
vod_uint_t duplicate_bitrate_threshold;
bool_t write_playready_kid; // TODO: remove
} dash_manifest_config_t;

typedef struct {
tags_writer_t representation;
tags_writer_t adaptation_set;
} dash_manifest_extensions_t;

typedef struct {
size_t extra_traf_atoms_size;
dash_write_extra_traf_atoms_callback_t write_extra_traf_atoms_callback;
Expand All @@ -51,9 +63,7 @@ vod_status_t dash_packager_build_mpd(
dash_manifest_config_t* conf,
vod_str_t* base_url,
media_set_t* media_set,
size_t representation_tags_size,
write_tags_callback_t write_representation_tags,
void* representation_tags_writer_context,
dash_manifest_extensions_t* extensions,
vod_str_t* result);

vod_status_t dash_packager_build_init_mp4(
Expand Down
Loading

0 comments on commit 146d5f0

Please sign in to comment.