GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; const char *opt; GF_Err e; u32 max_cache_duration, auto_switch_count; GF_DASHInitialSelectionMode first_select_mode; Bool keep_files, disable_switching; GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Connection request (%p) from terminal for %s\n", serv, url)); if (!mpdin|| !serv || !url) return GF_BAD_PARAM; mpdin->service = serv; mpdin->dash_io.udta = mpdin; mpdin->dash_io.delete_cache_file = mpdin_dash_io_delete_cache_file; mpdin->dash_io.create = mpdin_dash_io_create; mpdin->dash_io.del = mpdin_dash_io_del; mpdin->dash_io.abort = mpdin_dash_io_abort; mpdin->dash_io.setup_from_url = mpdin_dash_io_setup_from_url; mpdin->dash_io.set_range = mpdin_dash_io_set_range; mpdin->dash_io.init = mpdin_dash_io_init; mpdin->dash_io.run = mpdin_dash_io_run; mpdin->dash_io.get_url = mpdin_dash_io_get_url; mpdin->dash_io.get_cache_name = mpdin_dash_io_get_cache_name; mpdin->dash_io.get_mime = mpdin_dash_io_get_mime; mpdin->dash_io.get_bytes_per_sec = mpdin_dash_io_get_bytes_per_sec; mpdin->dash_io.get_total_size = mpdin_dash_io_get_total_size; mpdin->dash_io.on_dash_event = mpdin_dash_io_on_dash_event; max_cache_duration = 30; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MaxCacheDuration"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MaxCacheDuration", "30"); if (opt) max_cache_duration = atoi(opt); auto_switch_count = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount", "0"); if (opt) auto_switch_count = atoi(opt); keep_files = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "KeepFiles"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "KeepFiles", "no"); if (opt && !strcmp(opt, "yes")) keep_files = 1; disable_switching = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "DisableSwitching"); if (opt && !strcmp(opt, "yes")) disable_switching = 1; first_select_mode = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation"); if (!opt) { gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation", "minBandwidth"); opt = "minBandwidth"; } if (opt && !strcmp(opt, "maxBandwidth")) first_select_mode = GF_DASH_SELECT_BANDWIDTH_HIGHEST; else if (opt && !strcmp(opt, "minQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_LOWEST; else if (opt && !strcmp(opt, "maxQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_HIGHEST; else first_select_mode = GF_DASH_SELECT_BANDWIDTH_LOWEST; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage", "no"); mpdin->memory_storage = (opt && !strcmp(opt, "yes")) ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution", "yes"); mpdin->use_max_res = (!opt || !strcmp(opt, "yes")) ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching", "no"); mpdin->immediate_switch = (opt && !strcmp(opt, "yes")) ? 1 : 0; mpdin->in_seek = 0; mpdin->previous_start_range = -1; mpdin->dash = gf_dash_new(&mpdin->dash_io, max_cache_duration, auto_switch_count, keep_files, disable_switching, first_select_mode); if (!mpdin->dash) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot create DASH Client for %s\n", url)); gf_term_on_connect(mpdin->service, NULL, GF_IO_ERR); return GF_OK; } /*dash thread starts at the end of gf_dash_open */ e = gf_dash_open(mpdin->dash, url); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot initialize DASH Client for %s: %s\n", url, gf_error_to_string(e) )); gf_term_on_connect(mpdin->service, NULL, e); return GF_OK; } return GF_OK; }
GF_Err MPD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { GF_MPD_In *mpdin = (GF_MPD_In*) plug->priv; const char *opt; GF_Err e; s32 shift_utc_ms, debug_adaptation_set; u32 max_cache_duration, auto_switch_count, init_timeshift; Bool use_server_utc; GF_DASHInitialSelectionMode first_select_mode; Bool keep_files, disable_switching; GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[MPD_IN] Received Service Connection request (%p) from terminal for %s\n", serv, url)); if (!mpdin || !serv || !url) return GF_BAD_PARAM; mpdin->service = serv; mpdin->seek_request = -1; mpdin->dash_io.udta = mpdin; mpdin->dash_io.delete_cache_file = mpdin_dash_io_delete_cache_file; mpdin->dash_io.create = mpdin_dash_io_create; mpdin->dash_io.del = mpdin_dash_io_del; mpdin->dash_io.abort = mpdin_dash_io_abort; mpdin->dash_io.setup_from_url = mpdin_dash_io_setup_from_url; mpdin->dash_io.set_range = mpdin_dash_io_set_range; mpdin->dash_io.init = mpdin_dash_io_init; mpdin->dash_io.run = mpdin_dash_io_run; mpdin->dash_io.get_url = mpdin_dash_io_get_url; mpdin->dash_io.get_cache_name = mpdin_dash_io_get_cache_name; mpdin->dash_io.get_mime = mpdin_dash_io_get_mime; mpdin->dash_io.get_header_value = mpdin_dash_io_get_header_value; mpdin->dash_io.get_utc_start_time = mpdin_dash_io_get_utc_start_time; mpdin->dash_io.get_bytes_per_sec = mpdin_dash_io_get_bytes_per_sec; mpdin->dash_io.get_total_size = mpdin_dash_io_get_total_size; mpdin->dash_io.get_bytes_done = mpdin_dash_io_get_bytes_done; mpdin->dash_io.on_dash_event = mpdin_dash_io_on_dash_event; max_cache_duration = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "Network", "BufferLength"); if (opt) max_cache_duration = atoi(opt); auto_switch_count = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "AutoSwitchCount", "0"); if (opt) auto_switch_count = atoi(opt); keep_files = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "KeepFiles"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "KeepFiles", "no"); if (opt && !strcmp(opt, "yes")) keep_files = 1; disable_switching = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "DisableSwitching"); if (opt && !strcmp(opt, "yes")) disable_switching = 1; first_select_mode = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation"); if (!opt) { gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "StartRepresentation", "minBandwidth"); opt = "minBandwidth"; } if (opt && !strcmp(opt, "maxBandwidth")) first_select_mode = GF_DASH_SELECT_BANDWIDTH_HIGHEST; else if (opt && !strcmp(opt, "minQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_LOWEST; else if (opt && !strcmp(opt, "maxQuality")) first_select_mode = GF_DASH_SELECT_QUALITY_HIGHEST; else first_select_mode = GF_DASH_SELECT_BANDWIDTH_LOWEST; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "MemoryStorage", "yes"); mpdin->memory_storage = (opt && !strcmp(opt, "yes")) ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution"); if (!opt) { #if defined(_WIN32_WCE) || defined(GPAC_ANDROID) || defined(GPAC_IPHONE) opt = "yes"; #else opt = "no"; #endif gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "UseMaxResolution", opt); } mpdin->use_max_res = !strcmp(opt, "yes") ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "ImmediateSwitching", "no"); mpdin->immediate_switch = (opt && !strcmp(opt, "yes")) ? 1 : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "BufferingMode"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "BufferingMode", "minBuffer"); if (opt && !strcmp(opt, "segments")) mpdin->buffer_mode = MPDIN_BUFFER_SEGMENTS; else if (opt && !strcmp(opt, "none")) mpdin->buffer_mode = MPDIN_BUFFER_NONE; else mpdin->buffer_mode = MPDIN_BUFFER_MIN; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "LowLatency"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "LowLatency", "no"); if (opt && !strcmp(opt, "chunk") ) mpdin->use_low_latency = 1; else if (opt && !strcmp(opt, "always") ) mpdin->use_low_latency = 2; else mpdin->use_low_latency = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "AllowAbort"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "AllowAbort", "no"); mpdin->allow_http_abort = (opt && !strcmp(opt, "yes")) ? GF_TRUE : GF_FALSE; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "ShiftClock"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "ShiftClock", "0"); shift_utc_ms = opt ? atoi(opt) : 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "UseServerUTC"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "UseServerUTC", "yes"); use_server_utc = (opt && !strcmp(opt, "yes")) ? 1 : 0; mpdin->in_seek = 0; mpdin->previous_start_range = 0; init_timeshift = 0; opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "InitialTimeshift"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "InitialTimeshift", "0"); if (opt) init_timeshift = atoi(opt); //override all service callbacks mpdin->fn_connect_ack = serv->fn_connect_ack; serv->fn_connect_ack = mpdin_connect_ack; mpdin->fn_data_packet = serv->fn_data_packet; serv->fn_data_packet = mpdin_data_packet; mpdin->dash = gf_dash_new(&mpdin->dash_io, max_cache_duration, auto_switch_count, keep_files, disable_switching, first_select_mode, (mpdin->buffer_mode == MPDIN_BUFFER_SEGMENTS) ? 1 : 0, init_timeshift); if (!mpdin->dash) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot create DASH Client for %s\n", url)); mpdin->fn_connect_ack(mpdin->service, NULL, GF_IO_ERR); return GF_OK; } gf_dash_set_utc_shift(mpdin->dash, shift_utc_ms); gf_dash_enable_utc_drift_compensation(mpdin->dash, use_server_utc); opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "UseScreenResolution"); //default mode is no for the time being if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "UseScreenResolution", "no"); if (!opt || !strcmp(opt, "yes")) { GF_NetworkCommand com; memset(&com, 0, sizeof(GF_NetworkCommand)); com.base.command_type = GF_NET_SERVICE_MEDIA_CAP_QUERY; gf_service_command(serv, &com, GF_OK); if (com.mcaps.width && com.mcaps.height) { gf_dash_set_max_resolution(mpdin->dash, com.mcaps.width, com.mcaps.height, com.mcaps.display_bit_depth); } } opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "TimeBetween404"); if (opt) { gf_dash_set_min_timeout_between_404(mpdin->dash, atoi(opt)); } opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "SegmentExpirationThreshold"); if (opt) { gf_dash_set_segment_expiration_threshold(mpdin->dash, atoi(opt)); } opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "SwitchProbeCount"); if (opt) { gf_dash_set_switching_probe_count(mpdin->dash, atoi(opt)); } else { gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "SwitchProbeCount", "1"); } opt = gf_modules_get_option((GF_BaseInterface *)plug, "DASH", "DebugAdaptationSet"); if (!opt) gf_modules_set_option((GF_BaseInterface *)plug, "DASH", "DebugAdaptationSet", "-1"); debug_adaptation_set = opt ? atoi(opt) : -1; gf_dash_debug_group(mpdin->dash, debug_adaptation_set); /*dash thread starts at the end of gf_dash_open */ e = gf_dash_open(mpdin->dash, url); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("[MPD_IN] Error - cannot initialize DASH Client for %s: %s\n", url, gf_error_to_string(e) )); mpdin->fn_connect_ack(mpdin->service, NULL, e); return GF_OK; } return GF_OK; }