int add_cpl(opendcp_t *opendcp, pkl_t *pkl) { char uuid_s[40]; int i = pkl->cpl_count; strcpy(pkl->cpl[i].annotation, opendcp->xml.annotation); strcpy(pkl->cpl[i].issuer, opendcp->xml.issuer); strcpy(pkl->cpl[i].creator, opendcp->xml.creator); strcpy(pkl->cpl[i].title, opendcp->xml.title); strcpy(pkl->cpl[i].kind, opendcp->xml.kind); strcpy(pkl->cpl[i].rating, opendcp->xml.rating); strcpy(pkl->cpl[i].timestamp, opendcp->xml.timestamp); uuid_random(uuid_s); sprintf(pkl->cpl[i].uuid,"%.36s",uuid_s); /* Generate XML filename */ if ( !strcmp(opendcp->xml.basename,"") ) { sprintf(pkl->cpl[i].filename,"%.40s_cpl.xml",pkl->cpl[i].uuid); } else { sprintf(pkl->cpl[i].filename,"%.40s_cpl.xml",opendcp->xml.basename); } pkl->cpl_count++; return DCP_SUCCESS; }
int rtcp_init(iptv_rtcp_info_t * info) { uint32_t rnd; info->last_ts = 0; info->next_ts = 0; info->members = 2; info->senders = 1; info->last_received_sequence = 0; info->sequence_cycle = 1; info->source_ssrc = 0; info->average_packet_size = 52; // Fill my SSRC uuid_random((uint8_t *)&rnd, sizeof(random)); info->my_ssrc = rnd; srand48(rnd * 0x4232a9b9); return 0; }
int add_pkl(opendcp_t *opendcp) { char uuid_s[40]; int i = opendcp->pkl_count++; strcpy(opendcp->pkl[i].issuer, opendcp->xml.issuer); strcpy(opendcp->pkl[i].creator, opendcp->xml.creator); strcpy(opendcp->pkl[i].annotation, opendcp->xml.annotation); strcpy(opendcp->pkl[i].timestamp, opendcp->xml.timestamp); /* Generate UUIDs */ uuid_random(uuid_s); sprintf(opendcp->pkl[i].uuid,"%.36s",uuid_s); /* Generate XML filename */ if ( !strcmp(opendcp->xml.basename,"") ) { sprintf(opendcp->pkl[i].filename,"%.40s_pkl.xml",opendcp->pkl[i].uuid); } else { sprintf(opendcp->pkl[i].filename,"%.40s_pkl.xml",opendcp->xml.basename); } opendcp->pkl_count++; return DCP_SUCCESS; }
int main(int argc, char **argv) { int i; sigset_t set; #if ENABLE_MPEGTS uint32_t adapter_mask = 0; #endif int log_level = LOG_INFO; int log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG; const char *log_debug = NULL, *log_trace = NULL; gid_t gid = -1; uid_t uid = -1; char buf[512]; FILE *pidfile = NULL; static struct { void *thread_id; struct timeval tv; uint8_t ru[32]; } randseed; struct rlimit rl; extern int dvb_bouquets_parse; main_tid = pthread_self(); /* Setup global mutexes */ pthread_mutex_init(&fork_lock, NULL); pthread_mutex_init(&global_lock, NULL); pthread_mutex_init(&tasklet_lock, NULL); pthread_mutex_init(&atomic_lock, NULL); tvh_cond_init(&mtimer_cond); pthread_cond_init(>imer_cond, NULL); tvh_cond_init(&tasklet_cond); TAILQ_INIT(&tasklets); /* Defaults */ tvheadend_webui_port = 9981; tvheadend_webroot = NULL; tvheadend_htsp_port = 9982; tvheadend_htsp_port_extra = 0; __mdispatch_clock = getmonoclock(); __gdispatch_clock = time(NULL); /* Command line options */ int opt_help = 0, opt_version = 0, opt_fork = 0, opt_firstrun = 0, opt_stderr = 0, opt_nostderr = 0, opt_syslog = 0, opt_nosyslog = 0, opt_uidebug = 0, opt_abort = 0, opt_noacl = 0, opt_fileline = 0, opt_threadid = 0, opt_libav = 0, opt_ipv6 = 0, opt_nosatip = 0, opt_satip_rtsp = 0, #if ENABLE_TSFILE opt_tsfile_tuner = 0, #endif opt_dump = 0, opt_xspf = 0, opt_dbus = 0, opt_dbus_session = 0, opt_nobackup = 0, opt_nobat = 0, opt_subsystems = 0, opt_tprofile = 0; const char *opt_config = NULL, *opt_user = NULL, *opt_group = NULL, *opt_logpath = NULL, *opt_log_debug = NULL, *opt_log_trace = NULL, *opt_pidpath = "/var/run/tvheadend.pid", #if ENABLE_LINUXDVB *opt_dvb_adapters = NULL, #endif *opt_bindaddr = NULL, *opt_subscribe = NULL, *opt_user_agent = NULL, *opt_satip_bindaddr = NULL; static char *__opt_satip_xml[10]; str_list_t opt_satip_xml = { .max = 10, .num = 0, .str = __opt_satip_xml }; static char *__opt_satip_tsfile[10]; str_list_t opt_tsfile = { .max = 10, .num = 0, .str = __opt_satip_tsfile }; cmdline_opt_t cmdline_opts[] = { { 0, NULL, N_("Generic options"), OPT_BOOL, NULL }, { 'h', "help", N_("Show this page"), OPT_BOOL, &opt_help }, { 'v', "version", N_("Show version information"),OPT_BOOL, &opt_version }, { 0, NULL, N_("Service configuration"), OPT_BOOL, NULL }, { 'c', "config", N_("Alternate configuration path"), OPT_STR, &opt_config }, { 'B', "nobackup", N_("Don't backup configuration tree at upgrade"), OPT_BOOL, &opt_nobackup }, { 'f', "fork", N_("Fork and run as daemon"), OPT_BOOL, &opt_fork }, { 'u', "user", N_("Run as user"), OPT_STR, &opt_user }, { 'g', "group", N_("Run as group"), OPT_STR, &opt_group }, { 'p', "pid", N_("Alternate PID path"), OPT_STR, &opt_pidpath }, { 'C', "firstrun", N_("If no user account exists then create one with\n" "no username and no password. Use with care as\n" "it will allow world-wide administrative access\n" "to your Tvheadend installation until you create or edit\n" "the access control from within the Tvheadend web interface."), OPT_BOOL, &opt_firstrun }, #if ENABLE_DBUS_1 { 'U', "dbus", N_("Enable DBus"), OPT_BOOL, &opt_dbus }, { 'e', "dbus_session", N_("DBus - use the session message bus instead of the system one"), OPT_BOOL, &opt_dbus_session }, #endif #if ENABLE_LINUXDVB { 'a', "adapters", N_("Only use specified DVB adapters (comma-separated, -1 = none)"), OPT_STR, &opt_dvb_adapters }, #endif #if ENABLE_SATIP_SERVER { 0, "satip_bindaddr", N_("Specify bind address for SAT>IP server"), OPT_STR, &opt_satip_bindaddr }, { 0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n" "(default: -1 = disable, 0 = webconfig, standard port is 554)"), OPT_INT, &opt_satip_rtsp }, #endif #if ENABLE_SATIP_CLIENT { 0, "nosatip", N_("Disable SAT>IP client"), OPT_BOOL, &opt_nosatip }, { 0, "satip_xml", N_("URL with the SAT>IP server XML location"), OPT_STR_LIST, &opt_satip_xml }, #endif { 0, NULL, N_("Server connectivity"), OPT_BOOL, NULL }, { '6', "ipv6", N_("Listen on IPv6"), OPT_BOOL, &opt_ipv6 }, { 'b', "bindaddr", N_("Specify bind address"), OPT_STR, &opt_bindaddr}, { 0, "http_port", N_("Specify alternative http port"), OPT_INT, &tvheadend_webui_port }, { 0, "http_root", N_("Specify alternative http webroot"), OPT_STR, &tvheadend_webroot }, { 0, "htsp_port", N_("Specify alternative htsp port"), OPT_INT, &tvheadend_htsp_port }, { 0, "htsp_port2", N_("Specify extra htsp port"), OPT_INT, &tvheadend_htsp_port_extra }, { 0, "useragent", N_("Specify User-Agent header for the http client"), OPT_STR, &opt_user_agent }, { 0, "xspf", N_("Use XSPF playlist instead of M3U"), OPT_BOOL, &opt_xspf }, { 0, NULL, N_("Debug options"), OPT_BOOL, NULL }, { 'd', "stderr", N_("Enable debug on stderr"), OPT_BOOL, &opt_stderr }, { 'n', "nostderr", N_("Disable debug on stderr"), OPT_BOOL, &opt_nostderr }, { 's', "syslog", N_("Enable debug to syslog"), OPT_BOOL, &opt_syslog }, { 'S', "nosyslog", N_("Disable syslog (all messages)"), OPT_BOOL, &opt_nosyslog }, { 'l', "logfile", N_("Enable debug to file"), OPT_STR, &opt_logpath }, { 0, "debug", N_("Enable debug subsystems"), OPT_STR, &opt_log_debug }, #if ENABLE_TRACE { 0, "trace", N_("Enable trace subsystems"), OPT_STR, &opt_log_trace }, #endif { 0, "subsystems",N_("List subsystems"), OPT_BOOL, &opt_subsystems }, { 0, "fileline", N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline }, { 0, "threadid", N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid }, #if ENABLE_LIBAV { 0, "libav", N_("More verbose libav log"), OPT_BOOL, &opt_libav }, #endif { 0, "uidebug", N_("Enable web UI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug }, { 'A', "abort", N_("Immediately abort"), OPT_BOOL, &opt_abort }, { 'D', "dump", N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump }, { 0, "noacl", N_("Disable all access control checks"), OPT_BOOL, &opt_noacl }, { 0, "nobat", N_("Disable DVB bouquets"), OPT_BOOL, &opt_nobat }, { 'j', "join", N_("Subscribe to a service permanently"), OPT_STR, &opt_subscribe }, #if ENABLE_TSFILE || ENABLE_TSDEBUG { 0, NULL, N_("Testing options"), OPT_BOOL, NULL }, { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner }, { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile }, #endif { 0, "tprofile", N_("Gather timing statistics for the code"), OPT_BOOL, &opt_tprofile }, }; /* Get current directory */ tvheadend_cwd0 = dirname(tvh_strdupa(argv[0])); tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0)); /* Set locale */ setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); tvh_gettext_init(); /* make sure the timezone is set */ tzset(); /* Process command line */ for (i = 1; i < argc; i++) { /* Find option */ cmdline_opt_t *opt = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]); if (!opt) { show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), _("invalid option specified [%s]"), argv[i]); continue; } /* Process */ if (opt->type == OPT_BOOL) *((int*)opt->param) = 1; else if (++i == argc) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), _("option %s requires a value"), opt->lopt); else if (opt->type == OPT_INT) *((int*)opt->param) = atoi(argv[i]); else if (opt->type == OPT_STR_LIST) { str_list_t *strl = opt->param; if (strl->num < strl->max) strl->str[strl->num++] = argv[i]; } else *((char**)opt->param) = argv[i]; /* Stop processing */ if (opt_help) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL); if (opt_version) show_version(argv[0]); if (opt_subsystems) show_subsystems(argv[0]); } /* Additional cmdline processing */ if (opt_nobat) dvb_bouquets_parse = 0; #if ENABLE_LINUXDVB if (!opt_dvb_adapters) { adapter_mask = ~0; } else { char *p, *e; char *r = NULL; char *dvb_adapters = strdup(opt_dvb_adapters); adapter_mask = 0x0; i = 0; p = strtok_r(dvb_adapters, ",", &r); while (p) { int a = strtol(p, &e, 10); if (*e != 0 || a > 31) { fprintf(stderr, _("Invalid adapter number '%s'\n"), p); free(dvb_adapters); return 1; } i = 1; if (a < 0) adapter_mask = 0; else adapter_mask |= (1 << a); p = strtok_r(NULL, ",", &r); } free(dvb_adapters); if (!i) { fprintf(stderr, "%s", _("No adapters specified!\n")); return 1; } } #endif if (tvheadend_webroot) { char *tmp; if (*tvheadend_webroot == '/') tmp = strdup(tvheadend_webroot); else { tmp = malloc(strlen(tvheadend_webroot)+2); *tmp = '/'; strcpy(tmp+1, tvheadend_webroot); } if (tmp[strlen(tmp)-1] == '/') tmp[strlen(tmp)-1] = '\0'; if (tmp[0]) tvheadend_webroot = tmp; else free(tmp); } tvheadend_webui_debug = opt_uidebug; /* Setup logging */ if (isatty(2)) log_options |= TVHLOG_OPT_DECORATE; if (opt_stderr || opt_syslog || opt_logpath) { if (!opt_log_trace && !opt_log_debug) log_debug = "all"; log_level = LOG_DEBUG; if (opt_stderr) log_options |= TVHLOG_OPT_DBG_STDERR; if (opt_syslog) log_options |= TVHLOG_OPT_DBG_SYSLOG; if (opt_logpath) log_options |= TVHLOG_OPT_DBG_FILE; } if (opt_nostderr) log_options &= ~(TVHLOG_OPT_DECORATE|TVHLOG_OPT_STDERR|TVHLOG_OPT_DBG_STDERR); if (opt_nosyslog) log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG); if (opt_fileline) log_options |= TVHLOG_OPT_FILELINE; if (opt_threadid) log_options |= TVHLOG_OPT_THREAD; if (opt_libav) log_options |= TVHLOG_OPT_LIBAV; if (opt_log_trace) { log_level = LOG_TRACE; log_trace = opt_log_trace; } if (opt_log_debug) log_debug = opt_log_debug; tvhlog_init(log_level, log_options, opt_logpath); tvhlog_set_debug(log_debug); tvhlog_set_trace(log_trace); tvhinfo(LS_MAIN, "Log started"); signal(SIGPIPE, handle_sigpipe); // will be redundant later signal(SIGILL, handle_sigill); // see handler.. /* Set priviledges */ if((opt_fork && getuid() == 0) || opt_group || opt_user) { const char *homedir; struct group *grp = getgrnam(opt_group ?: "video"); struct passwd *pw = getpwnam(opt_user ?: "daemon"); if(grp != NULL) { gid = grp->gr_gid; } else { gid = 1; } if (pw != NULL) { if (getuid() != pw->pw_uid) { gid_t glist[16]; int gnum; gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist)); if (gnum > 0 && setgroups(gnum, glist)) { char buf[256] = ""; int i; for (i = 0; i < gnum; i++) snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf), ",%d", glist[i]); tvhlog(LOG_ALERT, LS_START, "setgroups(%s) failed, do you have permission?", buf+1); return 1; } } uid = pw->pw_uid; homedir = pw->pw_dir; setenv("HOME", homedir, 1); } else { uid = 1; } } tprofile_module_init(opt_tprofile); tprofile_init(>imer_profile, "gtimer"); tprofile_init(&mtimer_profile, "mtimer"); uuid_init(); idnode_boot(); config_boot(opt_config, gid, uid, opt_user_agent); tcp_server_preinit(opt_ipv6); http_server_init(opt_bindaddr); // bind to ports only htsp_init(opt_bindaddr); // bind to ports only satip_server_init(opt_satip_bindaddr, opt_satip_rtsp); // bind to ports only if (opt_fork) pidfile = tvh_fopen(opt_pidpath, "w+"); if (gid != -1 && (getgid() != gid) && setgid(gid)) { tvhlog(LOG_ALERT, LS_START, "setgid(%d) failed, do you have permission?", gid); return 1; } if (uid != -1 && (getuid() != uid) && setuid(uid)) { tvhlog(LOG_ALERT, LS_START, "setuid(%d) failed, do you have permission?", uid); return 1; } /* Daemonise */ if(opt_fork) { if(daemon(0, 0)) { exit(2); } if(pidfile != NULL) { fprintf(pidfile, "%d\n", getpid()); fclose(pidfile); } /* Make dumpable */ if (opt_dump) { if (chdir("/tmp")) tvhwarn(LS_START, "failed to change cwd to /tmp"); #ifdef PLATFORM_LINUX prctl(PR_SET_DUMPABLE, 1); #else tvhwarn(LS_START, "Coredumps not implemented on your platform"); #endif } umask(0); } memset(&rl, 0, sizeof(rl)); if (getrlimit(RLIMIT_STACK, &rl) || rl.rlim_cur < 2*1024*1024) { rlim_t rl2 = rl.rlim_cur; rl.rlim_cur = 2*1024*1024; if (setrlimit(RLIMIT_STACK, &rl)) { tvhlog(LOG_ALERT, LS_START, "too small stack size - %ld", (long)rl2); return 1; } } atomic_set(&tvheadend_running, 1); atomic_set(&tvheadend_mainloop, 0); /* Start log thread (must be done post fork) */ tvhlog_start(); /* Alter logging */ if (opt_fork) tvhlog_options &= ~TVHLOG_OPT_STDERR; if (!isatty(2)) tvhlog_options &= ~TVHLOG_OPT_DECORATE; /* Initialise clock */ pthread_mutex_lock(&global_lock); __mdispatch_clock = getmonoclock(); __gdispatch_clock = time(NULL); /* Signal handling */ sigfillset(&set); sigprocmask(SIG_BLOCK, &set, NULL); trap_init(argv[0]); /* SSL library init */ OPENSSL_config(NULL); SSL_load_error_strings(); SSL_library_init(); /* Rand seed */ randseed.thread_id = (void *)main_tid; gettimeofday(&randseed.tv, NULL); uuid_random(randseed.ru, sizeof(randseed.ru)); RAND_seed(&randseed, sizeof(randseed)); /* Initialise configuration */ tvhftrace(LS_MAIN, notify_init); tvhftrace(LS_MAIN, spawn_init); tvhftrace(LS_MAIN, idnode_init); tvhftrace(LS_MAIN, config_init, opt_nobackup == 0); /* Memoryinfo */ idclass_register(&memoryinfo_class); memoryinfo_register(&tasklet_memoryinfo); #if ENABLE_SLOW_MEMORYINFO memoryinfo_register(&htsmsg_memoryinfo); memoryinfo_register(&htsmsg_field_memoryinfo); #endif memoryinfo_register(&pkt_memoryinfo); memoryinfo_register(&pktbuf_memoryinfo); memoryinfo_register(&pktref_memoryinfo); /** * Initialize subsystems */ epg_in_load = 1; tvhthread_create(&mtimer_tick_tid, NULL, mtimer_tick_thread, NULL, "mtick"); tvhthread_create(&mtimer_tid, NULL, mtimer_thread, NULL, "mtimer"); tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL, "tasklet"); #if CONFIG_LINUXDVB_CA en50221_register_apps(); #endif tvhftrace(LS_MAIN, streaming_init); tvhftrace(LS_MAIN, tvh_hardware_init); tvhftrace(LS_MAIN, dbus_server_init, opt_dbus, opt_dbus_session); tvhftrace(LS_MAIN, intlconv_init); tvhftrace(LS_MAIN, api_init); tvhftrace(LS_MAIN, fsmonitor_init); tvhftrace(LS_MAIN, libav_init); tvhftrace(LS_MAIN, tvhtime_init); tvhftrace(LS_MAIN, codec_init); tvhftrace(LS_MAIN, profile_init); tvhftrace(LS_MAIN, imagecache_init); tvhftrace(LS_MAIN, http_client_init); tvhftrace(LS_MAIN, esfilter_init); tvhftrace(LS_MAIN, bouquet_init); tvhftrace(LS_MAIN, service_init); tvhftrace(LS_MAIN, descrambler_init); tvhftrace(LS_MAIN, dvb_init); #if ENABLE_MPEGTS tvhftrace(LS_MAIN, mpegts_init, adapter_mask, opt_nosatip, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner); #endif tvhftrace(LS_MAIN, channel_init); tvhftrace(LS_MAIN, bouquet_service_resolve); tvhftrace(LS_MAIN, subscription_init); tvhftrace(LS_MAIN, dvr_config_init); tvhftrace(LS_MAIN, access_init, opt_firstrun, opt_noacl); #if ENABLE_TIMESHIFT tvhftrace(LS_MAIN, timeshift_init); #endif tvhftrace(LS_MAIN, tcp_server_init); tvhftrace(LS_MAIN, webui_init, opt_xspf); #if ENABLE_UPNP tvhftrace(LS_MAIN, upnp_server_init, opt_bindaddr); #endif tvhftrace(LS_MAIN, service_mapper_init); tvhftrace(LS_MAIN, epggrab_init); tvhftrace(LS_MAIN, epg_init); tvhftrace(LS_MAIN, dvr_init); tvhftrace(LS_MAIN, dbus_server_start); tvhftrace(LS_MAIN, http_server_register); tvhftrace(LS_MAIN, satip_server_register); tvhftrace(LS_MAIN, htsp_register); if(opt_subscribe != NULL) subscription_dummy_join(opt_subscribe, 1); tvhftrace(LS_MAIN, avahi_init); tvhftrace(LS_MAIN, bonjour_init); tvhftrace(LS_MAIN, epg_updated); // cleanup now all prev ref's should have been created epg_in_load = 0; pthread_mutex_unlock(&global_lock); tvhftrace(LS_MAIN, watchdog_init); /** * Wait for SIGTERM / SIGINT, but only in this thread */ sigemptyset(&set); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); signal(SIGTERM, doexit); signal(SIGINT, doexit); pthread_sigmask(SIG_UNBLOCK, &set, NULL); tvhlog(LOG_NOTICE, LS_START, "HTS Tvheadend version %s started, " "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s", tvheadend_version, getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)), hts_settings_get_root()); if(opt_abort) abort(); pthread_mutex_lock(&global_lock); tvheadend_mainloop = 1; tvh_cond_signal(&mtimer_cond, 0); pthread_mutex_unlock(&global_lock); mainloop(); pthread_mutex_lock(&global_lock); tvh_cond_signal(&mtimer_cond, 0); pthread_mutex_unlock(&global_lock); pthread_join(mtimer_tid, NULL); #if ENABLE_DBUS_1 tvhftrace(LS_MAIN, dbus_server_done); #endif #if ENABLE_UPNP tvhftrace(LS_MAIN, upnp_server_done); #endif tvhftrace(LS_MAIN, satip_server_done); tvhftrace(LS_MAIN, htsp_done); tvhftrace(LS_MAIN, http_server_done); tvhftrace(LS_MAIN, webui_done); tvhftrace(LS_MAIN, fsmonitor_done); tvhftrace(LS_MAIN, http_client_done); tvhftrace(LS_MAIN, tcp_server_done); // Note: the locking is obviously a bit redundant, but without // we need to disable the gtimer_arm call in epg_save() pthread_mutex_lock(&global_lock); tvhftrace(LS_MAIN, epg_save); #if ENABLE_TIMESHIFT tvhftrace(LS_MAIN, timeshift_term); #endif pthread_mutex_unlock(&global_lock); tvhftrace(LS_MAIN, epggrab_done); #if ENABLE_MPEGTS tvhftrace(LS_MAIN, mpegts_done); #endif tvhftrace(LS_MAIN, dvr_done); tvhftrace(LS_MAIN, descrambler_done); tvhftrace(LS_MAIN, service_mapper_done); tvhftrace(LS_MAIN, service_done); tvhftrace(LS_MAIN, channel_done); tvhftrace(LS_MAIN, bouquet_done); tvhftrace(LS_MAIN, subscription_done); tvhftrace(LS_MAIN, access_done); tvhftrace(LS_MAIN, epg_done); tvhftrace(LS_MAIN, avahi_done); tvhftrace(LS_MAIN, bonjour_done); tvhftrace(LS_MAIN, imagecache_done); tvhftrace(LS_MAIN, lang_code_done); tvhftrace(LS_MAIN, api_done); tvhtrace(LS_MAIN, "tasklet enter"); tvh_cond_signal(&tasklet_cond, 0); pthread_join(tasklet_tid, NULL); tvhtrace(LS_MAIN, "tasklet thread end"); tasklet_flush(); tvhtrace(LS_MAIN, "tasklet leave"); tvhtrace(LS_MAIN, "mtimer tick thread join enter"); pthread_join(mtimer_tick_tid, NULL); tvhtrace(LS_MAIN, "mtimer tick thread join leave"); tvhftrace(LS_MAIN, dvb_done); tvhftrace(LS_MAIN, esfilter_done); tvhftrace(LS_MAIN, profile_done); tvhftrace(LS_MAIN, codec_done); tvhftrace(LS_MAIN, libav_done); tvhftrace(LS_MAIN, intlconv_done); tvhftrace(LS_MAIN, urlparse_done); tvhftrace(LS_MAIN, streaming_done); tvhftrace(LS_MAIN, idnode_done); tvhftrace(LS_MAIN, notify_done); tvhftrace(LS_MAIN, spawn_done); tprofile_done(>imer_profile); tprofile_done(&mtimer_profile); tprofile_module_done(); tvhlog(LOG_NOTICE, LS_STOP, "Exiting HTS Tvheadend"); tvhlog_end(); tvhftrace(LS_MAIN, config_done); tvhftrace(LS_MAIN, hts_settings_done); if(opt_fork) unlink(opt_pidpath); /* OpenSSL - welcome to the "cleanup" hell */ ENGINE_cleanup(); RAND_cleanup(); CRYPTO_cleanup_all_ex_data(); EVP_cleanup(); CONF_modules_free(); #if !defined(OPENSSL_NO_COMP) COMP_zlib_cleanup(); #endif ERR_remove_state(0); ERR_free_strings(); #if !defined(OPENSSL_NO_COMP) && OPENSSL_VERSION_NUMBER < 0x1010006f sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); #endif /* end of OpenSSL cleanup code */ #if ENABLE_DBUS_1 extern void dbus_shutdown(void); if (opt_dbus) dbus_shutdown(); #endif tvh_gettext_done(); free((char *)tvheadend_webroot); tvhftrace(LS_MAIN, watchdog_done); return 0; } /** * */ void tvh_str_set(char **strp, const char *src) { free(*strp); *strp = src ? strdup(src) : NULL; } /** * */ int tvh_str_update(char **strp, const char *src) { if(src == NULL) return 0; free(*strp); *strp = strdup(src); return 1; } /** * */ void scopedunlock(pthread_mutex_t **mtxp) { pthread_mutex_unlock(*mtxp); }
int add_reel(opendcp_t *opendcp, cpl_t *cpl, asset_list_t reel) { int result; int x,r; FILE *fp; char *filename; asset_t asset; struct stat st; char uuid_s[40]; dcp_log(LOG_INFO,"Adding Reel"); r = cpl->reel_count; /* add reel uuid */ uuid_random(uuid_s); sprintf(cpl->reel[r].uuid,"%.36s",uuid_s); /* parse argument and read asset information */ for (x=0;x<reel.asset_count;x++) { filename=reel.asset_list[x].filename; init_asset(&asset); sprintf(asset.filename,"%s",filename); sprintf(asset.annotation,"%s",basename(filename)); /* check if file exists */ if ((fp = fopen(filename, "r")) == NULL) { dcp_log(LOG_ERROR,"add_reel: Could not open file: %s",filename); return DCP_FILE_OPEN_ERROR; } else { fclose (fp); } /* get file size */ stat(filename, &st); sprintf(asset.size,"%"PRIu64, st.st_size); /* read asset information */ dcp_log(LOG_INFO,"add_reel: Reading %s asset information",filename); result = read_asset_info(&asset); if (result == DCP_FATAL) { dcp_log(LOG_ERROR,"%s is not a proper essence file",filename); return DCP_INVALID_ESSENCE; } if (x == 0) { opendcp->ns = asset.xml_ns; dcp_log(LOG_DEBUG,"add_reel: Label type detected: %d",opendcp->ns); } else { if (opendcp->ns != asset.xml_ns) { dcp_log(LOG_ERROR,"Warning DCP specification mismatch in assets. Please make sure all assets are MXF Interop or SMPTE"); return DCP_SPECIFCATION_MISMATCH; } } /* force aspect ratio, if specified */ if (strcmp(opendcp->xml.aspect_ratio,"") ) { sprintf(asset.aspect_ratio,"%s",opendcp->xml.aspect_ratio); } /* Set duration, if specified */ if (opendcp->duration) { if (opendcp->duration<asset.duration) { asset.duration = opendcp->duration; } else { dcp_log(LOG_WARN,"Desired duration %d cannot be greater than assset duration %d, ignoring value",opendcp->duration,asset.duration); } } /* Set entry point, if specified */ if (opendcp->entry_point) { if (opendcp->entry_point<asset.duration) { asset.entry_point = opendcp->entry_point; } else { dcp_log(LOG_WARN,"Desired entry point %d cannot be greater than assset duration %d, ignoring value",opendcp->entry_point,asset.duration); } } /* calculate digest */ calculate_digest(filename,asset.digest); /* get asset type */ result = get_asset_type(asset); /* add asset to cpl */ cpl->reel[r].asset[x] = asset; cpl->reel[r].asset_count++; } cpl->reel_count++; return DCP_SUCCESS; }
int write_assetmap(opendcp_t *opendcp) { xmlIndentTreeOutput = 1; xmlDocPtr doc; xmlTextWriterPtr xml; int a,c,r,rc; char uuid_s[40]; cpl_t cpl; reel_t reel; /* generate assetmap UUID */ uuid_random(uuid_s); dcp_log(LOG_INFO,"Writing ASSETMAP file %.256s",opendcp->assetmap.filename); /* create XML document */ xml = xmlNewTextWriterDoc(&doc,0); /* assetmap XML Start */ rc = xmlTextWriterStartDocument(xml, NULL, XML_ENCODING, NULL); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterStartDocument failed"); return DCP_FATAL; } xmlTextWriterStartElement(xml, BAD_CAST "AssetMap"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns", BAD_CAST NS_AM[opendcp->ns]); /* assetmap attributes */ xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",uuid_s); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Creator","%s",opendcp->xml.creator); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeCount","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "IssueDate","%s",opendcp->xml.timestamp); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Issuer","%s",opendcp->xml.issuer); xmlTextWriterStartElement(xml, BAD_CAST "AssetList"); dcp_log(LOG_INFO,"Writing ASSETMAP PKL"); /* PKL */ xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",opendcp->pkl[0].uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "PackingList","%s","true"); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(opendcp->pkl[0].filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",opendcp->pkl[0].size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end pkl asset */ dcp_log(LOG_INFO,"Writing ASSETMAP CPLs"); /* CPL */ for (c=0;c<opendcp->pkl[0].cpl_count;c++) { cpl = opendcp->pkl[0].cpl[c]; xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",cpl.uuid); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(cpl.filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",cpl.size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end cpl asset */ /* assets(s) start */ for (r=0;r<cpl.reel_count;r++) { reel = cpl.reel[r]; for (a=0;a<reel.asset_count;a++) { asset_t asset = reel.asset[a]; xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",asset.uuid); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(asset.filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",asset.size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end cpl asset */ } } } xmlTextWriterEndElement(xml); /* end assetlist */ xmlTextWriterEndElement(xml); /* end assetmap */ rc = xmlTextWriterEndDocument(xml); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterEndDocument failed %s",opendcp->assetmap.filename); return DCP_FATAL; } xmlFreeTextWriter(xml); xmlSaveFormatFile(opendcp->assetmap.filename, doc, 1); xmlFreeDoc(doc); return DCP_SUCCESS; }