From 2f5fe7a6db7a56d8a3f894fb11b09c21fe7f980d Mon Sep 17 00:00:00 2001 From: erankor Date: Sat, 27 Jan 2024 18:25:45 +0200 Subject: [PATCH] add `default` property to sequence & closed captions --- README.md | 2 ++ ngx_http_vod_module.c | 4 +-- ngx_http_vod_request_parse.c | 15 ++++----- vod/dash/dash_packager.c | 24 +++++++------- vod/hds/hds_manifest.c | 16 +++++----- vod/hls/m3u8_builder.c | 28 ++++++++++++----- vod/input/silence_generator.c | 4 +-- vod/media_format.h | 11 +++++-- vod/media_set.h | 5 ++- vod/media_set_parser.c | 54 +++++++++++++++++++++++--------- vod/mkv/mkv_format.c | 20 ++++++------ vod/mp4/mp4_parser.c | 57 ++++++++++++++++++---------------- vod/mss/mss_packager.c | 16 +++++----- vod/subtitle/subtitle_format.c | 27 +++++----------- 14 files changed, 159 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index 9b165ac3..2d905563 100644 --- a/README.md +++ b/README.md @@ -532,6 +532,8 @@ Optional fields: * `label` - a friendly string that identifies the sequence. If a language is specified, a default label will be automatically derived by it - e.g. if language is `ita`, by default `italiano` will be used as the label. +* `default` - a boolean that sets the value of the DEFAULT attribute of EXT-X-MEDIA tags using this sequence. + If not specified, the first EXT-X-MEDIA tag in each group returns DEFAULT=YES, while the others return DEFAULT=NO. * `bitrate` - an object that can be used to set the bitrate for the different media types, in bits per second. For example, `{"v": 900000, "a": 64000}`. If the bitrate is not supplied, nginx-vod-module will estimate it based on the last clip in the sequence. diff --git a/ngx_http_vod_module.c b/ngx_http_vod_module.c index 57fceedf..33955e22 100644 --- a/ngx_http_vod_module.c +++ b/ngx_http_vod_module.c @@ -5336,9 +5336,7 @@ ngx_http_vod_map_media_set_apply(ngx_http_vod_ctx_t *ctx, ngx_str_t* mapping, in ctx->submodule_context.media_set.segmenter_conf = mapped_media_set.segmenter_conf; sequence = cur_source->sequence; sequence->mapped_uri = mapped_source->mapped_uri; - sequence->lang_str = mapped_media_set.sequences->lang_str; - sequence->language = mapped_media_set.sequences->language; - sequence->label = mapped_media_set.sequences->label; + sequence->tags = mapped_media_set.sequences->tags; sequence->id = mapped_media_set.sequences->id; ngx_memcpy(sequence->bitrate, mapped_media_set.sequences->bitrate, sizeof(sequence->bitrate)); ngx_memcpy(sequence->avg_bitrate, mapped_media_set.sequences->avg_bitrate, sizeof(sequence->avg_bitrate)); diff --git a/ngx_http_vod_request_parse.c b/ngx_http_vod_request_parse.c index 98f4c086..21eeef62 100644 --- a/ngx_http_vod_request_parse.c +++ b/ngx_http_vod_request_parse.c @@ -734,10 +734,10 @@ ngx_http_vod_parse_lang_param(ngx_str_t* value, void* output, int offset) return NGX_HTTP_BAD_REQUEST; } - sequence->lang_str.data = (u_char *)lang_get_rfc_5646_name(result); - sequence->lang_str.len = ngx_strlen(sequence->lang_str.data); - sequence->language = result; - lang_get_native_name(result, &sequence->label); + sequence->tags.lang_str.data = (u_char *)lang_get_rfc_5646_name(result); + sequence->tags.lang_str.len = ngx_strlen(sequence->tags.lang_str.data); + sequence->tags.language = result; + lang_get_native_name(result, &sequence->tags.label); return VOD_OK; } @@ -1078,9 +1078,10 @@ ngx_http_vod_parse_uri_path( } cur_sequence->id.len = 0; - cur_sequence->lang_str.len = 0; - cur_sequence->language = 0; - cur_sequence->label.len = 0; + cur_sequence->tags.lang_str.len = 0; + cur_sequence->tags.language = 0; + cur_sequence->tags.label.len = 0; + cur_sequence->tags.is_default = -1; cur_sequence->first_key_frame_offset = 0; cur_sequence->key_frame_durations = NULL; cur_sequence->drm_info = NULL; diff --git a/vod/dash/dash_packager.c b/vod/dash/dash_packager.c index 96b8b070..4b48dd20 100644 --- a/vod/dash/dash_packager.c +++ b/vod/dash/dash_packager.c @@ -326,12 +326,12 @@ dash_packager_compare_tracks(uintptr_t bitrate_threshold, const media_info_t* mi (mi1->u.video.height == mi2->u.video.height); } - if (mi1->label.len == 0 || mi2->label.len == 0) + if (mi1->tags.label.len == 0 || mi2->tags.label.len == 0) { return TRUE; } - return vod_str_equals(mi1->label, mi2->label); + return vod_str_equals(mi1->tags.label, mi2->tags.label); } static void @@ -858,12 +858,12 @@ dash_packager_write_mpd_period( case MEDIA_TYPE_AUDIO: reference_track = (*adaptation_set->first) + filtered_clip_offset; - if (reference_track->media_info.lang_str.len > 0 || reference_track->media_info.label.len > 0) + if (reference_track->media_info.tags.lang_str.len > 0 || reference_track->media_info.tags.label.len > 0) { p = vod_sprintf(p, VOD_DASH_MANIFEST_ADAPTATION_HEADER_AUDIO_LANG, adapt_id++, - &reference_track->media_info.lang_str, - &reference_track->media_info.label); + &reference_track->media_info.tags.lang_str, + &reference_track->media_info.tags.label); } else { @@ -889,8 +889,8 @@ dash_packager_write_mpd_period( { reference_track = (*adaptation_set->first) + filtered_clip_offset; p = vod_sprintf(p, VOD_DASH_MANIFEST_ADAPTATION_HEADER_SUBTITLE_SMPTE_TT, - &reference_track->media_info.lang_str, - &reference_track->media_info.label); + &reference_track->media_info.tags.lang_str, + &reference_track->media_info.tags.label); break; } @@ -919,10 +919,10 @@ dash_packager_write_mpd_period( representation_id.len--; } - lang_code = lang_get_rfc_5646_name(cur_track->media_info.language); + lang_code = lang_get_rfc_5646_name(cur_track->media_info.tags.language); p = vod_sprintf(p, VOD_DASH_MANIFEST_ADAPTATION_SUBTITLE_VTT, - &cur_track->media_info.lang_str, - &cur_track->media_info.label, + &cur_track->media_info.tags.lang_str, + &cur_track->media_info.tags.label, lang_code, subtitle_adapt_id++, &cur_base_url, @@ -1205,7 +1205,7 @@ dash_packager_remove_redundant_tracks( // prefer to remove a track that doesn't have a label, so that we won't lose a language // in case of multi language manifest - if (track1->media_info.label.len == 0 || track2->media_info.label.len != 0) + if (track1->media_info.tags.label.len == 0 || track2->media_info.tags.label.len != 0) { remove = track1; } @@ -1438,7 +1438,7 @@ dash_packager_build_mpd( case MEDIA_TYPE_AUDIO: case MEDIA_TYPE_SUBTITLE: cur_track = (*adaptation_set->first) + filtered_clip_offset; - result_size += cur_track->media_info.label.len + cur_track->media_info.lang_str.len; + result_size += cur_track->media_info.tags.label.len + cur_track->media_info.tags.lang_str.len; break; } } diff --git a/vod/hds/hds_manifest.c b/vod/hds/hds_manifest.c index 5d03c0d8..af37d8b6 100644 --- a/vod/hds/hds_manifest.c +++ b/vod/hds/hds_manifest.c @@ -462,14 +462,14 @@ hds_packager_build_manifest( { if (adaptation_set->first[MEDIA_TYPE_AUDIO] != NULL) { - result_size += adaptation_set->first[MEDIA_TYPE_AUDIO]->media_info.label.len + - adaptation_set->first[MEDIA_TYPE_AUDIO]->media_info.lang_str.len; + result_size += adaptation_set->first[MEDIA_TYPE_AUDIO]->media_info.tags.label.len + + adaptation_set->first[MEDIA_TYPE_AUDIO]->media_info.tags.lang_str.len; } } else { - result_size += adaptation_set->first[0]->media_info.label.len + - adaptation_set->first[0]->media_info.lang_str.len; + result_size += adaptation_set->first[0]->media_info.tags.label.len + + adaptation_set->first[0]->media_info.tags.lang_str.len; } for (cur_track_ptr = adaptation_set->first; cur_track_ptr < adaptation_set->last; cur_track_ptr += muxed_tracks) @@ -573,8 +573,8 @@ hds_packager_build_manifest( } p = vod_sprintf(p, HDS_MANIFEST_HEADER_LANG, - &track->media_info.label, - &track->media_info.lang_str); + &track->media_info.tags.label, + &track->media_info.tags.lang_str); } // bootstrap tags @@ -704,8 +704,8 @@ hds_packager_build_manifest( { p = vod_sprintf(p, HDS_MEDIA_HEADER_PREFIX_AUDIO_LANG, bitrate / 1000, - &tracks[MEDIA_TYPE_AUDIO]->media_info.label, - &tracks[MEDIA_TYPE_AUDIO]->media_info.lang_str); + &tracks[MEDIA_TYPE_AUDIO]->media_info.tags.label, + &tracks[MEDIA_TYPE_AUDIO]->media_info.tags.lang_str); } else { diff --git a/vod/hls/m3u8_builder.c b/vod/hls/m3u8_builder.c index 02db57aa..a80b8cc2 100644 --- a/vod/hls/m3u8_builder.c +++ b/vod/hls/m3u8_builder.c @@ -855,6 +855,7 @@ m3u8_builder_closed_captions_write( { media_closed_captions_t* closed_captions; uint32_t index = 0; + bool_t is_default; for (closed_captions = media_set->closed_captions; closed_captions < media_set->closed_captions_end; closed_captions++) { @@ -869,7 +870,13 @@ m3u8_builder_closed_captions_write( p = vod_sprintf(p, M3U8_EXT_MEDIA_LANG, &closed_captions->language); } - if (closed_captions == media_set->closed_captions) + is_default = closed_captions->is_default; + if (is_default < 0) + { + is_default = closed_captions == media_set->closed_captions; + } + + if (is_default) { p = vod_copy(p, M3U8_EXT_MEDIA_DEFAULT, sizeof(M3U8_EXT_MEDIA_DEFAULT) - 1); } @@ -921,8 +928,8 @@ m3u8_builder_ext_x_media_tags_get_size( { cur_track = adaptation_set->first[0]; - label_len = cur_track->media_info.label.len; - result += vod_max(label_len, default_label.len) + cur_track->media_info.lang_str.len; + label_len = cur_track->media_info.tags.label.len; + result += vod_max(label_len, default_label.len) + cur_track->media_info.tags.lang_str.len; if (base_url->len != 0) { @@ -948,6 +955,7 @@ m3u8_builder_ext_x_media_tags_write( media_track_t* tracks[MEDIA_TYPE_COUNT]; vod_str_t* label; uint32_t group_index; + bool_t is_default; char* group_id; char* type; @@ -988,7 +996,7 @@ m3u8_builder_ext_x_media_tags_write( group_index = 0; } - label = &tracks[media_type]->media_info.label; + label = &tracks[media_type]->media_info.tags.label; if (label->len == 0) { label = &default_label; @@ -1000,13 +1008,19 @@ m3u8_builder_ext_x_media_tags_write( group_index, label); - if (tracks[media_type]->media_info.lang_str.len > 0) + if (tracks[media_type]->media_info.tags.lang_str.len > 0) { p = vod_sprintf(p, M3U8_EXT_MEDIA_LANG, - &tracks[media_type]->media_info.lang_str); + &tracks[media_type]->media_info.tags.lang_str); + } + + is_default = tracks[media_type]->media_info.tags.is_default; + if (is_default < 0) + { + is_default = adaptation_set == first_adaptation_set; } - if (adaptation_set == first_adaptation_set) + if (is_default) { p = vod_copy(p, M3U8_EXT_MEDIA_DEFAULT, sizeof(M3U8_EXT_MEDIA_DEFAULT) - 1); } diff --git a/vod/input/silence_generator.c b/vod/input/silence_generator.c index 06420145..b86c2025 100644 --- a/vod/input/silence_generator.c +++ b/vod/input/silence_generator.c @@ -102,9 +102,7 @@ silence_generator_generate( track->media_info.duration_millis = parse_params->clip_to - parse_params->clip_from; track->media_info.full_duration = (uint64_t)track->media_info.duration_millis * track->media_info.timescale; track->media_info.duration = track->media_info.full_duration; - track->media_info.lang_str = sequence->lang_str; - track->media_info.language = sequence->language; - track->media_info.label = sequence->label; + track->media_info.tags = sequence->tags; rc = media_format_finalize_track( request_context, diff --git a/vod/media_format.h b/vod/media_format.h index 85af29e7..629aaf5b 100644 --- a/vod/media_format.h +++ b/vod/media_format.h @@ -225,6 +225,13 @@ typedef struct { mp4a_config_t codec_config; } audio_media_info_t; +typedef struct { + language_id_t language; + vod_str_t lang_str; + vod_str_t label; + bool_t is_default; +} media_tags_t; + typedef struct media_info_s { uint32_t media_type; uint32_t format; @@ -243,9 +250,7 @@ typedef struct media_info_s { int64_t empty_duration; // temporary during parsing int64_t start_time; // temporary during parsing uint64_t codec_delay; - language_id_t language; - vod_str_t lang_str; - vod_str_t label; + media_tags_t tags; union { video_media_info_t video; audio_media_info_t audio; diff --git a/vod/media_set.h b/vod/media_set.h index 76e310c9..84133005 100644 --- a/vod/media_set.h +++ b/vod/media_set.h @@ -59,9 +59,7 @@ struct media_sequence_s { media_clip_t** clips; // [clip_count] vod_str_t stripped_uri; vod_str_t id; - vod_str_t label; - vod_str_t lang_str; - language_id_t language; + media_tags_t tags; uint32_t bitrate[MEDIA_TYPE_COUNT]; uint32_t avg_bitrate[MEDIA_TYPE_COUNT]; int64_t first_key_frame_offset; @@ -109,6 +107,7 @@ typedef struct { vod_str_t id; vod_str_t language; vod_str_t label; + bool_t is_default; } media_closed_captions_t; typedef struct { diff --git a/vod/media_set_parser.c b/vod/media_set_parser.c index 81e33b6f..c46542fe 100644 --- a/vod/media_set_parser.c +++ b/vod/media_set_parser.c @@ -64,6 +64,7 @@ enum { MEDIA_CLOSED_CAPTIONS_PARAM_ID, MEDIA_CLOSED_CAPTIONS_PARAM_LANGUAGE, MEDIA_CLOSED_CAPTIONS_PARAM_LABEL, + MEDIA_CLOSED_CAPTIONS_PARAM_DEFAULT, MEDIA_CLOSED_CAPTIONS_PARAM_COUNT }; @@ -105,6 +106,7 @@ static vod_status_t media_set_parse_source(void* ctx, vod_json_object_t* element static vod_status_t media_set_parse_clips_array(void* ctx, vod_json_value_t* value, void* dest); static vod_status_t media_set_parse_bitrate(void* ctx, vod_json_value_t* value, void* dest); static vod_status_t media_set_parse_source_type(void* ctx, vod_json_value_t* value, void* dest); +static vod_status_t media_set_parse_bool(void* ctx, vod_json_value_t* value, void* dest); // constants static json_parser_union_type_def_t media_clip_union_params[] = { @@ -133,8 +135,9 @@ static json_object_value_def_t media_clip_source_params[] = { static json_object_value_def_t media_sequence_params[] = { { vod_string("id"), VOD_JSON_STRING, offsetof(media_sequence_t, id), media_set_parse_null_term_string }, { vod_string("clips"), VOD_JSON_ARRAY, offsetof(media_sequence_t, unparsed_clips), media_set_parse_clips_array }, - { vod_string("language"), VOD_JSON_STRING, offsetof(media_sequence_t, lang_str), media_set_parse_null_term_string }, - { vod_string("label"), VOD_JSON_STRING, offsetof(media_sequence_t, label), media_set_parse_null_term_string }, + { vod_string("language"), VOD_JSON_STRING, offsetof(media_sequence_t, tags.lang_str), media_set_parse_null_term_string }, + { vod_string("label"), VOD_JSON_STRING, offsetof(media_sequence_t, tags.label), media_set_parse_null_term_string }, + { vod_string("default"), VOD_JSON_BOOL, offsetof(media_sequence_t, tags.is_default), media_set_parse_bool }, { vod_string("bitrate"), VOD_JSON_OBJECT, offsetof(media_sequence_t, bitrate), media_set_parse_bitrate }, { vod_string("avg_bitrate"), VOD_JSON_OBJECT, offsetof(media_sequence_t, avg_bitrate), media_set_parse_bitrate }, { vod_null_string, 0, 0, NULL } @@ -150,6 +153,7 @@ static json_object_key_def_t media_closed_captions_params[] = { { vod_string("id"), VOD_JSON_STRING, MEDIA_CLOSED_CAPTIONS_PARAM_ID }, { vod_string("language"), VOD_JSON_STRING, MEDIA_CLOSED_CAPTIONS_PARAM_LANGUAGE }, { vod_string("label"), VOD_JSON_STRING, MEDIA_CLOSED_CAPTIONS_PARAM_LABEL }, + { vod_string("default"), VOD_JSON_BOOL, MEDIA_CLOSED_CAPTIONS_PARAM_DEFAULT }, { vod_null_string, 0, 0 } }; @@ -523,6 +527,16 @@ media_set_parse_bitrate( return VOD_OK; } +static vod_status_t +media_set_parse_bool( + void* ctx, + vod_json_value_t* value, + void* dest) +{ + *(bool_t*)dest = value->v.boolean; + return VOD_OK; +} + vod_status_t media_set_map_source( request_context_t* request_context, @@ -867,6 +881,15 @@ media_set_parse_closed_captions( cur_output->language.len = 0; } + if (params[MEDIA_CLOSED_CAPTIONS_PARAM_DEFAULT] != NULL) + { + cur_output->is_default = params[MEDIA_CLOSED_CAPTIONS_PARAM_DEFAULT]->v.boolean; + } + else + { + cur_output->is_default = -1; + } + cur_output++; } @@ -952,9 +975,10 @@ media_set_parse_sequences( cur_output->id.len = 0; cur_output->unparsed_clips = NULL; - cur_output->lang_str.len = 0; - cur_output->language = 0; - cur_output->label.len = 0; + cur_output->tags.lang_str.len = 0; + cur_output->tags.language = 0; + cur_output->tags.label.len = 0; + cur_output->tags.is_default = -1; cur_output->first_key_frame_offset = 0; cur_output->key_frame_durations = NULL; cur_output->drm_info = NULL; @@ -984,27 +1008,27 @@ media_set_parse_sequences( continue; } - if (cur_output->lang_str.len != 0) + if (cur_output->tags.lang_str.len != 0) { - if (cur_output->lang_str.len >= LANG_ISO639_3_LEN) + if (cur_output->tags.lang_str.len >= LANG_ISO639_3_LEN) { - cur_output->language = lang_parse_iso639_3_code(iso639_3_str_to_int(cur_output->lang_str.data)); - if (cur_output->language != 0) + cur_output->tags.language = lang_parse_iso639_3_code(iso639_3_str_to_int(cur_output->tags.lang_str.data)); + if (cur_output->tags.language != 0) { - cur_output->lang_str.data = (u_char *)lang_get_rfc_5646_name(cur_output->language); - cur_output->lang_str.len = ngx_strlen(cur_output->lang_str.data); + cur_output->tags.lang_str.data = (u_char *)lang_get_rfc_5646_name(cur_output->tags.language); + cur_output->tags.lang_str.len = ngx_strlen(cur_output->tags.lang_str.data); } } - if (cur_output->label.len == 0) + if (cur_output->tags.label.len == 0) { - if (cur_output->language != 0) + if (cur_output->tags.language != 0) { - lang_get_native_name(cur_output->language, &cur_output->label); + lang_get_native_name(cur_output->tags.language, &cur_output->tags.label); } else { - cur_output->label = cur_output->lang_str; + cur_output->tags.label = cur_output->tags.lang_str; } } } diff --git a/vod/mkv/mkv_format.c b/vod/mkv/mkv_format.c index 19cbe40f..ec02078b 100644 --- a/vod/mkv/mkv_format.c +++ b/vod/mkv/mkv_format.c @@ -773,16 +773,16 @@ mkv_metadata_parse( // inherit the sequence language and label sequence = parse_params->source->sequence; - if (sequence->label.len != 0) + if (sequence->tags.label.len != 0) { - track.name = sequence->label; + track.name = sequence->tags.label; // Note: it is not possible for the sequence to have a language without a label, // since a default label will be assigned according to the language - if (sequence->lang_str.len != 0) + if (sequence->tags.lang_str.len != 0) { - track.language = sequence->lang_str; - lang_id = sequence->language; + track.language = sequence->tags.lang_str; + lang_id = sequence->tags.language; } } @@ -865,19 +865,19 @@ mkv_metadata_parse( break; } - cur_track->media_info.lang_str = track.language; - cur_track->media_info.language = lang_id; + cur_track->media_info.tags.lang_str = track.language; + cur_track->media_info.tags.language = lang_id; if (track.name.len > 0) { - cur_track->media_info.label = track.name; + cur_track->media_info.tags.label = track.name; } else if (lang_id > 0) { - lang_get_native_name(lang_id, &cur_track->media_info.label); + lang_get_native_name(lang_id, &cur_track->media_info.tags.label); } else { - cur_track->media_info.label = track.language; + cur_track->media_info.tags.label = track.language; } cur_track->media_info.media_type = media_type; cur_track->media_info.codec_id = cur_codec->codec_id; diff --git a/vod/mp4/mp4_parser.c b/vod/mp4/mp4_parser.c index c21b8b28..9e862d6e 100644 --- a/vod/mp4/mp4_parser.c +++ b/vod/mp4/mp4_parser.c @@ -253,6 +253,7 @@ static vod_status_t mp4_parser_parse_hdlr_atom(atom_info_t* atom_info, metadata_parse_context_t* context) { const hdlr_atom_t* atom = (const hdlr_atom_t*)atom_info->ptr; + media_tags_t* tags; vod_str_t name; uint32_t type; @@ -280,7 +281,8 @@ mp4_parser_parse_hdlr_atom(atom_info_t* atom_info, metadata_parse_context_t* con } // parse the name / already set - if ((context->parse_params.parse_type & PARSE_FLAG_HDLR_NAME) == 0 || context->media_info.label.data != NULL) + tags = &context->media_info.tags; + if ((context->parse_params.parse_type & PARSE_FLAG_HDLR_NAME) == 0 || tags->label.data != NULL) { return VOD_OK; } @@ -303,19 +305,17 @@ mp4_parser_parse_hdlr_atom(atom_info_t* atom_info, metadata_parse_context_t* con return VOD_OK; } - context->media_info.label.data = vod_alloc( - context->request_context->pool, - name.len + 1); - if (context->media_info.label.data == NULL) + tags->label.data = vod_alloc(context->request_context->pool, name.len + 1); + if (tags->label.data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, context->request_context->log, 0, "mp4_parser_parse_hdlr_atom: vod_alloc failed"); return VOD_ALLOC_FAILED; } - vod_memcpy(context->media_info.label.data, name.data, name.len); - context->media_info.label.data[name.len] = '\0'; - context->media_info.label.len = name.len; + vod_memcpy(tags->label.data, name.data, name.len); + tags->label.data[name.len] = '\0'; + tags->label.len = name.len; return VOD_OK; } @@ -475,6 +475,7 @@ mp4_parser_parse_mdhd_atom(atom_info_t* atom_info, metadata_parse_context_t* con { const mdhd_atom_t* atom = (const mdhd_atom_t*)atom_info->ptr; const mdhd64_atom_t* atom64 = (const mdhd64_atom_t*)atom_info->ptr; + media_tags_t* tags; uint64_t duration; uint32_t timescale; uint16_t language; @@ -525,15 +526,16 @@ mp4_parser_parse_mdhd_atom(atom_info_t* atom_info, metadata_parse_context_t* con context->media_info.full_duration = duration; context->media_info.duration_millis = rescale_time(duration, timescale, 1000); - context->media_info.language = lang_parse_iso639_3_code(language); - if (context->media_info.language != 0) + tags = &context->media_info.tags; + tags->language = lang_parse_iso639_3_code(language); + if (tags->language != 0) { - context->media_info.lang_str.data = (u_char *)lang_get_rfc_5646_name(context->media_info.language); - context->media_info.lang_str.len = ngx_strlen(context->media_info.lang_str.data); + tags->lang_str.data = (u_char *)lang_get_rfc_5646_name(tags->language); + tags->lang_str.len = ngx_strlen(tags->lang_str.data); - if (context->media_info.label.len == 0) + if (tags->label.len == 0) { - lang_get_native_name(context->media_info.language, &context->media_info.label); + lang_get_native_name(tags->language, &tags->label); } } @@ -543,29 +545,32 @@ mp4_parser_parse_mdhd_atom(atom_info_t* atom_info, metadata_parse_context_t* con static vod_status_t mp4_parser_parse_udta_name_atom(atom_info_t* atom_info, metadata_parse_context_t* context) { + media_tags_t* tags; vod_str_t name; + name.data = (u_char*)atom_info->ptr; name.len = atom_info->size; // atom empty/non-existent or name already set - if (name.len == 0 || context->media_info.label.data != NULL) + tags = &context->media_info.tags; + if (name.len == 0 || tags->label.data != NULL) { return VOD_OK; } - context->media_info.label.data = vod_alloc( + tags->label.data = vod_alloc( context->request_context->pool, name.len + 1); - if (context->media_info.label.data == NULL) + if (tags->label.data == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, context->request_context->log, 0, "mp4_parser_parse_udta_name_atom: vod_alloc failed"); return VOD_ALLOC_FAILED; } - vod_memcpy(context->media_info.label.data, name.data, name.len); - context->media_info.label.data[name.len] = '\0'; - context->media_info.label.len = name.len; + vod_memcpy(tags->label.data, name.data, name.len); + tags->label.data[name.len] = '\0'; + tags->label.len = name.len; return VOD_OK; } @@ -2863,16 +2868,16 @@ mp4_parser_process_moov_atom_callback(void* ctx, atom_info_t* atom_info) // inherit the sequence language and label sequence = context->parse_params.source->sequence; - if (sequence->label.len != 0) + if (sequence->tags.label.len != 0) { - metadata_parse_context.media_info.label = sequence->label; + metadata_parse_context.media_info.tags.label = sequence->tags.label; // Note: it is not possible for the sequence to have a language without a label, // since a default label will be assigned according to the language - if (sequence->lang_str.len != 0) + if (sequence->tags.lang_str.len != 0) { - metadata_parse_context.media_info.lang_str = sequence->lang_str; - metadata_parse_context.media_info.language = sequence->language; + metadata_parse_context.media_info.tags.lang_str = sequence->tags.lang_str; + metadata_parse_context.media_info.tags.language = sequence->tags.language; } } @@ -2886,7 +2891,7 @@ mp4_parser_process_moov_atom_callback(void* ctx, atom_info_t* atom_info) // filter by language if (context->parse_params.langs_mask != NULL && metadata_parse_context.media_info.media_type == MEDIA_TYPE_AUDIO && - !vod_is_bit_set(context->parse_params.langs_mask, metadata_parse_context.media_info.language)) + !vod_is_bit_set(context->parse_params.langs_mask, metadata_parse_context.media_info.tags.language)) { return VOD_OK; } diff --git a/vod/mss/mss_packager.c b/vod/mss/mss_packager.c index 5c7ed92d..ccf0e5ed 100644 --- a/vod/mss/mss_packager.c +++ b/vod/mss/mss_packager.c @@ -188,12 +188,12 @@ mss_packager_compare_tracks(uintptr_t bitrate_threshold, const media_info_t* mi1 (mi1->u.video.height == mi2->u.video.height); } - if (mi1->label.len == 0 || mi2->label.len == 0) + if (mi1->tags.label.len == 0 || mi2->tags.label.len == 0) { return TRUE; } - return vod_str_equals(mi1->label, mi2->label); + return vod_str_equals(mi1->tags.label, mi2->tags.label); } static void @@ -255,7 +255,7 @@ mss_packager_remove_redundant_tracks( // prefer to remove a track that doesn't have a label, so that we won't lose a language // in case of multi language manifest - if (track1->media_info.label.len == 0 || track2->media_info.label.len != 0) + if (track1->media_info.tags.label.len == 0 || track2->media_info.tags.label.len != 0) { remove = track1; } @@ -419,7 +419,7 @@ mss_packager_build_manifest( { cur_track = *adaptation_set->first; - result_size += cur_track->media_info.label.len + cur_track->media_info.lang_str.len; + result_size += cur_track->media_info.tags.label.len + cur_track->media_info.tags.lang_str.len; } result_size += @@ -491,8 +491,8 @@ mss_packager_build_manifest( p = vod_sprintf(p, MSS_STREAM_INDEX_HEADER_LABEL, MSS_STREAM_TYPE_AUDIO, - &cur_track->media_info.label, - &cur_track->media_info.lang_str, + &cur_track->media_info.tags.label, + &cur_track->media_info.tags.lang_str, adaptation_set->count, segment_durations[adaptation_set->type].segment_count, MSS_STREAM_TYPE_AUDIO); @@ -513,8 +513,8 @@ mss_packager_build_manifest( cur_track = *adaptation_set->first; p = vod_sprintf(p, MSS_STREAM_INDEX_HEADER_SUBTITLE, - &cur_track->media_info.label, - &cur_track->media_info.lang_str, + &cur_track->media_info.tags.label, + &cur_track->media_info.tags.lang_str, adaptation_set->count, segment_durations[adaptation_set->type].segment_count); break; diff --git a/vod/subtitle/subtitle_format.c b/vod/subtitle/subtitle_format.c index 3dab36a7..0cbe2d81 100644 --- a/vod/subtitle/subtitle_format.c +++ b/vod/subtitle/subtitle_format.c @@ -66,11 +66,8 @@ subtitle_parse( media_base_metadata_t** result) { subtitle_base_metadata_t* metadata; - media_sequence_t* sequence; media_track_t* track; - language_id_t lang_id; - vod_str_t lang_str; - vod_str_t label; + media_tags_t tags; uint64_t duration; metadata = vod_alloc(request_context->pool, sizeof(*metadata)); @@ -90,24 +87,18 @@ subtitle_parse( } // inherit the sequence language and label - sequence = parse_params->source->sequence; - if (sequence->label.len != 0) - { - lang_str = sequence->lang_str; - lang_id = sequence->language; - label = sequence->label; - } - else + tags = parse_params->source->sequence->tags; + if (tags.label.len == 0) { // no language, assume English - ngx_str_set(&lang_str, "eng"); - lang_id = VOD_LANG_EN; - lang_get_native_name(lang_id, &label); + ngx_str_set(&tags.lang_str, "eng"); + tags.language = VOD_LANG_EN; + lang_get_native_name(tags.language, &tags.label); } // filter by language if (parse_params->langs_mask != NULL && - !vod_is_bit_set(parse_params->langs_mask, lang_id)) + !vod_is_bit_set(parse_params->langs_mask, tags.language)) { metadata->base.tracks.nelts = 0; return VOD_OK; @@ -143,9 +134,7 @@ subtitle_parse( track->media_info.duration = duration; track->media_info.full_duration = full_duration; track->media_info.duration_millis = duration; - track->media_info.lang_str = lang_str; - track->media_info.language = lang_id; - track->media_info.label = label; + track->media_info.tags = tags; track->media_info.bitrate = (source->len * 1000 * 8) / full_duration; metadata->source = *source;